[CLJ-1423] Applying a var to an infinite arglist consumes all available memory Created: 15/May/14 Updated: 19/Aug/16 Resolved: 19/Aug/16
|Fix Version/s:||Release 1.9|
|Patch:||Code and Test|
It is possible to apply a function to an infinite argument list: for example, (apply distinct? (repeat 1)) immediately returns false, after realizing just a few elements of the infinite sequence (repeat 1). However, (apply #'distinct? (repeat 1)) attempts to realize all of (repeat 1) into memory at once.
This happens because Var.applyTo delegates to AFn.applyToHelper to decide which arity of Var.invoke to dispatch to; but AFn doesn't expect infinite arglists (mostly those use RestFn). So it uses RT.seqToArray, which doesn't work well in this case.
Instead, Var.applyTo(args) can just dispatch to deref().applyTo(args), and let the function being stored figure out what to do with the arglist.
I've changed Var.applyTo to do this, and added a test (which fails before my patch is applied, and passes afterwards).
Screened by: Alex Miller
|Comment by Alex Miller [ 18/Jan/16 5:29 PM ]|
I also did a quick perf test on this:
which showed times ~82 ms per rep before the patch and ~10 ms per rep after the patch (on par with applying the function directly).
I added a new patch that squashes the commits, adds the ticket number to the commit message, attribution was retained.