If I want maximum performance for a program written in Julia, one of my options would be manually managing the memory with help of Julia C Standard Library.
But is it possible to do that in another way? Has Julia facilities for manually manage the memory?
Do you mean pre-allocate memory and re-use it? Sure, Julia provides lots of in-place operations that act on existing arrays and other data structures. You can even allocate storage for one type and re-use it for another type using reinterpret.
Do you mean working avoiding garbage collection entirely and manually free-ing memory as needed? Yes, you can allocate your own memory by malloc and use raw pointers (or unsafe_wrap to treat them as arrays/etcetera), but it obviously takes a lot more care. Usually this is not worth it except to interact with external non-Julia libraries.
Do you mean swapping in a custom garbage-collection algorithm for standard Julia objects? Not really, without recompiling Julia itself and doing a lot of low-level hacking. Of course, you can turn GC off completely with GC.enable(false), and manually invoke it with GC.gc().
I read on an article that D, Nim and Rust can be as fast as C if managing the memory manually, I don’t believe that managing the memory manually should be restricted to interacting with non-Julia libraries only.
I didn’t know that GC can be disabled, good to know.
That article was certainly mistaken, as there’s no need for manually managing memory (i.e., calling malloc and free by hand) in Rust.
While disabling GC is an option, writing your code in a way that doesn’t require GC to run much (if at all) by reducing allocations in the first place, is as good as managing memory manually with malloc et al.
/\ “Nim, D, and Rust can go as fast as C/C++ can when you switch to “unsafe” manual memory management.”
While disabling GC is an option, writing your code in a way that doesn’t require GC to run much (if at all) by reducing allocations in the first place, is as good as managing memory manually with malloc et al.
Is that I want to do in the future (I’m still studying programming).
I had never heard of that benchmark so I went and looked and it describes itself as being a benchmark primarily for memory management intensive operations
For the most part that’s just not true of most real world problems that you would choose to use Julia for so I don’t think it’s particularly relevant to decision making
It’s definitely the case that memory management can slow down your programs but there are many many ways to account for that within Julia without resorting to malloc
Did you remember when you was a very young child and you played with play dough? I can do the same with Julia macros and its memory management facilities.
It’s usually a mistake to avoid allocations (they are not slow), or to use Libc.malloc directly.
When you allocate indirectly the same Libc.malloc is used (and same or better speed). For real-time, you want to avoid GC triggered, by avoiding allocations in parts of your program (a main loop). Even if you want to manage your own memory call Libc.malloc, there are packages you may want to use rethar than Julia’s standard library API directly. See e.g. StaticTools.jl.
Avoiding Libc.malloc entirely, directly or indirectly is problematic. Then you have no heap.
I theory you can get memory straight from the kernel (e.g. Linux’s or Windows’s etc), but your program wouldn’t be portable that way. You really want to use malloc in libc at least indirectly for portability.
There are alternative malloc than in the default libc, e.g. mimalloc and there’s a PR to make it work in Julia. It’s a good replacement. There are also alternative libc available, see musl Julia, and Cosmobilitan is interesting but not yet supported…
Data structures often allocate without user control, so this may be hard to achieve in many cases. For instance, in Julia I cannot fill a Dict using a preallocated backing buffer; other languages make this easier.
SimpleChains.jl is a library that manually manages its memory internally via reinterpreting and bumping pointers.
It will reuse the same memory between calls to avoid allocations.
Rather than use malloc, it just allocates a regular Julia Vector{UInt8} and gets the pointer.