Open joinr opened 5 years ago
Thanks for the report! We'll investigate this further. //cc @cichli I have some doubts that this might be some poor interaction with the content-type middleware in cider-nrepl, but this has to be confirmed.
I'm not sure if this should be a separate issue or falls into this one, but rapid printing inside CIDER's REPL in general hangs Emacs pretty hard. E.g. the following code hangs Emacs without ability to interrupt or recover it:
(doseq [i (range)] (println i))
If I call the same thing in C-u M-x inferior-lisp RET clojure RET
it doesn't hang and prints very fast.
Additional info, when I force my way through, eighter by killing the java process, and killing the REPL buffer, or being lucky enough for interrupt action to register, Emacs is still pretty much hanging, continuing printing buffered text, and probably collecting a lot of garbage, as it seems.
This is very annoying when I do debugging via printing, and there are tight loops I want to debug. Basically I have to insert (Thread/sleep 300)
after such prints to be sure that I will not hang Emacs.
Running the (dotimes [i 200000] (println i))
snippet results in a significant slowdown in the REPL, making emacs hang completely at some point (tested with emacs -Q
). Doing a CPU profiling at the same time the report shows a lot of GC and some slowness in the nrepl-client-filter
.
I was hoping that solving #3219 would also make this case less problematic but the behavior seems unchanged.
A lot of times this happens unexpectedly when I decide to add logging to some tight loop to debug it, and I often have to kill the java
process to make emacs responsible again. Which kills the program's state, though it is less painful when Emacs crashes because of this (which happened to me a few times).
When printing a large string, as described in the issue, the situation is almost the same - most of the time spent collecting garbage:
I wonder if it's somehow related to pprint (which I think is what cider is actually using by default, and is an implicit "gotcha").
My 2c - the 1MB limiting works as intended, from what I can see, but even when that is accomplished, it does not suffice to prevent Emacs from suffering.
As it's well-known, basically any long line will make Emacs struggle.
We use pprint, which play to our advantage, since most times it means that no long lines are generated.
So, a common red path is when:
Perhaps repl printing internals could have some sort of "long line avoidance" mechanism? Don't know if it's been attempted before.
I'd imagine that it can easily backfire in terms of performance - running logic on every insert can be expensive. But perhaps there's opportunity.
Expected behavior
Cider 0.21 should - upon trying to print large amounts of text (e.g. > 1mb) gracefully halt for us, and during printing, print in chunks as to enable user interruption.
Actual behavior
When working with a ~3mb tab delimited text file, Cider tries to chunk print, but grinds to a halt as emacs starts to freeze. If user is fast enough and interrupts, the REPL is recoverable (this must happen within the first few chunks of printing). If user does not interrupt, and lets the printing continue unabated, Cider does not seem to reach the graceful cutoff point (I let it run for about 30s just to see). User can interrupt cider only with (cider-interrupt). At that point, REPL prompt reappears, but further evaluation is disabled. It seems like the nREPL process is hung up. CPU utilization confirms emacs is still grinding trying to do something (20% vs. 0% resting).
Steps to reproduce the problem
Given the uncompressed raw text file stored in gzipped format here at path "path-to-file", from the repl:
Environment & Version information
CIDER version information
CIDER 0.21.0 (New York), nREPL 0.6.0 Clojure 1.10.0, Java 1.8.0_181
Lein/Boot version
leiningen 2.9.1
Emacs version
25.3
Operating system
Windows 10