Skip to content
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

[5.7] Inline Arr::pluck() in data_get() #25938

Merged
merged 1 commit into from
Oct 5, 2018
Merged

[5.7] Inline Arr::pluck() in data_get() #25938

merged 1 commit into from
Oct 5, 2018

Conversation

vlakoff
Copy link
Contributor

@vlakoff vlakoff commented Oct 4, 2018

Follow-up to #25892. Cherry-picked from it a small code inlining.

  • avoids "cross-calling" between these two methods
  • 10~20% performance boost

I think this way the code is clearer (shows the recursivity) and safer (more encapsulated, avoids interconnection).

The performance benefit can be interesting too, as the function appears to be O(n) depending on the size of input data. So with thousands of users, the function can become slow; with this change the function is still slow, but with a small improvement worth picking.

Bench on PHP 7.2.10:

0.71760010719299
0.63960003852844

89.130426837635

$array = array_fill(0, 500, ['name' => 'taylor']);
$nb = 1000;

$t1 = microtime(true);
for ($ii = $nb; $ii--; ) {
    data_get($array, '*.name');
}
$t2 = microtime(true);
for ($ii = $nb; $ii--; ) {
    data_get_2($array, '*.name');
}
$t3 = microtime(true);

echo $t2 - $t1;
echo '<br>';
echo $t3 - $t2;
echo '<br><br>';
echo $t2 - $t1 == 0 ? 'N/A' : ($t3 - $t2) * 100 / ($t2 - $t1);
function data_get_2($target, $key, $default = null)
{
    if (is_null($key)) {
        return $target;
    }

    $key = is_array($key) ? $key : explode('.', $key);

    while (! is_null($segment = array_shift($key))) {
        if ($segment === '*') {
            if ($target instanceof Collection) {
                $target = $target->all();
            } elseif (! is_array($target)) {
                return value($default);
            }

            $result = [];

            foreach ($target as $item) {
                $result[] = data_get_2($item, $key);
            }

            return in_array('*', $key) ? Arr::collapse($result) : $result;
        }

        if (Arr::accessible($target) && Arr::exists($target, $segment)) {
            $target = $target[$segment];
        } elseif (is_object($target) && isset($target->{$segment})) {
            $target = $target->{$segment};
        } else {
            return value($default);
        }
    }

    return $target;
}

- avoids "cross-calling" between these two methods
- 10~20% performance boost
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants