-
Notifications
You must be signed in to change notification settings - Fork 8k
Faster array initialization #17002
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
Faster array initialization #17002
Conversation
With opache, arrays are marked as immutable. Without opcache, nested arrays need refcounting, and thus require a loop over its elements.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think this may be a good idea.
callgrind shows ~0.5% improvement on wordpress, but there is no visible real-time difference. The complication and VM size increase is not significant.
ct_eval and sccp should be cleaned up.
JIT support is not required.
&& throw_op->result_type & (IS_TMP_VAR|IS_VAR) | ||
&& throw_op->opcode != ZEND_ADD_ARRAY_ELEMENT | ||
&& throw_op->opcode != ZEND_ADD_ARRAY_UNPACK | ||
&& throw_op->opcode != ZEND_ARRAY_SET_PLACEHOLDER |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I would name this ZEND_SET_ARRAY_ELEMET
, but this is just a preference.
AFAIR Authoritative composer autoloading depends on a big compile time known static array, which then is used for locating the files. this might be a use-case worth measuring, as its a vital part in every application (bootstrap overhead of a minimal app) |
@staabm Comp-time arrays don't benefit, only array initializers with some dynamic values. |
We can make some assumptions about the value of the fields.
39143f8
to
df615f2
Compare
This performed better for Symfony Demo in my benchmarks, possibly due to better instruction caching.
I think I've squeezed all I can out of this, but still don't get a measurable improvement for real applications. Some other opinions would be nice, @bwoebi? |
@iluuu1994 I consider the optimization valid, but the impact low. I mean, how often do you actually create a larger array with expressions? And how big are these? From my experience mixed array initializers containing expressions tend to be mostly small arrays where the impact is low. The other problem is, probably, that before this patch, the fastest way to write arrays where you have many constants and few expressions, is to initialize the array with the constant part, then assign a few values explicitly. So, probably, where this patch has a measurable impact, users probably have rewritten their code in a way that is currently fastest, but won't be able to harness the optimizations introduced by this patch. Also, copying arData is redundant if it's packed and nothing pre-initialized. Like in the common Does it change the real world benchmarks at all if you introduce a dedicated opcode (ZEND_INITIALIZE_SMALL_PACKED_ARRAY, op1, op2) for just that case of 1 or 2 packed values? (and probably also use ZEND_INITIALIZE_SMALL_PACKED_ARRAY + ADD_ARRAY_ELEMENT for 3 packed values) |
@bwoebi Thanks for your evaluation. It's particularly well suited for things like: return [
'username' => $username,
'password' => $password,
'date_of_birth' => $dateOfBirth,
]; But yeah, I think the improvement is too small for the added complexity.
One packed value likely won't make a big difference, as this is already possible in one opcode ( |
I have abandoned this idea for now. We might still consider an opcode for creating array pairs. |
Small idea I had. Instead of constructing arrays with dynamic elements from scratch, clone a template from a constant though
ARRAY_DUP
, and then populate the missing element slots throughARRAY_SET_PLACEHOLDER
by a byte-offset into the array data stored inop2.num
. This optimization is only applied when opcache is enabled, because in that case the array template literal is immutable. This allows for a fast clone usingmemcpy
without walking the array for refcounting.Benchmarks
All benchmarks are called with:
Unsurprisingly, the biggest benefits can be achieved when most of the array elements are constant. Using constant keys in hashed arrays is also beneficial, since the keys are pre-filled. That said, I did not observe any significant improvements in real applications like Symfony Demo.
If we plan for merge this, type inference and SCCP should be improved. Currently, during compilation, placeholders are set to
null
. This makes it hard to understand whether these are real constants or placeholders that are later removed. We should use some other placeholder value that can be easily distinguished, either_IS_ERROR
or some new one. It will also be possible to eliminateARRAY_SET_PLACEHOLDER
opcodes ifop1
is discovered during SCCP.Implement JIT supportNot needed according to Dmitry