Quickly fork, edit online, and submit a pull request for this page.
Requires a signed-in GitHub account. This works well for small changes.
If you'd like to make larger changes you may want to consider using
a local clone.

Migrating to Shared

Starting with
dmd version 2.030,
the default storage class
for statics and globals will be
thread local storage (TLS), rather
than the classic global data segment.
While most D code should just compile and run successfully without
change, there can be some issues.

Reading or writing TLS variables is potentially slower than for
classic global variables. The exact difference depends, among others,
on compiler code generation settings and the target architecture.
The performance difference ranges from negligible (Windows) to a call
to a special function (PIC on Linux, macOS, *BSD. Search for example
for __tls_get_address online). For non-PIC, the performance
difference is much smaller or even negligible.
If you find that TLS access is slower than classic global variables,
what can you do about it?

Minimize use of global variables. Reducing the use
of globals can improve the modularization and maintainability
of the code anyway, so this is a worthy goal.

Group related global variables into a struct. The TLS-related
overhead is (often) proportional to the number of variables accessed.
Because a global struct variable is just one single variable, after
accessing one member of the struct, accessing another member is
"for free" (does not incur the extra TLS-related overhead).
Of course when you've grouped the data into a struct, perhaps you
should remove the global altogether by passing around a reference to
the struct as context...

Make global variables immutable. Immutable data doesn't have
synchronization problems, so the compiler doesn't place it
in TLS.

Cache a reference to the global. Making a local cache
of it, and then accessing the cached value rather than the
original, can speed things up especially if the cached value
gets enregistered by the compiler.

Immutable data, once initialized, never changes.
This means that there are no synchronization issues
with multithreading, and so no need to put immutable data
into TLS. The compiler will put immutable data into
classic global storage, not TLS.

A good chunk of global data falls into this category.
Just mark it as immutable and it's done.

int[3] table = [6, 123, 0x87];

becomes:

immutableint[3] table = [6, 123, 0x87];

Immutability is also nice because it opens the door
for further compiler optimizations.

While this works with classic global variables, it
won't work with TLS variables. The reason is because
TLS variables don't have a location in memory known to
either the linker or the loader. It's a runtime computed
value.

Sometimes you may encounter strange error messages from the linker
about the global variables.
These are nearly always caused by one module putting the variable
in TLS, and another putting that same variable in classic global
storage.
This can happen when linking code with libraries that were built
with earlier versions of dmd. Check that libphobos2.a was properly
replaced with the latest.
It can also happen when interfacing with C. C globals default
to being classic global, although C does support TLS declarations.
Make sure the corresponding D declarations match the C ones in
terms of TLS or classic global.