I’ve been playing around with Julia for awhile and am a big fan of the language overall. Recently, I’ve been doing a bit of work to construct an immutable collections and functional utilities library (work in progress, but source is here). A few core pieces are finished at this point so I’ve been testing the performance. Without going into details, what I’ve found is that my persistent dictionary (
PDict) has a performance on par with the Julia native
Dict type, with respect to
get operations (PDict queries take about 2.5 times as long as Dict queries), but is 2000 times slower for operations like insert. While I’m not surprised that the persistent operations are slower, I am surprised that they are this many orders of magnitude slower (for reference, clojure’s persistent map performs inserts in about 4x the time required for Julia’s mutable dicts, in my tests). I don’t claim to have a perfect implementation of the insert operation, but the size of the difference got me wondering about implementation details, and, long story short, I have a few questions about how structs and mutable structs actually work under the hood.
In particular, I’m wondering how the memory for structs gets handled. I’m not completely sure how Julia handles the movement and/or allocation of data structures on the heap and stack, but some of the documents and questions/answers I’ve read seem to indicate that immutable structs are allocated on the stack and are always passed by value rather than reference. If this is really the case, then many of the performance advantages of objects like immutable dictionaries will be entirely wiped away—a big advantage of immutable dictionaries is that you need never copy them (it will never change so just pass it by reference). If this is the case, then it would be more efficient to declare them as mutable structs so that they can live on the heap.
Similarly, if I declare a struct that itself contains a field that is of a concrete immutable type, does this type get included in the structure by reference or by value? If by value, then can I work around this by declaring the field to be of an intermediate abstract type? Would this even be useful?
Is there any documentation of these issues? I would also be happy to get a pointer to where in julia/src this gets hammered out.
Thanks in advance.