-
Notifications
You must be signed in to change notification settings - Fork 58
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
No finalizer #189
No finalizer #189
Conversation
Needs tests. |
Good call, I'll add some tests. |
I'm coming to the conclusion that this library really needs to be reworked to not use finalizers for resource management. Or rather, to use them properly. We really do want to leak memory when sending data, and we want to do a ccall that gives libzmq the c-function that will delete that memory. We need to trust libzmq to do that properly. It's not really proper to need libuv in order to write libzmq bindings... right? But at least I have written the tests. |
I think I need to take back the bit about not using libuv. I read the docs a bit more and I see that GC and libuv are intertwined more than I appreciated. |
You have two options:
|
From what I read it isn't possible to do that (yet, anyways). I wish I could release the buffer from the garbage-collection system entirely and manage it through C calls, basically get a pointer and permission to do a C-style |
Huh??? What are you talking about? The GC is completely unrelated to libuv. It knows how to scan tasks as well as a few other special non-native julia objects and that's as much as how much it interact with ANY other systems. It's basically the one system that is the least "intertwined" with anything else, since basically everything else uses the GC but not the other way around. |
@yuyichao See:
Also see https://docs.julialang.org/en/v1/manual/calling-c-and-fortran-code/#Thread-safety-1, specifically:
The GC isn't completely unrelated to libuv. Those are libuv calls to the event loop that should direct GC to delete data it holds (when it deigns to). |
Where does anything you quote mention even a single time about the GC?
Yes? But this isn't GC related. libuv controls the event loop, yes. Neither the event loop nor libuv has anything to do with the GC. The GC only works when you are allocating, it doesn't care if there's a event loop or not.
No. |
Or if you mean, libuv uses the GC to allocate data, which will obviously also be free'd by the GC then yes, but that's a single directional interaction, it never direct the GC to do anything special, it's just a user of the GC, much like anything else, so I don't see what's intertwined. |
Hey, calmate! Libzmq is based around zero-copy. It would be ideal to take data allocated in Julia and pass it into ZMQ. ZMQ holds the data, but it doesn't know how to delete it. You do that by passing it a C function. Normally, that C function would straight delete the data. There are two issues with that:
So you couldn't just call into GC directly, you have to schedule a GC call. That requires interacting with libuv so that GC gets called in a thread-safe manner within Julia. Really, the recommended manner of "telling" GC to delete something isn't actually to tell GC to delete something, it's to call a function that gets rid of some references to the data. Then GC is free to delete the data whenever it wants to. |
That is not the job of the GC. Such concept doesn't even exist in the GC. You stop referencing that object and the GC will delete it when it feels like it. Put it in a dict/set if you want to keep it for longer and that's what everyone do.
It IS thread safe. All what you read is that the julia runtime, NOT the GC, doesn't support external thread. Again, it has nothing to do with the GC. The part you link really doesn't mention anything about the GC so I still don't know where you get that idea from......................
And there really isn't anything as a GC call, you are just running normal julia code to deal with normal julia objects...........
No. "That requires interacting with libuv so that julia runtime gets called on a managed thread". The GC supports all the thread related stuff any part of julia does.
That's not the recommended manner, that's the only possible way and there will never be a different way. Again, if you can't wrap your mind around how a GC actually manages memory (I didn't at first) that's perfectly fine point to complain and learn about. If you combine the two completely unrelated issue together just because you happen to hit both at the same time and call "GC and libuv are intertwined more than I appreciated" that's just wrong. I agree with almost all the direct observations you have and it's just this wrong conclusion that I'm objecting. For me, having the GC and libuv intertwined to any degree (in a user visible way at least, using a different main loop inside the GC if the needs arise would be perfectly fine) is a completely stupid, non-sense and unacceptable design, given the current overall design of the language so I want to make is absolutely clear that the interaction between the two is only single directional. (And as I just realized, not so clear from your initial statement, that the two issues you have are just unrelated to each other) |
@yuyichao Are you trying to piss me off? Because you're succeeding. For starters, caps and bold is bad internet etiquette equivalent to yelling. I'm sure you know that, knock it off. Don't be rude by saying I can't "wrap my mind" around something. You know that's loaded language. You know that would piss you off if somebody said it to you. So don't say it to somebody else. Next, I don't assume something is thread-safe unless somebody explicitly tells me it is. Nowhere do I read in the docs that the GC is thread-safe. You may have some more intimate knowledge about Julia's GC, but if it's not documented to be thread-safe then I will assume that isn't part of its contract. Even if its current implementation is thread-safe, I don't want to get burned later if it becomes unsafe. Finally, don't just say, "No," and be condescending. Ask what I meant when I said that libuv and GC are intertwined. I think they're intertwined because I can't do anything GC-related unless I'm doing it in a thread-safe manner because AFAICT GC isn't promised to be thread-safe. That's literally all I meant by "more intertwined." I'd previously hoped I could have an API directly into the GC I could use to say, "this variable may have zero references later, but hang on to it until I tell you otherwise" (like I'm moving on. This all is moot. I know how to prevent GC from deleting my data before I want it to and I know how to signal to the GC that the data is ready to be deleted, and I know how to do that in a thread-safe manner using libuv because I can't trust the GC to be thread-safe. You can rant if you like but I'm done. |
No I don't. Those are emphasizing the important points, i.e. the points I'm directly objecting, and make them stand out from the long reasoning behind that point.
I actually don't mind someone saying that to me because I'm very sure there are a lot of things I can't wrap my head around. Well sorry about that and noted. I'm actually commenting on you asking for a
That's really not how it works because if GC isn't threadsafe then literally nothing is. It's not even a user visible part so there's no need to document about an implementation detail in user document. It's extensively documented for developer (comments in
I usually do when I feel like there's even a little bit of ambiguity but by all mean libuv and GC are not intertwined. Your use case needs both and that's it. If you said instead sth like "interacting with julia/GC from an external thread involves libuv more than I appreciate" that's perfectly fine (edit: and I'll even agree). As far as I understand, and please correctly me if this is a wrong understanding of the sensence, "libuv and GC are intertwined" is describing the libuv and GC, rather than a specific usecase that needs both. And as I hinted above, the property described here makes so little sense here that it feels very insulting. (I thought about mentioning this more explicitly in the previous comment but removed it. I didn't know that the highlight pisses you off though.............................)
As I said above, there's no such API now because nothing is needed. It's actually much more efficient to do one dict per user since the lookup and scaning will be faster. The only, really only, reason this is now impossible to do from an external thread without libuv is because julia itself does not support external thread, again, not sure how to emphasize once again without bold, not the GC. FWIW, clearing a reference isn't even a GC operation......
I'm not sure if you are using an alternative meaning of thread-safe here so please ignore if by thread safe you don't mean being able to use it from multiple thread without undefined behavior. If you do mean the thread-safety as what I thought you mean, then again, you aren't talking about thread-safety at all, you are talking about external thread support. A friendly note that you are actually relying on the GC to be thread safety all along. |
Add functions for resource management a la https://docs.julialang.org/en/v1.0/manual/control-flow/#finally-Clauses-1.