-
- Notifications
You must be signed in to change notification settings - Fork 8
array_key_last: faster implementation #1
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
| The issue is that this mutates the internal pointer, which is something that shouldn't happen. |
| I extend the gist example. And look like a same behavior like a foreach. Unchanged internal pointer. I tested on php 5.4-7.2 EDIT Add reference for array to anonymous function, it is same results. <?php function timer() { static $start; if ($start === null) { $start = microtime(true); } else { $diff = microtime(true) - $start; $start = null; echo $diff . PHP_EOL; } } function meassure(callable $callback, $message = '') { if ($message) { echo $message . PHP_EOL; } timer(); for ($i = 0; $i < 100000; ++$i) { $callback(); } timer(); } function showKey(& $array) { echo key($array) . PHP_EOL; } function internalPointerToThirdPosition(& $array) { reset($array); next($array); next($array); } function array_key_first_symfony(array $array) { foreach ($array as $key => $value) { return $key; } } function array_key_first(array $array) { reset($array); return key($array); } function array_key_last_symfony(array $array) { $key = null; foreach ($array as $key => $value); return $key; } function array_key_last(array $array) { end($array); return key($array); } $array = ['foo' => null] + range(0, 100) + ['bar' => '1']; echo PHP_EOL; internalPointerToThirdPosition($array); showKey($array); meassure(function () use (&$array) { if (array_key_first_symfony($array) !== 'foo') { throw new \Exception('failed'); } }, 'array_key_first_symfony'); showKey($array); echo PHP_EOL; internalPointerToThirdPosition($array); showKey($array); meassure(function () use (&$array) { if (array_key_first($array) !== 'foo') { throw new \Exception('failed'); } }, 'array_key_first'); showKey($array); echo PHP_EOL; internalPointerToThirdPosition($array); showKey($array); meassure(function () use (&$array) { if (array_key_last_symfony($array) !== 'bar') { throw new \Exception('failed'); } }, 'array_key_last_symfony'); showKey($array); echo PHP_EOL; internalPointerToThirdPosition($array); showKey($array); meassure(function () use (&$array) { if (array_key_last($array) !== 'bar') { throw new \Exception('failed'); } }, 'array_key_last'); showKey($array); |
| This change internal pointer: function array_key_last(array &$array) { end($array); return key($array); } |
| Indeed you're right sorry I read too fast. |
| New implementation is every time the faster. Here are results: And benchmark code: <?php function timer() { static $start; if ($start === null) { $start = microtime(true); } else { $diff = microtime(true) - $start; $start = null; echo $diff . PHP_EOL; } } function meassure(callable $callback, $message = '') { if ($message) { echo $message . ': '; } timer(); for ($i = 0; $i < 10000; ++$i) { $callback(); } timer(); } function array_key_last_symfony(array $array) { $key = null; foreach ($array as $key => $value) { ; } return $key; } function array_key_last(array $array) { end($array); return key($array); } $arraySize = [10, 20, 50, 100, 200, 500, 1000, 2000, 5000, 10000]; foreach ($arraySize as $size) { echo PHP_EOL . PHP_EOL; $array = ['foo' => null] + range(0, $size) + ['bar' => '1']; echo sprintf('Array size: %s', $size) . PHP_EOL; meassure(function () use ($array) { if (array_key_last_symfony($array) !== 'bar') { throw new \Exception('failed'); } }, 'array_key_last_symfony'); meassure(function () use ($array) { if (array_key_last($array) !== 'bar') { throw new \Exception('failed'); } }, 'array_key_last'); } |
| Pull request moved to main repository |
This PR was merged into the 1.9-dev branch. Discussion ---------- array_key_last: improving performance First PR is [here](symfony/polyfill-php73#1), where was discussion. Q: The issue is that this mutates the internal pointer. A: created [benchmark](symfony/polyfill-php73#1 (comment)) and implementation does not change internal pointer. Q: about performance for small vs big arrays A: look like implementation is [every time faster](symfony/polyfill-php73#1 (comment)) This implementation is approx twice faster than cycle foreach. Benchmark is [on my gist](https://gist.github.com/h4kuna/6353ce99bd45b9c5fcdf49ef6d0e3da8). Results on my machine. ``` array_key_last_symfony 0.1387140750885 array_key_last 0.055586814880371 ``` Commits ------- 77aa2ff array_key_last: improving performance
Hello
if I right measured, here is faster implementation for function array_key_last.
I move internal pointer of array.
Benchmark is on my gist.
Results on my machine.