-
Notifications
You must be signed in to change notification settings - Fork 12.8k
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
Monomorphize generic functions #1736
Comments
The extremely crude benchmark below yield less-than-promising results. The monomorphic version of
|
I don't want to discourage benchmarking, but I don't think this captures the whole picture. It is true that despite generating amazingly inefficient code for many generic functions we probably don't suffer that much because they mostly serve to glue other pieces together. However, first, performance is not the only concern: correctness is another. The current code for walking data structures dynamically is quite fragile and gets a number of cases wrong (alignment of enums being a prominent example). This stuff can be fixed, but it's going to require a lot of effort. Second, I think monomorphizing is an enabler for a lot of other things, some of which will also improve performance:
|
Also: removing the && and ++ argument mode distinction. Another benchmark, with more hopeful results (derived tydescs), shows a factor 70 speedup, and a size reduction of the Given the fact that most functions tend to non-generic, and that we'll probably only generate a lot of version for some heavily used, typically small functions like
|
Adds a --monomorpize flag to rustc to turn it on. You probably don't want to use it yet, since it's broken in a whole bunch of ways, but it successfully monomorphizes simple generic functions called from within the crate. Issue #1736
The free glue for opaque boxes will pick the actual tydesc out of the box, and call its glue. Issue #1736
Monomorphization seems to mostly work now. More experimental data:
This suggests that code blowup is not prohibitive, but definitely significant. There are still some tricks that can be used to reduce this. The speedup is somewhat disappointing. Since we're still spending most of our time in malloc/free related things, I wasn't exactly expecting a big boost from monomorphizing, but more than a percent. |
Enough to be able to compile librustc with --monomorphize. Issue #1736
Very exciting! 10% is tolerable on size. It's measurable but Kryder's law erases it quickly. I imagine it only takes a few of those 70x-perf-difference cases to lose a user though. So long as they retain some control over this functionality, I suspect users will be glad to see the feature. |
Marijn, do you monomorphize vtables too? That is, if I have a generic type with an iface bound, do I get static dispatch in the end? Also, do you have a generic "all boxes" version? |
@graydon: The 70x perf difference was an increase in speed. I don't think being fast will lose us users. @nikomatsakis: I'm not yet generating monomorphized vtables, but I am monomorphizing functions with bounded type parameters to not use a vtable at all. Using one instance of a generic functions for all box types is implemented. |
@marijnh I know! I mean "this is good -- in cases where we're 70x too slow and users could get that speed back by going to C++, we'd lose them". It's good we have an answer for those cases now! |
This mostly works in caf04ce . Compilation slowdown is significant (~40%). I haven't profiled yet. Generic code becomes a lot faster (~6× in the artificial benchmark at https://gist.github.com/2008845). |
There is consensus that we should at least experiment with generating single-type instances of generic functions. So if you have
map<T, U>
and you call it on<int, int>
, the compiler can compile a version specifically for those types, and if you then call it on<@int, (float, float)>
, it can generate another version.We can reuse generated functions for similar types. For example, since generics can't look 'into' types, types like
int
anduint
could be passed to the same version of a function without problems. We also store tydescs in boxes now, so a single version could be used for all@
types, and simply look inside the box if it needs to call free or compare glue on them.This is related to the project of cross-crate inlining. To monomorphize a function, you also need some representation of its code.
The text was updated successfully, but these errors were encountered: