-
-
Notifications
You must be signed in to change notification settings - Fork 418
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
Replace memory-leak-inciting Writer.reserve
with more intuitive Writer.reserve_current
method.
#2260
Conversation
Just wanted to note that this could be seen as a change in semantics rather than a fix. The docstring says "Reserve space for size additional bytes" - I think this is a bit ambiguous as to whether it implies the old behaviour (reserve N additional bytes on every call), or the new behaviour that you've introduced here (ensure that at least N total bytes are reserved). Honestly, I'd lean more toward thinking that the docstring implies the old behaviour, particularly because of the word additional. I think both meanings are actually valid, so how would you feel about having both methods available, with clarified docstrings and appropriate names on each one? |
I've added the "needs discussion during sync" label just to mark that it needs discussion - if we come to a good answer before next week's sync, we can just remove that label. |
I initially considered it to be "not a bug" before rethinking it so I understand your suggestion. I'm not sure what the names should be to make the distinction clear and not confusing so I'm open to suggestions (or if someone wants to create another PR with the appropriate changes I'll close this one). |
Also, as additional context, the |
It seems like the new behaviour you're introducing here is much more similar semantics to With that in mind, I don't think either the old behaviour or the new behaviour of this method are the same as the So maybe we need two new names to thoroughly avoid confusion? I'll think on it a little bit, and anyone else can feel free to give suggestions in the meantime. |
What about one of
as new names for the old And one of:
for the new implementation which just calls Preferably both names should match (e.g. |
I think Do we also need to consider a new name for |
I've been going over the minimal case with @dipinhora and I think this is
I don't think this is a change in semantics. I think this is a straight up bug. I'm shocked that something like this, which I would think is completely safe, can leak memory: use "buffered"
actor Main
let _wb: Writer = Writer
var _num: USize = 10000000
var _data: Array[ByteSeq] = Array[ByteSeq]
new create(env: Env) =>
f()
be f() =>
_wb.reserve(8)
_wb.write("random stuff")
_data = _wb.done()
_num = _num - 1
if _num > 0 then
f()
end whether its a semantics change or not, i think we need to fix that under principal of least surprise bug. |
@SeanTAllen - no one in this thread is saying that this API is okay, or that it should stay how it is - the issue at hand is finding the right way to fix it, and most importantly, avoiding having confusion like this in the future. I understand that the behaviour was surprising to you and @dipinhora, but I was just pointing out that this is most likely behaving as the author intended it to. That is, I see it not as a "memory leak in From my perspective, the main issues with the "old" code (before this PR) are:
So my hesitation to merge this PR as is are that I think it might still suffer from those same two problems above.
|
I wrote this together with @sylvanc. I don't remember why we did it this way rather than some other way, but maybe he does. I dug through some old Wallaroo slack logs and found a conversation about this method from June, 2016. In the conversation I suggested that maybe what |
After discussing this on the sync call a bit, we didn't come to a conclusion, but my personal preference for this result would be to rename the method as |
Prior to this commit, multiple calls to `Writer.reserve` would allocate more and more memory in `_current` even if a sufficient amount of unused memory was already available and allocated in `_current`. This commit changes the logic in `reserve` to call `_check` as that has similar logic to confirm/reserve memory required but without the memory leak. This commit also renames `reserve` to `reserve_current`.
ee840af
to
c920a0f
Compare
@jemc I've renamed the method and changed the docstring. Please let me know if this is what you had in mind. |
Writer.reserve
Writer.reserve
with more intuitive Writer.reserve_current
method.
Thanks! |
Prior to this commit, multiple calls to
Writer.reserve
wouldallocate more and more memory in
_current
even if a sufficientamount of unused memory was already available and allocated in
_current
.This commit changes the logic in
reserve
to call_check
asthat has similar logic to confirm/reserve memory required but
without the memory leak.
For context:
We had a piece of code with a memory leak related to
Writer.reserve
calls. Removing the calls removed the leak. We were callingWriter.reserve
right aftercreate
andWriter.done
and then filling theWriter
usingWriter.write
in between. This resulted in a memory leak becauseWriter.write
doesn't use_current
andWriter.done
doesn't change/reallocate_current
if there was no data written to it. As a result, over time, multipleWriter.reserve
/Writer.write
/Writer.done
cycles resulted in the memory leak becauseWriter.reserve
would continually add more memory to_current
even though it already had enough unused space already allocated. This PR corrects the memory leak.Note: I wasn't able to think of a good test to add to
_test.pony
to prevent a regression because_current
is hidden behind theWriter
interface and there is no way to inspect it directly. I'd appreciate any ideas regarding adding a test to prevent a regression.