-
Notifications
You must be signed in to change notification settings - Fork 14k
Description
Thread locals are often slower than they need to be. For example, if we have:
thread_local! {
static FOO: i32 = 777;
}Every access of the form FOO.with(|foo| ...) will first check whether FOO is initialized, and then initialize it if this is the first access. On some (most?) platforms we can statically initialize thread locals with a constant expression (in this case the constant expression is 777).
A check on every access can be fairly costly, and we should try to avoid checks whenever possible. It is possible to avoid them by using #[thread_local] instead of thread_local!, but that is an unstable feature without a clear stabilization plan...
In #17954 @alexcrichton said:
I do not think we should strive to stabilize
#[thread_local]. It's incredibly not portable which makes it not too useful for most software. We should strive to improvethread_local!. The feature to implement is for the compiler to understand whether the initialization expression is a constant expression or not. If it's a constant expression then we can bypass theNonestorage and "am I initialized checks", making it equivalent to raw#[thread_local]
@eddyb answered:
That's easy in the compiler but
thread_local!is not implemented in the compiler.
@arielb1 suggests:
... But we could add an
eager_thread_local!macro for that case.
@alexcrichton adds:
As for how to implement a "const expr detection" in a macro I'm not entirely sure. We could either move the implementation into the compiler (which I'd prefer to avoid) or take @arielb1's suggestion of a new macro or a variant of the current macro's syntax.
For example we could "perverse" the meaning via:
thread_local!(const A: i32 = 3);wherestaticin the macro means "lazily initialized, but any expression valid" andconstmeans "must be a constant expression". I don't think this is a good idea, but an example of what we might do.
My question after all that would be:
Can we perhaps make the thread_local! macro expand to a special lang item that provides two implementations - one for the lazy initialization case and one for the static initialization zero-checks case? Then the compiler would choose one of them, depending on whether the initialization expression is a constant expression.