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

Improve performance of the uts46 crate #453

Merged
merged 13 commits into from
Jun 27, 2018
Merged

Improve performance of the uts46 crate #453

merged 13 commits into from
Jun 27, 2018

Conversation

Marwes
Copy link

@Marwes Marwes commented Jun 25, 2018

I may have complicated the table structure more than is desired so I'd be happy to remove it if you want. It does shrink the total size of the tables by 6000 * 8 - 1500 * 2 = 42kb though (and gives a slight performance boost).

(Calculation is done as removed_ranges * range_size - added_indexes * index_size)

Total performance change of parsing a small and simple url.

 name   old ns/iter     new ns/iter     diff ns/iter   diff %  speedup 
 short  4,819 (5 MB/s)  3,516 (7 MB/s)        -1,303  -27.04%   x 1.37 

This change is Reviewable

Markus Westerlind added 9 commits June 20, 2018 15:07
This might not be exact, but it should be a good estimate. I don't think
this will ever over allocate in any case(?).
By making `MAPPING_TABLE` consist of slices we merge all runs of single
character ranges into a single range and subtract the start of the range
from the actual codepoint to figure out which `Mapping` each of those
individual character has. This reduces the size of the table that is
binary searched to about 1/4 which does not impact runtime performance
very much but does remove about (6000 * 8 - 1500 * 16 =) 24kb from the
resulting binary (with more improvements to follow)
`MAPPING_TABLE` were pretty large from the last commit as it contains
two pointers for each element. By converting it into a index to another
table + a single element indicator to recover most of it
(6000 * 8 - 1500 * 4 =) 42kb reduction.
Since we don't need all bits we can store the first indicator in `u16`
directly and save another 3kb
@SimonSapin
Copy link
Member

Looks good, thank you!


Reviewed 2 of 2 files at r1, 3 of 3 files at r2, 1 of 1 files at r3, 1 of 1 files at r4, 3 of 3 files at r5, 3 of 3 files at r6, 3 of 3 files at r7, 1 of 1 files at r8, 2 of 2 files at r9, 1 of 1 files at r10.
Review status: all files reviewed, 3 unresolved discussions (waiting on @Marwes)


idna/src/make_uts46_mapping_table.py, line 130 at r5 (raw file):

    current = []
    for r in ranges:
        mapping = r[2]

Coding style nit: I find this hard to read when I need to keep elsewhere to find out what is at index 0, 1, 2. What do you think of using tuple deconstruction in the for loop?


idna/src/make_uts46_mapping_table.py, line 164 at r7 (raw file):

    block_len = len(ranges)
    single = (1 << 15) if block_len == 1 else 0 
    print("    %s | %s, " % (offset, single))

If this boolean / bit still needs to be stored (see previous comment), I’d prefer the bitwise OR to be done in Python, since many more people will recompile the Rust code. Also add an assert that we don’t overflow 15 bits?


idna/src/uts46.rs, line 75 at r6 (raw file):

            &MAPPING_TABLE[offset as usize]
        } else {
            &MAPPING_TABLE[(offset + codepoint as u16 - TABLE[i].from as u16) as usize]

Aren’t these two code paths the same? Maybe the boolean is not needed at all?


Comments from Reviewable

@Marwes
Copy link
Author

Marwes commented Jun 26, 2018

Review status: all files reviewed, 3 unresolved discussions (waiting on @Marwes)


idna/src/make_uts46_mapping_table.py, line 130 at r5 (raw file):

Previously, SimonSapin (Simon Sapin) wrote…

Coding style nit: I find this hard to read when I need to keep elsewhere to find out what is at index 0, 1, 2. What do you think of using tuple deconstruction in the for loop?

👍


idna/src/make_uts46_mapping_table.py, line 164 at r7 (raw file):

Previously, SimonSapin (Simon Sapin) wrote…

If this boolean / bit still needs to be stored (see previous comment), I’d prefer the bitwise OR to be done in Python, since many more people will recompile the Rust code. Also add an assert that we don’t overflow 15 bits?

Sure


idna/src/uts46.rs, line 75 at r6 (raw file):

Previously, SimonSapin (Simon Sapin) wrote…

Aren’t these two code paths the same? Maybe the boolean is not needed at all?

It differentiates between the two cases

  • One (single) mapping for an entire range
  • One mapping for each element in a range (added through this PR)

In the first case multiple codepoints needs to map to offset so I can't do any arithmetic on it


Comments from Reviewable

@SimonSapin
Copy link
Member

Review status: all files reviewed, 2 unresolved discussions (waiting on @SimonSapin)


idna/src/uts46.rs, line 75 at r6 (raw file):

Previously, Marwes (Markus Westerlind) wrote…

It differentiates between the two cases

  • One (single) mapping for an entire range
  • One mapping for each element in a range (added through this PR)

In the first case multiple codepoints needs to map to offset so I can't do any arithmetic on it

Ok I see, thanks.


Comments from Reviewable

@Marwes
Copy link
Author

Marwes commented Jun 27, 2018

@SimonSapin That should take care of all comments.

@SimonSapin
Copy link
Member

Great, thanks!

@bors-servo r+


Reviewed 1 of 1 files at r11, 1 of 1 files at r12, 3 of 3 files at r13, 3 of 3 files at r14.
Review status: :shipit: complete! all files reviewed, all discussions resolved


Comments from Reviewable

@bors-servo
Copy link
Contributor

📌 Commit 5dfd1ec has been approved by SimonSapin

@bors-servo
Copy link
Contributor

⌛ Testing commit 5dfd1ec with merge 7c27f90...

bors-servo pushed a commit that referenced this pull request Jun 27, 2018
Improve performance of the uts46 crate

I may have complicated the table structure more than is desired so I'd be happy to remove it if you want. It does shrink the total size of the tables by 6000 * 8 - 1500 * 2 = 42kb though (and gives a slight performance boost).

(Calculation is done as `removed_ranges * range_size - added_indexes * index_size`)

Total performance change of parsing a small and simple url.
```
 name   old ns/iter     new ns/iter     diff ns/iter   diff %  speedup
 short  4,819 (5 MB/s)  3,516 (7 MB/s)        -1,303  -27.04%   x 1.37
```

<!-- Reviewable:start -->
---
This change is [<img src="https://reviewable.io/review_button.svg" height="34" align="absmiddle" alt="Reviewable"/>](https://reviewable.io/reviews/servo/rust-url/453)
<!-- Reviewable:end -->
@bors-servo
Copy link
Contributor

☀️ Test successful - status-travis
Approved by: SimonSapin
Pushing 7c27f90 to master...

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants