Pretty much what the title says, but for more information: I am coming from C background and Nim's memory management confuses me a little bit. Documentation doesn't really say much about how they work, or I am just dumb.
Is arc basically RAII? If so, great! If not what's the difference? Is it guaranteed that the compiler injects destroy calls?
Should I use orc?
Should I concern myself with move semantics? Should I use them?
Should I manage memory manually for hot paths (with alloc and dealloc I presume)?
You should use .acyclic in combination with your ref object declarations, move things around when crossing thread boundaries and/or isolate. This style then leaves the choice of mm:atomicArc/arc/orc to the clients of your libraries. If you don't develop libraries you can simply demand mm:atomicArc and gain some convenience in a multi-threaded setting.
And yes, ARC is basically a smarter RAII where many move operations are figured out by the compiler. ORC adds a cycle collector to ARC but it doesn't work across threads yet and makes things more complex and newly written code should avoid it.
The general rule for real-time audio programming is: no allocations and no locks in real-time threads (i.e. the threads that write to your OS audio API or produce data for it).
That usually means: pre-allocate everything to fixed max sizes in the non-realtime parts of your code and use single producer/consumer ringbuffers to pass stuff between non-RT and RT threads.
E.g. afaics it would be ok to use a seq in your RT threads, but only if you pre-allocate it to the max size you need with newSeqOfCap.
The general rule for real-time audio programming is: no allocations and no locks in real-time threads
I've heard that one before but never heard a good reason for these draconian measures. Nim's allocator is O(1) and locks can be fair which bounds them to O(N) where N is the number of competing threads.
And streaming from disk/network can introduce unpredictable latencies too and most audio software doesn't run on a hard realtime OS.
So IMO for novices the best advice is, "relax, get your code correct and then look into tools that can measure latencies precisely".
@SpotlightKid is spot on.
You should:
Now in Nim memory management is linked to the type:
Do note that Nim strings and Nim seq are heap allocated but with value semantics.
Don't allocate in the hot path, use ringbuffers, realtime audio needs deterministic time guarantees, Nim allocator is based on TLSF which does give them (see https://nim-lang.org/blog/2022/11/11/a-cost-model-for-nim.html, http://www.gii.upv.es/tlsf/) but you still want to remove that from the hotpath.
Here is a simple single-threaded ringbuffer btw: https://github.com/mratsim/weave/blob/v0.4.10/weave/cross_thread_com/channels_spsc.md#example-naive-implementation
If you need alloca or malloc wrappers, here you go https://github.com/mratsim/constantine/blob/v0.2.0/constantine/platforms/allocs.nim Just remember to never allocate in a hot path, or even better, preallocate at program or heavy compute start and just reuse buffers afterwards.
I also do remember reading a rant from andrewrk (Zig author used to be an audio software engineer, see https://github.com/andrewrk/libsoundio) with more details and examples
Just because you don't use or understand a domain doesn't mean you can dismiss it as FUD.
I can and I do until I hear some real arguments, not war stories from 2010. And even if all the professionals are still correct about this issue in 2025, my point still stands that newcomers are helped by getting things done before they worry about a single audio glitch with a chance of 1 to 1 million.
Only the address space of the stack is preallocated, not the physical memory to back it up.
As soon as you enter main you need to allocate a stack for the thread to put variables on.
my point still stands that newcomers are helped by getting things done before they worry about a single audio glitch with a chance of 1 in 1 million.
@mekalu is a C dev, everything is manual memory management here, and I'm not even saying to not use heap allocation, I'm saying don't allocate in compute kernels or critical path to sound output.
I.e. preallocate buffers and pass them as openArray[T]
Having to rewrite thousands of lines when you could have save that by making an informed decision early on is a waste. And it's a familiar style to a C dev.
As soon as you enter main you need to allocate a stack for the thread to put variables on.
Ever heard of "demand paging"? The stack is effectively lazily allocated and it might even be harder to preallocate effectively than a heap...
How would you move mutable owned data between threads? other than raw ptrs
I can pass the data using spawn threadproc(x.move) and it is accessible inside the proc, but read only.
I tried isolating x and extracting it inside the proc, but x is immutable and extract needs var x
The only way I managed to get working is to capture a channel and receive x, and sending x.move from the main thread
@Araq That's pretty interesting I'd always assumed stack memory allocation was complete when the first line of the procedure gets run. I do know paging isn't typically an issue since you would set up a memory lock to avoid it.
I've spent a lot of time tuning my systems to get below 2ms round trip latency on audio hardware and it's pretty hard, and exponentially harder with each additional potential source of buffer underruns.
Because of this, I typically take the opposite approach- if I can exclude an entire class of potential dropout sources I will do it, until I get completely dropout-free operation. Then I will try adding convenient things to see if it breaks anything. That way, it's easier to narrow down culprits.
So as a new Nim audio programmer I would certainly start with @SpotlightKid and @mratsim's advice and pre-allocate with newSeqOfCap and avoid locks, and then later try switching to newSeq and withLock one by one and see if it stops working.
But it's pretty exciting that the Nim memory allocator has deterministic performance!
But- in the hot path, spike-free operation is king and you're trying to shave off a handful of CPU cycles here and there. A Nim memory allocation has to be at least in the ballpark of 50, so I think you would want to preallocate regardless.
So as a new Nim audio programmer I would certainly start with @SpotlightKid and @mratsim's advice and pre-allocate with newSeqOfCap and avoid locks, and then later try switching to newSeq and withLock one by one and see if it stops working.
Well if you start with the super efficient way why would you than pessimize your code later. My point is to do it the other way round. But sure, if you already know what you're doing, keep doing it. When you're a newbie, get things to work first and pick convenience first. IMO.
using T1.createThread(threadproc, x.ensuremove) causes this error Error: cannot move 'x', passing 'x' to a sink parameter introduces an implicit copy
x is a plain string, not sink/var/ptr/...
why would you then pessimize your code later
because it's really easy to follow the RT rules if you can be wasteful.
so you do newSeqOfCap(10000000) to get it to work at all. And then instead of wondering how much you're going to need you see if you can get away with newSeq.
I lost $485,000.00 USDT to a fake cryptocurrency trading platform a few weeks back after I got lured into the trading platform with the intent of earning a 10% profit daily trading on the platform. It was a hell of a time for me as I could hardly pay my bills and got me ruined financially. I had to confide in a close friend of mine who then introduced me to this crypto recovery team with the best recovery software at CYBERSPACE HACK PRO. I contacted them and they were able to completely recover my stolen digital assets with ease. Their service was superb, and my problems were solved in swift action, It only took them 48 hours to investigate and track down those scammers and my funds were returned to me. I strongly recommend this team to anyone going through a similar situation with their investment or fund theft to look up this team for the best appropriate solution to avoid losing huge funds to these scammers. Send complaint to
Contact info:
Email: Cyberspacehackpro(@)rescueteam.com
WhatsApp: +1 (659) 217 9239