-
-
Notifications
You must be signed in to change notification settings - Fork 102
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
Optimize offsetGet #506
Optimize offsetGet #506
Conversation
We don't actually need to call getCharLength() if we inline the operation and use mb_substr with substr. This trick fetches 4 bytes from the current byte offset because UTF-8 characters are at most 4 bytes. mb_substr will then read the first Unicode character from the selected 4 bytes. Signed-off-by: Kamil Tekiela <[email protected]>
33f2e72
to
a66f0d5
Compare
Codecov ReportPatch coverage:
Additional details and impacted files@@ Coverage Diff @@
## master #506 +/- ##
============================================
- Coverage 96.46% 96.45% -0.02%
+ Complexity 2179 2170 -9
============================================
Files 66 66
Lines 5065 5045 -20
============================================
- Hits 4886 4866 -20
Misses 179 179
☔ View full report in Codecov by Sentry. 📢 Have feedback on the report? Share it here. |
Definitely. |
Signed-off-by: Kamil Tekiela <[email protected]>
Signed-off-by: Kamil Tekiela <[email protected]>
* @Assert("mode(variant.time.avg) < 800 microseconds +/- 20%") | ||
* @Assert("mode(variant.time.avg) > 100 microseconds +/- 10%") | ||
*/ | ||
public function benchGetCharLength(): void |
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.
Can you benchmark the function and set a baseline please ?
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 it not remain the same? How do I run this benchmark?
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.
Well, since it's a more complete function and the function was removed maybe everything should be updated then
But having a benchmark data could help
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 added a new commit. Is this what you had in mind? These are the results I get:
benchBuildUtfString.....................I19 ✔ Mo6.052ms (±3.59%)
benchUtfStringRandomAccessWithUnicode...I19 ✔ Mo63.459μs (±10.50%)
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.
Yes, that's good to have checked at all times.
For the results I do not know, if the benchmark was added before we could compare but that's totally okay never mind :)
Could we keep the previous optimisation that should normally be the fastest one and keep yours to avoid calling ord ? |
No, because it's either this or that. To use the ASCII map optimization one must use But maybe I misunderstood what you mean. What exactly are you proposing? Do you see a way to merge these two solutions together? |
Indeed, I misunderstood the new solution
Not really because of the use of delta and other things that seems to advance the string much more quickly Maybe phpbench could show how this is quick ? |
Yeah it does. I wish there was a way to avoid it but I can't think of any. Good thing that |
Signed-off-by: Kamil Tekiela <[email protected]>
28bf110
to
be2ca97
Compare
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.
Looks great !
We don't actually need to call getCharLength() if we inline the operation and use mb_substr with substr. This trick fetches 4 bytes from the current byte offset because UTF-8 characters are at most 4 bytes. mb_substr will then read the first Unicode character from the selected 4 bytes.
The previous technique was actually brilliant. The ASCII map optimization is the fastest way to calculate it, but it also is quite long. This technique would be perfect if PHP had a way to avoid
ord()
call altogether. I benchmarked 3 different techniques I could come up with. The ASCII map is the fastest. But actually, the worst thing for performance is a function call. So inlining the long implementation wouldn't be wise. That's why I decided to use themb_substr()
technique.Real-life benchmarks:
Before:
After:
As you can see this is a microoptimization, so I think we shouldn't be so worried about which one is the fastest. The difference in my benchmark is only 4ms with 10k calls.
What do you think? Should I add a code comment explaining how this works?