-
-
Notifications
You must be signed in to change notification settings - Fork 571
Use foreach
over slower functions array_map()
and Utils::map()
#712
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
Use foreach
over slower functions array_map()
and Utils::map()
#712
Conversation
Did you have a chance to check how much it will improve performance? My concern about this PR is that there are also other utility methods that will be harder to convert. Also, I mainly had this method for consistency of ordering of arguments of |
I lazily assumed it makes things faster, and am pretty sure it does. It makes sense for me to have Utils in place when translating from JS. Once the conversion is done and a level of maturity is achieved, rewriting in idiomatic PHP and optimizing performance is a logical next step. I think every PHP developer is familiar with foreach and array_map, so this should not impact readability in a negative way. We can tackle the other Utils later. |
Another thing to keep in mind is that In general, I don't feel like this is a valuable change. I can be proven wrong with some benchmarks though. |
I recall that part of the reason for using |
I totally agree with that sentiment. However, in PHP this kind of flexibility comes with a runtime cost. Manual monomorphization can be tedious, but PHPStan and the test suite should have us covered here. I will try and produce some benchmark results. |
# Conflicts: # src/Error/Error.php # src/Error/FormattedError.php # src/Executor/Promise/Adapter/ReactPromiseAdapter.php # src/Server/Helper.php # src/Type/SchemaValidationContext.php # src/Utils/ASTDefinitionBuilder.php # src/Utils/Utils.php # src/Validator/Rules/KnownArgumentNamesOnDirectives.php # src/Validator/Rules/NoFragmentCycles.php # tests/Executor/SyncTest.php # tests/Language/LexerTest.php # tests/Type/ValidationTest.php
Added a benchmark that does a lot of schema parsing, triggering code within
We could just convert everything to I think that particularly in library code, such micro-optimizations do matter. Personal gusto or ease of writing becomes less important when you consider the (as of writing this) 6652 users that are currently wasting CPU cycles: https://github.com/webonyx/graphql-php/network/dependents?package_id=UGFja2FnZS01NDI5NjAyMjc%3D |
# Conflicts: # composer.json # examples/01-blog/Blog/Data/DataSource.php # src/Validator/Rules/KnownArgumentNamesOnDirectives.php # tests/Type/ValidationTest.php
foreach
over slower functions array_map()
and Utils::map()
# Conflicts: # CHANGELOG.md # phpstan-baseline.neon
# Conflicts: # CHANGELOG.md # src/Error/Error.php # src/Error/FormattedError.php # src/Experimental/Executor/CoroutineContext.php # src/Experimental/Executor/CoroutineExecutor.php
Codecov Report
@@ Coverage Diff @@
## master #712 +/- ##
==========================================
+ Coverage 94.12% 94.14% +0.01%
==========================================
Files 117 117
Lines 9761 9715 -46
==========================================
- Hits 9188 9146 -42
+ Misses 573 569 -4
Continue to review full report at Codecov.
|
Co-authored-by: Simon Podlipsky <simon@podlipsky.net>
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.
should I target some places where I think we can use map in extra branch so you can cherrypick?
/** @var array<string, mixed> */ | ||
protected array $extensions; | ||
/** @var array<string, mixed>|null */ | ||
protected ?array $extensions; |
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.
is there a benefit from nullability somewhere?
I guess this would also classify as BC break
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.
Consistency across the other props here that can maybe hold an array
. While an empty array is an acceptable default for most cases, I think the optionality of this is best expressed by null
. We don't go around and add empty strings as defaults for optional strings everywhere either.
# Conflicts: # src/Executor/Promise/Adapter/ReactPromiseAdapter.php
Co-authored-by: Simon Podlipsky <simon@podlipsky.net>
Sounds good. I would like to get this one merged if it is alright in order to limit the amount of WIP merge requests. I do plan to follow up with removal of other, expensive utils. |
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.
Aight, let's go 🚢 . I'll follow with something on top of this soon.
This increases the performance measured in the benchmarks by about 1-3% on average.
While there are some spots where the map functions may look a bit nicer, other parts were complicated quite a bit by its use (e.g. double
array_map()
intoarray_combine()
).