New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Unify Nim's GC/memory management options #177
Comments
That sounds good, I've notive lots of overhead with a tree data structure with a backpointer to the parent. |
That's a good point, since we don't lose the type information (it's still a |
That's the kind of typo that makes people think the wrong thing. :o) |
Update: With 1.4 we'll ship
(As a first step, they simply stop being documented.) We would be left with:
|
As someone whose project entirely depends on custom memory management ( Omni ) I would strongly prefer the What's the reasoning of taking it out completely? I believe it's still a nice feature to have for people like me that want to use Considering this feature is already in the language, and it doesn't involve more work to keep it alive, I really hope that there is a way it will be kept as it is. |
But you're free to use Nim's |
I do already use I just tried to compile some of my code with I just have problems understanding the choice of taking it out of the language (considering it is already there), as I believe it can be useful, even just for people using Moreover, I believe that |
Well you're right that supporting |
Although arc is probably superior to both The good thing about regions compared to gc:none is that you can always free the memory you use, so in case of saving one of them (if any) id say regions is more worth it |
Comparing
For example, I want to be able to use your Omni project with Nim's async framework and with mratsim's superior multi-threading solution, all in one program. With |
Thing is, you can't really use Omni in anything other than Omni (it ships with its own Having said so, what I am not saying that |
I think Araqs point was not specifically about omni, but about any kind of library, omni is not a good example here. Its a fair point, but i am still not convinced about the idea of just getting rid of them completely. About using projects with different gcs, i have always felt like it could be a nice feature, being able to have a computationally intensive part of your library use a gc and other part another one, wouldnt this be possible? cant the gcs be treated as libraries? (this is a bit offtopic already) |
@vitreo12 I don't understand how this works with today's --gc:none. Do you use it with -d:useMalloc? Do you use it for the warning messages the Nim compiler produces when you use a feature that uses the GC?
Ok, I get that but how do you do this with --gc:none? I'm not aware of an API that lets you do that. |
@RecruitMain707 |
@Araq I don't use
All memory in Omni is allocated / freed with a special function, Also, regarding the hard real time problem, Omni follows the standard Usually, you'd want to compile your omni code with one of these wrappers, as they already take care of calling the right functions at the right time for that specific audio programming environment. |
@vitreo12 do these "if statements" look like " if (NIM_UNLIKELY(*nimErr_)) goto BeforeRet_;"? If so, they're not useless - ARC/ORC use new exception implementation based on |
@Yardanico Those are the ones. Is there a way to remove them? |
@vitreo12 gc:none doesn't have them because --exceptions:goto is only enabled with ARC/ORC by default. Why would you want to remove them? |
Isn't a bunch of |
Cause I know I won't be raising exceptions in the program. I compile disabling all the runtime checks off. Or maybe I am just misunderstanding their usage by the way, I am a musician first and programmer secondly, excuse me for some misunderstandings! :) |
Other parts of the stdlib can (and runtime checks do that as well, though
Note that some of them are always enabled (scoped) because the logic in stdlib needs them. |
I see. I managed to get (almost) the same |
Some people use |
Update: With 1.4 we're shipping The plans for the deprecation of the other GCs was met with some resistance so for now they won't be deprecated -- but they won't see much further development from the Nim core team either.
|
im fine with them not being developed any further by the nim team, its totally fair. |
I think that before deciding to deprecate, first ORC needs to be made the default memory management for at least 1 final release. |
Doing a bit of hardish-realtime low-latency audio development of my own. This is 2ms to get 40Mbyte/s of audio data from the microphone to the CPU to the speaker, with zero tolerance for buffer over/underruns. This only works with a patched kernel, tuned interrupts and pre-allocated memory- and no memory allocations. So you can have your own pre-allocated mempool, and you can have the stack, that's it. GC_none is invaluable in this setting, because you don't have to hope you are not accidentally creating GC overhead that will cause the dreaded audio dropouts- you know, because GC_none warns you. It is already very hard to debug buffer over/underrounds in realtime audio code, if you add the GC layer as a potential source of issues, that disqualifies the language from use in this setting, period. This is, I guess, the unique use of GC_none- if you don't need the GC, you can be absolutely sure it's not there, and you can rule it out as the source of your Heisenbug of the day. This is a really, really big deal compared to, say, go. Note that these properties are shared by other applications as well, such as robotics control, and industrial automation (not theoretical examples, those areas use the same kernel patches as linux audio). If you keep GC_none, you could potentially code rocket control firmware in Nim. Nim is the only modern language in existance you can realtime audio development this in (except maybe if you count Rust)- even without the GC, Nim syntax is king, and you get templates and macros. Don't kill this. |
@capocasa what prevents people from using arc/orc to code rocket control firmware? |
Assuming realtimish performance is is required for rocket control firmware- if this assumption is wrong then arc/orc would do fine. Realtimish performance precludes memory allocations, so not using a GC is the only option. And in this case, as mentioned above, not having the GC in the code at all, along with warning if GC memory is used, are really important for debugging. |
@RecruitMain707 Nothing, but you don't have to do garbage collection if it's gonna blow up anyway :) @capocasa You make a good point about the warnings. I think making |
@Clyybber Thanks! It would certainly help to have the warnings seperately. But it would still be much preferable to keep gc:none. Because then I still have to trust that ARC behaves as I expect it to. This is normally ok, but when I am on the brink of insanity due to debugging a Heisenbug, this is bad. Imagine there is a very large rock suspended on a rope over your head where you sit. It is mounted on a top-rated cable and the release mechanism is connected to a sensor that is guaranteed not to go off when aimed at your particular hair color. In theory, you could now code with confidence. But you would still have to burn brain cycles wondering if there might not be some sort of malfunction. You would probably vastly prefer- and code better- if you could simply remove the entire contraption. |
Hardly, but since |
Depends on your definition of realtimish- certainly as I used it.
Yay! |
If you could tell Nim's allocator to work from this pre-allocated memory, would that help? Nim's allocator uses constant-time (O(1)) algorithms. |
Yeah, that would most likely work, and be pretty amazing- I'd consider it quite the advance for audio programming to say the least! Using seqs for sound processing- wow. Much better than futzing around with length/UncheckedArray. Traditionally, you have a real time thread, where the mentioned restrictions apply, but you also have a control thread where you do soft realtime (think games) or no realtime. Or, you have regular set up code, then real time code, then nonrelatime cleanup code. So it would be optimal to be able to set the GC behavior on arbitrary lines, or possibly blocks. |
Realize that |
|
@disruptek I'm not worried about a Heisenbug in Arc, I'm worried about a Heisenbug in my code that might or might not have to do with it subtly interacting with arc in a way I didn't anticipate, compounding debugging difficulty. In other words, I don't mind to pay the complexity cost for a heavy feature like a GC, as long as I'm actually using it. |
This is an alternative to #144. #144 is not dead but scheduled for Nim version 2 which is a couple of years away. The reason for this is that
owned
is quite a breaking change and we're better served with stability now that version 1 is out and with us for the years to come.GC: arc
The plan is to leverage the technology developed for destructors to give us a new GC mode,
--gc:arc
that mapsref
to atomatic refcounting. RC operations are optimized away when you use thesink
andlent
annotations as they are outlined in https://nim-lang.org/docs/destructors.html. How cycles are dealt with is an open question, the first implementation will ignore the problem, but there are a couple of solutions:collectCycles(someRef)
API for manually freeing cyclic data structures in a subgraph of the heap..cursor
annotation on object fields that are "parent" / unowning pointers. More on this later.The GC modes
The plan is to deprecate and remove the GC options until we are left with only
--gc:arc
and--gc:boehm
. Both options can handle shared heaps and work well with multi-threading,--gc:arc
is optimized for latency and works for all heap sizes, small or really big,--gc:boehm
is better for throughput on medium sized heaps (medium here means about 500MB).--gc:arc
also works out of the box on weird targets such as webassembly and has better interop with C/C++/Python/etc.The .cursor annotation
Besides cycles this proposal has a shortcoming in that so called "cursor" variables imply RC ops. These are very hard to optimize away in a multi-threaded setting and yet also can add considerable runtime overhead:
The solution is to annotate
it
with.cursor
to tell the compiler it doesn't need to emit RC ops. In fact,.cursor
more generally prevents object construction/destruction pairs and so can also be useful in other contexts. The alternative solution would be to use raw pointers (ptr
) instead which is more cumbersome and also more dangerous for Nim's evolution: Later on the compiler can try to prove.cursor
annotations to be safe, but forptr
the compiler has to remain silent about possible problems.It is natural to extend the
.cursor
pragma to object fields in order to break up cycles declaratively:But please notice that this is not C++'s weak_ptr, it means the
right
field is not involved in the reference counting, it is a raw pointer without runtime checks.The text was updated successfully, but these errors were encountered: