^{:once true} should deal with this. Try the following simplified test case with and without it:
(defn query [result-fn] (let [x (for [n (range 1e6)] (make-array Object 100000)) f (^:once fn* [rs] (result-fn rs))] (f x))) (defn testq [] (let [myfn (fn [rs] (doseq [r rs] nil))] (query myfn))) On Tuesday, 20 June 2017 03:47:45 UTC+3, James Reeves wrote: > > This might be a bug in java.jdbc. The code that passes the result set seq > to the function is: > > (^{:once true} fn* [rset] > ((^{:once true} fn* [rs] > (result-set-fn (if as-arrays? > (cons (first rs) > (map row-fn (rest rs))) > (map row-fn rs)))) > (result-set-seq rset opts))) > > I'm wondering if this function holds onto the head of the seq, since it's > bound to "rs". > > On 20 June 2017 at 00:20, Luke Burton <luke_...@me.com <javascript:>> > wrote: > >> >> Anyone have any insights here? Really the most important thing I'm trying >> to learn is 2) how to identify when a lazy seq head is being retained, >> other than waiting for it to become bad enough that your program OOMs. >> >> >> On Jun 16, 2017, at 6:14 PM, Luke Burton <luke_...@me.com <javascript:>> >> wrote: >> >> >> Riddle me this: >> >> https://gist.github.com/hagmonk/a75621b143501966c22f53ed1e2bc36e >> >> Wherein I synthesize a large table in Postgres, then attempt to lazily >> load the table, discarding each row as I receive it. I tried *many* >> permutations and experiments, but settled on these two tests to illustrate >> my point. Which is that I simply can't get it to work with >> clojure.java.jdbc. >> >> test1, according to all my research and reading of the source code >> involved, should consume the query results lazily. It does not, and I can't >> for the life of me figure out why. Traffic starts to stream in, and the >> heap is overwhelmed almost immediately. I've deliberately set the heap to 1 >> GB. >> >> test2 uses a technique I borrowed wholesale from Ghadi Shayban in JDBC-99 >> <https://dev.clojure.org/jira/browse/JDBC-99?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel#issue-tabs>, >> >> which is to have ResultSet implement IReduceInit. It consumes a nominal >> amount of memory. I've verified it's actually doing something by putting >> counters in, and using YourKit to watch about 20 MB/s of traffic streaming >> into the JVM. It's brilliant, it doesn't even break 200 MB total heap usage. >> >> I used YourKit to track where the memory is being retained for test1. >> Initially I made the mistake of not setting the fetchSize, so I saw an >> ArrayList inside the driver holding the reference. The driver >> documentation <https://jdbc.postgresql.org/documentation/head/query.html> >> confirms >> that autoCommit must be disabled and the fetchSize set to some non-zero >> number. >> >> After making that change, YourKit confirmed that the GC root holding all >> the memory was the stack local variable "rs". At least I think it did, as a >> non-expert in this domain. I tried disassembling the functions using >> no.disassemble and the IntelliJ decompiler but I'm not really at the point >> where I understand what to look for. >> >> So my questions are: >> >> 1) what am I doing wrong with clojure.java.jdbc? >> >> Note some things I've already tried: >> >> * using row-fn instead of result-set-fn >> * using prepared statements >> * explicitly setting auto-commit false on the connection >> * declaring my result-set-fn with (^{:once true} *fn […]) (I did not see >> a change in the disassembly when using this) >> * probably other things I am forgetting >> >> 2) in these situations where you suspect that the head of a lazy sequence >> is being retained, how do you reason about it? I'm kind of lucky this one >> blew the heap so quickly, who knows how much of my production code might >> burning memory unnecessarily but not quite as fatally. Do you disassemble >> the functions and observe some smoking gun? How do you peek under the >> covers to see where the problem is? >> >> Luke. >> >> -- >> You received this message because you are subscribed to the Google >> Groups "Clojure" group. >> To post to this group, send email to clo...@googlegroups.com >> <javascript:> >> Note that posts from new members are moderated - please be patient with >> your first post. >> To unsubscribe from this group, send email to >> clojure+u...@googlegroups.com <javascript:> >> For more options, visit this group at >> http://groups.google.com/group/clojure?hl=en >> --- >> You received this message because you are subscribed to the Google Groups >> "Clojure" group. >> To unsubscribe from this group and stop receiving emails from it, send an >> email to clojure+u...@googlegroups.com <javascript:>. >> For more options, visit https://groups.google.com/d/optout. >> >> >> -- >> You received this message because you are subscribed to the Google >> Groups "Clojure" group. >> To post to this group, send email to clo...@googlegroups.com >> <javascript:> >> Note that posts from new members are moderated - please be patient with >> your first post. >> To unsubscribe from this group, send email to >> clojure+u...@googlegroups.com <javascript:> >> For more options, visit this group at >> http://groups.google.com/group/clojure?hl=en >> --- >> You received this message because you are subscribed to the Google Groups >> "Clojure" group. >> To unsubscribe from this group and stop receiving emails from it, send an >> email to clojure+u...@googlegroups.com <javascript:>. >> For more options, visit https://groups.google.com/d/optout. >> > > > > -- > James Reeves > booleanknot.com > -- You received this message because you are subscribed to the Google Groups "Clojure" group. To post to this group, send email to clojure@googlegroups.com Note that posts from new members are moderated - please be patient with your first post. To unsubscribe from this group, send email to clojure+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/clojure?hl=en --- You received this message because you are subscribed to the Google Groups "Clojure" group. To unsubscribe from this group and stop receiving emails from it, send an email to clojure+unsubscr...@googlegroups.com. For more options, visit https://groups.google.com/d/optout.