-
-
Notifications
You must be signed in to change notification settings - Fork 2.9k
Optimize StaticStringMap Implementation #21498
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
base: master
Are you sure you want to change the base?
Conversation
be28052
to
4de75ff
Compare
impressive results! can you post the benchmark(s) source code and also expose a version that lets |
08a1339
to
6ce870d
Compare
Why remove the initComptime() and init() API? The idea behind #19719 was to move kvs_list from a type param to a init() param in order to avoid very long type names which result from them being a type param. EDIT: I like the simplicity of this implementation and the results seem to speak for themselves 👍 . FWIW, I don't care about runtime init(). But I think keeping the StaticStringMap name and moving kvs_list to an initComptime() param might be preferrable. |
Thank you for explaining the original reasoning! It's well founded. - I'll work on that and see how soon I can get it working. What are your thoughts on replacing |
034277d
to
56b7655
Compare
e24762b
to
67e31c5
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.
Impressive results.
Please document the breaking changes in the PR writeup (pretend you are writing release notes).
Please also explain why you deleted a lot of test coverage, otherwise it's difficult to be sure these changes don't break existing use cases.
Sounds good - let me know if you would like further changes. |
c5b9e07
to
d60e6d1
Compare
c90a8b0
to
d93419d
Compare
i started a review pointing out an issue in toLowerSimd but it doesnt seem to be working so I'll post it here:
this has two issues: is_upper incorrectly identifying [0, 65) as being uppercase letters, and - const true_vec: BVec = @splat(true);
- const is_upper: BVec = @select(bool, at_min, at_max, true_vec);
+ const false_vec: BVec = @splat(false);
+ const is_upper: BVec = @select(bool, at_min, at_max, false_vec);
- const lowered: SVec = input + @as(SVec, @splat('a' - 'A'));
+ const lowered: SVec = input +% @as(SVec, @splat('a' - 'A')); comptime code to verify that the changed version works |
That is correct. I don't think removing runtime init() is or the getLongestPrefix() functions is going to be a big deal. They were only added as extra, maybe nice to haves. And getLongestPrefix() was doing a linear scan so its probably better to remove it. |
3d6e6ef
to
0143320
Compare
I'm pretty sure the failures are unrelated, but I am curious about the aarch64-linux-release failure. Looks like it is incremental related. Is this test nondeterministic by any chance? |
My working theory for our inconsistent CI failures is that some system condition when under load causes processes to frequently crash. That aligns with what we see here -- note that on the failed incremental test, we also get a It's possible there is an incremental test case which is sometimes crashing the compiler, but I'd have to see the crash on a I'll re-run the failed jobs when the in-progress one finishes. EDIT: oh, that incremental test totally is actually flaky, my bad -- see this run. Will fix now! |
0143320
to
86bf50c
Compare
|
There is a limitation to both the old approach, and the new approach. Custom equal functions cannot say that two different-length arrays/strings are equal, because in both implementations the length is compared before they even reach the equal function. There are a few options we can take:
The third option could be done in two ways: we could say "make a function that takes one comptime-known element and one runtime-known element, and it decides how to compare them". This has the distinct advantage that the interface is further simplified, but cripples the current advantage of the defaultEql function. The second way to accept the third option is to keep the current interface, changing nothing. Personally I would prefer the first option, as I like simplicity. In my opinion, we don't need StaticArrayMap, but a comptime-optimized mapping between strings (normal or case-insensitive) is more than enough. Thoughts? I could make this into an issue if it's desired, but I figure it would be smoother to make such a change now rather than later. |
I agree. |
Please rebase against latest master branch and force push. When I do that with github ui I receive this:
|
4aefeb8
to
7f43808
Compare
2032978
to
e709cd9
Compare
I am interested in getting this landed for the 0.14.0 release, and would be happy to make any adjustments to facilitate this. Is there anything more that may be needed of me? |
it's a very messy writeup, comment history, commit history, which means it will require careful review, which means it will not have time to be merged before 0.14.0 |
e709cd9
to
f643ea2
Compare
f643ea2
to
15d4be4
Compare
No more runtime initialization, no more StaticStringMapWithEql. Introduce StaticStringMapIgnoreCaseAscii. Update references to StaticStringMapWithEql to use StaticStringMapIgnoreCaseAscii. Update asn1 to conform to comptime-known requirements of StaticStringMap.get(). Skip testing std.meta.stringToEnum with the stage2_riscv64 backend.
15d4be4
to
4842774
Compare
Optimized StaticStringMap
StaticStringMap
is an optimized mapping between some key/value pairs. The keys are always strings, and the values can be any type. The structure is initialized with the key/value pairs, and there is no way to change key/value pairs through the lifetime of the type.This PR replaces the implementation of
StaticStringMap
.Runtime
init()
has been removed. UseinitComptime()
instead.Functions
getLongestPrefix()
andgetLongestPrefixIndex()
have been removed.Type
StaticStringMapWithEql
is no longerpub
.Type
StaticStringMapIgnoreCaseAscii
has been added. It is a case-insensitiveStaticStringMap
.StaticStringMap
now checks for redundant keys.Test cases were removed if they referenced removed features.
The motivation behind this PR is a simplified implementation and improved code generation.

Here is the code generation: https://godbolt.org/z/ojW841qzh
The performance of
StaticStringMap
has more than doubled for the LLVM backend:bench.zip
x86_64 backend benchmark for `get` and `has`
Zig built with LLVM running `zig fmt CodeGen.zig`
Zig built with x86_64 backend running `zig fmt CodeGen.zig`
Zig built with LLVM compiling "hello world"
Zig built with x86_64 backend compiling "hello world"
Zig built with LLVM running "zig ast-check CodeGen.zig"
Zig built with x86_64 backend running "zig ast-check CodeGen.zig"
Size difference in Zig compiled with LLVM backend
Size difference in Zig compiled with x86_64 backend
Building the benchmark of both implementations
Closes #20055