warp: Composing `Or` filters as an imbalanced tree causes signficialy longer build times
In a project I’m working on, I was able to cut debug build times by ~65%, from 6 minutes to 2 minutes, by building a more balanced Or tree of filters. Note that I optimized this code for readability and did not make the tree as balanced as it could be, an optimally balanced tree should yield even better results.
It might be useful to others it this was documented somewhere. Another thing that could make things easier is for warp to provide an or! macro that takes a flat list of filters and automatically builds an optimally balanced tree for them, in a way that preserves the filters order priority.
About this issue
- Original URL
- State: open
- Created 4 years ago
- Reactions: 10
- Comments: 18 (1 by maintainers)
Links to this issue
Commits related to this issue
- Improve build times with the `http` feature by 65% (!) From around 6 minutes to 2 minutes. Accomplished by building a more balanced `Or` tree of warp filters. The tree being built is not optimally ... — committed to bwt-dev/bwt by shesek 4 years ago
- Further improve build times with the `http` feature Construct a maximally balanced Or tree and use boxed filters in debug mode. Refs https://github.com/shesek/bwt/issues/15, https://github.com/seanm... — committed to bwt-dev/bwt by shesek 4 years ago
@jhpratt nerd-sniped me with their comment above that “I’m not sure it’s possible to implement in a
macro_rules!, unfortunately.” I made a macro to build a balanced tree oforfilters. (Here is a playground link to a version that just builds node trees if you want to play with it.)I tested this on @shesek’s repo, and this macro invocation:
turned into this code:
Basically, it seems to work. I observed the following incremental build times on my 3900X when switching between the different approaches:
I think this is enough of an improvement that it’s worth considering polishing this and bringing it into
warp.Edit: improved macro, playground link
I went ahead and added some comments from my understanding of the code. I don’t know how much of the commentary is helpful/needed, so if you think any of it is unnecessary or overly verbose, feel free to remove or amend it. I thought it was probably better to braindump now and polish it later.
I’ve just simplified the macro provided by @SafariMonkey. It only has four rules, two of which are internal. While likely having near zero impact on the actual performance, I’ve changed the bracket delimiters to semicolons, reducing the number of tokens. Additionally, everything is boxed in debug mode, which significantly improves compilation speed. This can be trivially disabled by removing the
debug_boxed!call in the first arm.@SafariMonkey thanks so much for this macro! It reduced my debug compile times for thoughts.page from ~3m56s to ~14s, which is a huge relief.
It would be great to get a macro like this into warp — perhaps it would be best to split it into to two macros, one to balance or trees, and the other to take a whole tree and debug_box it?
Of course documentation isn’t present in the sample — I still hardly understand how the macro works. I basically just spent a little time hacking away to inline the splitting and reducing the number of rules. With documentation, I think this would be a sensible addition to warp.
For what it’s worth, this the first macro I’ve written with this complexity, I’ve written a few “repeat this with some things changed” macros before but that’s it. The biggest help in writing this was having a well documented “split a list” macro already shared (see the link at the top of the doc comment). I tried to keep the comments on the macro up to date with my tweaks.
Someone with more experience in
macro_rules!may be able to spot some issues or improvements. For example, I bracket the first expression in theorpair - I’m not sure if there’s any point in doing so, but I’m trying to play it safe for the general case.Hi, this also helps easing on compile times, check https://github.com/seanmonstar/warp/pull/273 and https://github.com/seanmonstar/warp/issues/507#issuecomment-615974062
I have a warp 0.2.5 app with about 20 route handlers that was suffering 30+ minute incremental compile times. I had to rearrange my app quite a bit to use the macro since it doesn’t seem to work if I pass it filter functions (like the ones in the todo example). I think this is similar to the issue @sashomasho mentioned. Once I converted the filter functions to straight variables in
main.rsand passed them to the macro, I got a compile time of a little over 3 minutes. 10x speed up 😀 . Thanks for sharing the macro.I do wish I could get it to under a minute, but it’s definitely bearable now.
Thanks, this one reduced my debug compilation times from 4+ minutes to 28 seconds. I had to extract all handlers to separate variables to understand why the macro made the compiler angry initially, it turned out that the my websocket filter cannot be boxed, not sure why. I decided to share my experience, since this is the seconds time I try it, but it’s worth it.