-
-
Notifications
You must be signed in to change notification settings - Fork 93
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
racket-xp-mode: Handling very large files #522
Comments
My feelings are:
|
I plan to merge commit 6a911b1 for this.
I think it already is -- it calls the various The Racket Mode back end gathers these into a single response. Partly because that is convenient for "normal" loads. But also because it does some massaging, e.g. turning the one-way arrows into two-way definitions <-> uses, for the kind of "navigate among things" UX you need in lieu of graphical arrows. I could "streamify" that. But ...
Even modulo the gathering/massaing work Racket Mode's back end does -- for instance, if I just make all the So. Streaming the response would indeed prevent Emacs from freezing, on these outlier extremely large files. But I fear it won't help beyond that -- it won't result in a satisfying experience, if the buffer updates in dribbles over 30+ seconds. My gut instinct ATM is that, unless check-syntax itself could work something like 10X faster (if that's even possible??), a streaming redesign of the Racket Mode back end wouldn't be worth it (given the mitigation above). Initially it would just break things for normal size files, until I found and fixed those breakages. But that's just my gut instinct ATM. I'll mull more. |
Just a comment about a likely future direction for this: On the experimental Furthermore, even when Emacs asks us to font-lock some portion of the buffer, we simply mark it "fontified", submit a request to the back end (for the lang lexer stuff to re-run), then return immediately. When the back end eventually returns a response, only then is the information used to apply properties (like With this approach, performance seems good, even for very large buffers. Worst case, some buffer portion might briefly appear un-fontified, then resolve correctly. (Alas I have a recent report where it seems not to be working at all, about which I'm still completely mystified: #642. But presumably the basic idea is still valid (?).) Assuming that approach pans out, and I do merge the |
Via Racket Slack, @samth supplied this example file which is over 8 million bytes and 86,000 lines long.
It seems to take nearly 60 seconds for the Racket Mode back end to run check-syntax and prepare the response.
The response is a single huge s-expression, which after our
elisp-writeln
(which takes about 2 seconds) is about 20,452,540 bytes long.Emacs then seems to freeze when reading the response.
I'm not yet sure how much time is spent attempting an Emacs Lisp
read
of the process buffer text. Since the process filter will be getting text in smaller chunks, theread
is being attempted multiple times before succeeding.If it were to get past that, I'm not sure how much time is spent in the command response handler
dolist
of the response sexpr, adding text properties to the buffer.Clearly the current design isn't intended or able to handle files this large. A 5,000 line file like
drracket/private/unit.rkt
is closer to the envisioned definition of "large".What I don't yet know, is what to do about it.
Simple mitigation
Of course there can be a mitigation: We can supply people a function to use for a
racket-mode-hook
, that is not merelyracket-xp-mode
. Instead of unconditionally enabling that mode, it would checkbuffer-size
.Another mitigation could be, don't change the hook function. Instead, have
racket-xp-mode
itself checkbuffer-size
, and act differently. e.g. Setracket-xp-after-change-refresh-delay
tonil
for such a buffer, and, have the manualracket-xp-annotate
command warn about such buffers."Streaming"
Instead of returning a single response, the back end command could send a stream of notifications.
Although this would probably solve the issue of Emacs "freezing", it's not clear that ~60 seconds of such notifications and updates to the buffer is going to be a good or coherent experience. For example, what if the user edits, prompting a new check-syntax? How/when do we delete text properties for the previous generation?
Don't give Emacs the data and use text properties, at all
Another idea is not to return the data in a command response and insert it as text properties; instead hold it in the back end. Add a command to query it, e.g. "What are the annotations for this interval of the buffer?" Drawbacks here include managing a new source of state in the back end. Also, we consult properties in an Emacs
'pre-redisplay-functions
hook, so we can update things on screen as the user navigates. Now each such movement of point will need to issue a command to the back end; will that be fast enough to be satisfactory?Other?
Probably there are other ideas, which I'm not yet thinking of, with their own tradeoffs, which I don't yet know.
The text was updated successfully, but these errors were encountered: