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

array_merge() being used on looping => docs #138

Closed
rentalhost opened this Issue Feb 13, 2017 · 10 comments

Comments

Projects
None yet
3 participants
@rentalhost
Copy link
Collaborator

rentalhost commented Feb 13, 2017

EDIT: needs to be documented here


I'm getting the reporting about using of array_merge() in loopings. My question is: what is the best way to not do that?

For instance: the code below stores some data from $user, that is an array of int.

$dupesIds = [];

foreach ($users as $user) {
    // ...
    $dupesIds = array_merge($dupesIds, $user->some_ids_array);
}
@kalessil

This comment has been minimized.

Copy link
Owner

kalessil commented Feb 13, 2017

Itshould be like this (saves looooots of memory allocation rounds, what leads to better performace as well)

$dupesIds = [];
foreach ($users as $user) {
    $dupesIds []= $user->some_ids_array;
}
$dupesIds = call_user_func_array('array_merge', $dupesIds)
@rentalhost

This comment has been minimized.

Copy link
Collaborator Author

rentalhost commented Feb 13, 2017

I do some tests, and the problem is not the memory (in this case, inside looping is better), but the CPU usage (it's a looooooooot worse).

Can you put your example on plugin (description)? It can help to users to follow it. Currently description is very unclear about other options. 😄

From plugin: Analyzes loops and reports if any resource-greedy array functions are being used (e.g. 'array_merge(...)').


Some benchmarking (7.000 iterations):

Case 1: with array_merge() on looping (http://pastebin.com/acEdVLSE).
Note: over 7.000 iterations is impossible run this code on my PC. haha

Time: 953.20ms
Memory: 8.00Mb
Mem. Peak: 12.00Mb

Case 2: with array_merge() outside the looping with call_user_func_array() - following your example (http://pastebin.com/QAqSDfEK).

Time: 3.00ms (-99.68% compared to case 1)
Memory: 2.00Mb (-75.00%)
Mem. Peak: 6.00Mb (-50.00%)


Extra case: with array_merge() outside the looping with call_user_func_array() - 250.000 iterations.
You can note that the memory usage is high, because you are storing a big array, instead of merging it in each looping, but it is more fast than first case.

Time: 112.80ms
Memory: 12.00Mb
Mem. Peak: 82.00Mb

@kalessil

This comment has been minimized.

Copy link
Owner

kalessil commented Feb 13, 2017

You also can try prefixing call_user_func_array with root NS: '\call_user_func_array(...)' ;)

@kalessil

This comment has been minimized.

Copy link
Owner

kalessil commented Feb 13, 2017

It can gain some extra execution time benefits in PHP7+

@rentalhost

This comment has been minimized.

Copy link
Collaborator Author

rentalhost commented Feb 13, 2017

No changes. I guess that it's a micro-micro optimization haha. Running on PHP 7.1.

\count(\call_user_func_array('array_merge', $idsArray));

Time: 112.80ms (same time)
Memory: 12.00Mb (same memory)
Mem. Peak: 82.00Mb (same memory peak)

@kalessil

This comment has been minimized.

Copy link
Owner

kalessil commented Feb 13, 2017

Okay, I think opcache is not used during the benchmarking. In the case opcache does pretty neat optimizations )

@kalessil kalessil changed the title array_merge() being used on looping array_merge() being used on looping => docs Feb 14, 2017

@kalessil kalessil added this to the 2.3.3 milestone Feb 14, 2017

@kalessil kalessil removed their assignment Feb 17, 2017

@kalessil kalessil modified the milestones: 2.3.4, 2.3.3 Feb 20, 2017

@kalessil

This comment has been minimized.

Copy link
Owner

kalessil commented Feb 23, 2017

Documented here, feedback is welcome.

@kalessil kalessil closed this Feb 23, 2017

@rieschl

This comment has been minimized.

Copy link

rieschl commented May 23, 2017

Sorry for posting in a closed issue but I think it's worth mentioning that PHP will throw a Fatal error (ArgumentCountError) if the foreach loop isn't executed at least once:

array_merge() expects at least 1 parameter, 0 given

something like

if (!empty($options) {
    $options = array_merge(...$options);
}

could be inserted

@kalessil

This comment has been minimized.

Copy link
Owner

kalessil commented May 23, 2017

No problems, it's pretty handy actually as the context already here - I'll update the docs.

    $options = [[]]; // the inner array prevents errors when invoking the array_merge after loop
    ...

kalessil added a commit that referenced this issue May 23, 2017

@kalessil

This comment has been minimized.

Copy link
Owner

kalessil commented May 23, 2017

@rieschl : I updated the documentation, thanks for reporting =)

voku added a commit to voku/Arrayy that referenced this issue Nov 5, 2018

[+]: use "infection" to test the tests :)
[+]: optimize performance from "array_merge()" -> kalessil/phpinspectionsea#138
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.