On 12/16/2011 08:41 PM, Jonathan M Davis wrote:
On Friday, December 16, 2011 12:29:18 Andrei Alexandrescu wrote:
Jonathan, could I impose on you to replace all static cdtors in
std.datetime with lazy initialization? I looked through it and it
strikes me as a reasonably simple job, but I think you'd know better
what to do than me.

A similar effort could be conducted to reduce or eliminate static cdtors
from druntime. I made the experiment of commenting them all, and that
reduced the size of the baseline from 218KB to 200KB. This is a good
amount, but not as dramatic as what we can get by working on std.datetime.

Hmm. I had reply for this already, but it seems to have disappeared, so I'll
try again.

You could make core.time use property functions instead of the static
immutable variables that it's using now for ticksPerSec and appOrigin, but in
order to do that right would require introducing a mutex or synchronized block
(which is really just a mutex under the hood anyway), and I'm loathe to do
that in time-related code. ticksPerSec gets used all over the place in
TickDuration, and that could have a negative impact on performance for
something that needs to be really fast (since it's used in stuff like StopWatch
and benchmarking). On top of that, in order to maintain the current semantics,
the property functions would have to be pure, which they can't be without
doing some nasty casting to convince the compiler that stuff which isn't pure
is actually pure.

lazy variables would resolve this.


For std.datetime, the problem would be reduced if a class could be created in
CTFE and still be around at runtime, but we can't do that yet, and it wouldn't
completely solve the problem, since the shared static constructor related to
LocalTime has to call tzset. So, some sort of runtime initialization must be
done. And the instances for the singleton are not only immutable, but the
functions for getting them are pure. So, once again, some nasty casting would
be required to get it to work without breaking purity. And once again, we'd
have introduce a mutex. And for both core.time and std.datetime we're talking
about a mutex would be needed only briefly to ensure that we don't end up with
two threads trying to initialize the variable at the same time. After that, it
would just be impeding performance for no value. They're classic situations
for static constructors - initializing static immutable variables - and
really, they _should_ be using static constructors. If we have to get rid of
them, it's to get around other problems in the language or compiler instead of
fixing those problems. So, on some level, that seems like a failure on the part
of the language

no.

and the compiler.

yes. Although I am not severely affected by 500kb of bloat.

If we _have_ to find a workaround, then we
have to find a workaround, but I find the need to be distasteful to say the
least. I previously tried to get rid of the static constructors in
std.datetime and couldn't precisely because they're needed unless you play
major casting games to get around immutable and pure.

If we play nice, it's impossible to get rid of the static constructors in
std.datetime. It probably is possible if we do nasty casting, but (much as I
hate to use the word) it seems like this is a hack to get around the fact that
the compiler isn't dealing with static constructors as well as we'd like. I'd
_really_ like to see this fixed at the compiler level.

And honestly, I think that a far worse problem with static constructors is
circular dependencies. _That_ is something that needs to be addressed with
regards to static constructors.

Circular dependencies are not to be blamed on the design of static constructors.

In general at this point, it's looking like
static constructors are turning out to be a bit of a failure on some level,
given the issues that we're having because of them, and I think that we should
fix the language and/or compiler so that they _aren't_ a failure.

- Jonathan M Davis


We are having (minor!!) problems because the task of initializing global data in a modular way is inherently hard.

Just have a look how other languages handle initialization of global data and you'll notice that the D solution is actually very sensible.

Reply via email to