Conversation
gadmm
left a comment
There was a problem hiding this comment.
Looks good to me. Using young_limit uniformly is nice, masking will rely on that. A small question again about memprof_track_young below.
You mention caml_final_to_do but I didn't see it appear in the patches.
This PR is needed for #8805 but technically not for 4.10 given that the current behaviour, although it is not the one desired, is not problematic. However, if we want to avoid delaying #8993, I would need to know if the current PR is going to be merged very very soon because I'll need to rebase on it. (Same remark for the reversion in semantics of check_urgent_gc which is due for 4.10 in all cases and that I'll need to do separately if #8993 was to be delayed.)
Ah right. I forgot to push that. |
look good to me |
|
A behaviour I noticed before but which is repeated with this patch: in long-running allocating C functions, since allocations do not reset caml_something_to_do, if a signal arrives or a finaliser is pending, then all subsequent small allocations are made slow because they will all poll and then decide to not do anything (until the callbacks are finally executed). Is this tradeoff accepted? My implementation of masking tries hard to avoid that so maybe we can fix this in the future with masking. |
|
This patch looks good to me. Well spotted/fixed! It worries me that there is no automated testing of this. I don't think this should be too hard to write a test case for: do something which causes a callback to become pending, and then allocate and assert that the callback runs before the next GC cycle. There's an example of such a test in testsuite/tests/c-api/alloc_async.
FWIW, I think this overhead is fine. If there's a simple way to avoid it, then that would be nice, but I don't think it's worth spending much effort or runtime complexity on. |
Well, yes, I thought that should be the price to pay. Do you have figures in order to evaluate the slowdown?
Still, we would need to enter |
Then, this test would only be relevant in native mode with #8805 because the bytecode interpreter checks |
Good point. We should wait until #8805 is merged before adding this test.
This is true for finalisers but not for signals, so the test should use signals. When a signal arrives, the register caching young_limit is updated from the signal handler. I think this is the right behaviour, actually: it's OK to delay a finaliser until the next GC cycle since finalisers are always delayed by a GC cycle, but signals should be handled promptly.
(Agreed that this is an independent discussion, but if you're investigating this you can use |
|
I'm all for merging this (@stedolan, I am assuming that you also approve of the patch?), but I think that indeed writing a test would be very nice if it's not too much work. |
I agree!
Thinking about this again, isn't this only true for Memprof callbacks? Signal callbacks work fine before #8805, so a test using those in native code should fail before this PR and pass afterwards. |
Currently (until #8805), in native, caml_garbage_collection correctly calls signal handlers both before and after this PR. IMO this is less of a bugfix than finishing implementing a feature that will only become visible once #8805 lands, in that sense a test isn't strictly necessary, and I agree with @jhjourdan if he says that it's complicated to test. |
I agree that it's a separate discussion, and I do not have figures. It is very dependent on the user's code. If the user follows the advice of regularly calling a process_pending_* function, then they are safe from it. The trick with masking in order to avoid entering |
Actually, I think we can write a test, which would fail before this PR in bytecode. Just give me a little more time for that! |
44553d0 to
f2f36c9
Compare
… call to [caml_alloc_small_dispatch].
…patch], we can use [young_limit] to check for signals both in bytecode and native modes.
|
I have just added a test which checks that signals are indeed handled at every allocation in the minor heap from OCaml code. I took care of not calling any function after raising the signal, so that we are sure that the signal is not handled by the other mechanism in |
|
Thanks! |
Thanks to @gadmm, we found a bug in #8691 (cf #8691 (comment)): async callbacks were not checked systematically in
caml_alloc_small_dispatch, despite our desire.Fixing this will be especially important once #8805 will be merged, since
caml_alloc_small_dispatchwill be the only entry point for handling async callbacks in native mode. Without this PR patch but with #8805, signal handling in native mode will be delayed until the next minor collection.In addition, this PR fixes two other less important issues in #8691:
caml_memprof_to_doandcaml_final_to_do, which was used in old versions of the PR Guarantee that allocation functions do no trigger callbacks when called from C #8691,young_limitboth in native and bytecode modes. This makes it more uniform, and since we are checking for async callbacks incaml_alloc_small_dispatch, there is no reason not to setyoung_limitwhen there is one pending.