Skip to content

Optimize PHP html_entity_decode function - #18092

Closed
ArtUkrainskiy wants to merge 1 commit into
php:masterfrom
ArtUkrainskiy:html_entity_decode/improve-memchr
Closed

ArtUkrainskiy wants to merge 1 commit into
php:masterfrom
ArtUkrainskiy:html_entity_decode/improve-memchr

Conversation

@ArtUkrainskiy

@ArtUkrainskiy ArtUkrainskiy commented Mar 16, 2025 •

Copy link
Copy Markdown
Contributor

Improvements affect the C function traverse_for_entities:

  • Use memchr to search for '&' instead of scanning character by character.
  • Use memchr to locate ';' to determine potential entity boundaries instead of process_named_entity_html, avoiding unnecessary per-character validations.
  • Use memcpy instead of character-by-character copying.
  • Refactor code for improved structure and readability.

Benchmark branch - https://github.com/ArtUkrainskiy/php-src/tree/html_entity_decode/benchmark

------------------------------------------------------------------------------
|                      Test |     old avg(ns) |     new avg(ns) |    diff(%) |
------------------------------------------------------------------------------
|                      4k & |            5949 |           21115 |    -71.98% |
------------------------------------------------------------------------------
|             only entities |            8279 |           10202 |    -18.80% |
------------------------------------------------------------------------------
|        400 valid entities |            6439 |            5861 |      7.80% |
------------------------------------------------------------------------------
|        200 valid entities |            4891 |            3178 |     38.12% |
------------------------------------------------------------------------------
|        200 invalid entity |            4777 |            3181 |     37.29% |
------------------------------------------------------------------------------
|             200 ampersand |            4809 |            1221 |    198.35% |
------------------------------------------------------------------------------
|        100 valid entities |            4188 |            1777 |    124.49% |
------------------------------------------------------------------------------
|         50 valid entities |            2885 |             979 |    193.50% |
------------------------------------------------------------------------------
|        String ends with & |            2428 |             176 |   1221.69% |
------------------------------------------------------------------------------

As you can see, the speedup depends on the number of entities and & characters in the string — the fewer there are, the more noticeable the performance improvement.

In edge cases, where the string consists entirely of & characters or valid HTML entities, performance actually worsens. However, I don't think this is a common scenario.

Either way, I plan to continue optimizing and implement & scanning using SIMD instructions, which should significantly improve performance even in high-entity-density cases.

@ArtUkrainskiy
ArtUkrainskiy requested a review from bukka as a code owner March 16, 2025 17:38
@ArtUkrainskiy ArtUkrainskiy reopened this Mar 16, 2025
@ArtUkrainskiy
ArtUkrainskiy force-pushed the html_entity_decode/improve-memchr branch from d166abe to 66f5709 Compare March 16, 2025 17:52
Comment thread ext/standard/html.c Outdated
Comment thread ext/standard/html.c Outdated
@bukka

bukka commented Mar 17, 2025 •

Copy link
Copy Markdown
Member

@Girgias are you going to review the logic as well? Just checking if I should look into this or if you are happy to handle it all?

@Girgias

Girgias commented Mar 17, 2025

Copy link
Copy Markdown
Member

@Girgias are you going to review the logic as well? Just checking if I should look into this or if you are happy to handle it all?

Please do review the logic, I only had a cursory glance :)

@bukka

bukka commented Mar 17, 2025

Copy link
Copy Markdown
Member

Ok I will check it out next week if no one is quicker.

@ArtUkrainskiy
ArtUkrainskiy force-pushed the html_entity_decode/improve-memchr branch from 9b3e96d to f093c30 Compare March 17, 2025 16:30
@dragoonis

Copy link
Copy Markdown
Contributor

Nice idea @ArtUkrainskiy :-) 👍

@ArtUkrainskiy
ArtUkrainskiy requested a review from Girgias March 26, 2025 19:04
@ArtUkrainskiy
ArtUkrainskiy marked this pull request as draft March 26, 2025 19:05
@ArtUkrainskiy
ArtUkrainskiy marked this pull request as ready for review March 29, 2025 11:23

@bukka bukka left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think it looks reasonable except that introduction of valid_entity boolean and checking that everywhere which doesn't look like performance optimization to me. I understand that it was probably meant to make code more readable but not sure if it's worth it in this case. Might be worth to check if it has any impact.

Comment thread ext/standard/html.c Outdated
Comment thread ext/standard/html.c Outdated
@ArtUkrainskiy
ArtUkrainskiy requested a review from bukka March 30, 2025 18:43

@bukka bukka left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This looks better. The comments are pretty much only for minor issue / optimizations. Overall I think it looks good.

Comment thread ext/standard/html.c Outdated
Comment thread ext/standard/html.c Outdated
Comment thread ext/standard/html.c Outdated
Comment thread ext/standard/html.c Outdated
Comment thread ext/standard/html.c Outdated
@bukka

bukka commented Jun 15, 2025

Copy link
Copy Markdown
Member

I went through this again and think it looks good. Doesn't make sense to hold it because of few NITs which I can easily address during the merge. I will try do a bit of testing in about two weeks time and merge it then.

Optimize scanning for '&' and ';' using memchr. Use memcpy instead of
character-by-character copying language.

Closes phpGH-18092
@bukka
bukka force-pushed the html_entity_decode/improve-memchr branch from 5f8363b to 10589dc Compare July 7, 2025 16:24
@bukka

bukka commented Jul 7, 2025

Copy link
Copy Markdown
Member

I have done a bit of testing. Also fixed few nits and squash / rebased it so think it should be good enough. I will do one last round of testing in a couple of weeks and if I don't find anything, I will merge it.

@bukka bukka closed this in e0c3f46 Jul 21, 2025
@bukka

bukka commented Jul 21, 2025

Copy link
Copy Markdown
Member

I did a bit more checking and it seems all fine so merged to master. Thanks for the contribution!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants