Postgres, as mentioned in the mail and the linked source code. The problem at this point doesn't appear to be options given to the driver, since I show two implementations using the same driver options. One processes the results lazily, one does not.
Now, I'm calling two different methods in clojure.java.jdbc, so there's a chance the driver options aren't being propagated correctly to the implementation in one of the methods. It's already soaked up way too much of my time (and I like the elegance of the reducible-result-set alternative) so I haven't revisited the code to explore further. > On Jun 23, 2017, at 7:38 AM, r0man <roman.sche...@burningswell.com > <mailto:roman.sche...@burningswell.com>> wrote: > > Hi Luke, > > which database are you using? I had the same issue with MySQL recently. At > the end I got it working with clojure.java.jdbc. > I don't have the code at hand, but according to the MySQL docs you have to > set the fetch size to Integer.MIN_VALUE. > > https://dev.mysql.com/doc/connector-j/5.1/en/connector-j-reference-implementation-notes.html > > <https://dev.mysql.com/doc/connector-j/5.1/en/connector-j-reference-implementation-notes.html> > > r0man > > On Saturday, June 17, 2017 at 3:15:13 AM UTC+2, Luke Burton wrote: > > Riddle me this: > > https://gist.github.com/hagmonk/a75621b143501966c22f53ed1e2bc36e > <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 clojure@googlegroups.com > <mailto: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 > <mailto:clojure+unsubscr...@googlegroups.com> > For more options, visit this group at > http://groups.google.com/group/clojure?hl=en > <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 > <mailto:clojure+unsubscr...@googlegroups.com>. > For more options, visit https://groups.google.com/d/optout > <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 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.