-
Notifications
You must be signed in to change notification settings - Fork 78
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
yaml-0.10.0 requires larger stack usage #147
Comments
The diff that introduced the space leak: be36373 The diff between the two versions: http://hdiff.luite.com/cgit/yaml/diff/ |
Bummer! I can try to take a look tomorrow. |
I took a quick look, memory usage went up from 3 MB to 10 MB and is linear (if I double the file size it's 7 MB vs 18 MB). Doesn't look very dramatic to me. |
Measuring memory usage may well not detect the space leak - the space leak is about accumulating relatively large amounts of gunk which are later forced. E.g. we accumulate |
Using |
At the point I switch type Parse = StateT (Map String Value) (ResourceT IO) to type Parse = RWST () () (Map String Value) (ResourceT IO) I need (I'm using |
Before it was using Control.Monad.Trans.State, which is actually the lazy one. Would be interesting to see if the strict and lazy state were both small stack usage. |
Would also be good to see the RWS.Lazy as well. |
|
I don't observe any difference between strict / lazy |
I see that the Strict RWST is not strict in the writer, which is very likely where the space leak is coming from. It will be building up a Alternative would be to use the https://www.fpcomplete.com/blog/2017/06/readert-design-pattern pattern, which is my goto alternative to RWST. |
https://blog.infinitenegativeutility.com/2016/7/writer-monads-and-space-leaks explains the problem - Writer monads are inherently a space leak, and there's nothing you can do about it. ReaderT/IORef is the solution. |
I thought I dropped a comment here, but looks like it got lost. I'm in favor of fixing this problem, and generally avoiding any flavor of |
Ok, I assume we will revert to using I'll give it a stab. |
Why switch to a StateT? I'd recommend a ReaderT that contains an IORef (or perhaps more than one). That pattern tends to be most performant and simple. |
I opened #148 to address this.
The
I assume this matters for long lists (as your test data essentially is). I didn't observe any difference by changing it. I don't have a strong opinion here. As a side note, this thunks won't be retained unless there is a warning. |
I at least agree that reasoning about performance is easier with an |
Yes, definitely fix the Int thing. It's performance leak 101. Slow, memory hungry, everything bad about laziness. Regarding ReaderT, no need to go for atomic, and StateT IO is already imperative. However, personal choice. |
For large stack usage, it's nearly 100% of the time a space leak, leaking performance. I detected this using the HLint space leak tests, which started failing with the 0.10.0 upgrade. See https://github.com/ndmitchell/spaceleak for my methodology.
Using the test case:
This crashes when I do:
This code starts failing with be36373, but works fine with
-K1K
before that, so ping @sol. The test data can be found at https://github.com/ndmitchell/hlint/blob/master/data/hlint.yaml.I did some "obvious" changes based on the diff - moving to
RWS.Strict
, moving toMap.Strict
, moving tofoldl'
. I thought I'd spotted it withparseS
taking anInt
it never forces, which is almost certainly a space leak, but even that didn't make the space leak go away (but is probably desirable). I suspect the best way forward is to apply the changes from the patch in question one at a time.The text was updated successfully, but these errors were encountered: