Open sjkobayashi opened 1 year ago
Yes, this happens because Snail just uses the REPL thread. This problem should go away once #104 is fixed, which I'm starting to think needs to be a priority improvement.
I just released a change which should fix #104 and make this problem go away (a88755d). It'll be in MELPA in a couple of hours. Could you please give it a try and let me know what you think?
Thank you for looking into this! It seems like it works when no computation is involved, but it still hangs when there's computation.
For instance, completion pops up when running the following:
for i in 1:30
println(i)
sleep(1.0)
end
But it hangs when running something like the following:
using BenchmarkTools
@btime exp.(rand(100000));
It probably happens because Snail uses Julia tasks internally to manage concurrency. I will look into converting to (native) threads. I didn't do this initially because I've run into problems with JULIA_NUM_THREADS
before (being unexpectedly set to 1 and therefore not really doing any meaningful multithreading). Thank you for the information, I'll update this ticket when I have some time to work on it.
I see. Did that happen even with --threads=auto
argument?
Oh wow. I didn't know about the auto
option. Since it has been available since 1.7, it means I have not looked into this in a long time. :) Thanks for telling me about it!
I'll definitely look into converting Snail from tasks to threads, then. Not exactly sure how much work it'll take.
Do you think I should also make Snail default to using the auto
thread count option as long as the user hasn't overridden it? Or should I just document that it's a recommended value for julia-snail-extra-args
?
Happy to help! It seems like the -t/--threads
argument takes precedence before JULIA_NUM_THREADS
, so it may be safer to just say that it's a recommended value. A bit unrelated, but you may find this upcoming feature on 1.10 interesting too: https://github.com/JuliaLang/julia/pull/48600
I have threads kind of working on this branch: https://github.com/gcv/julia-snail/tree/experimental-threads
It seems to avoid locking up, but it has another problem: task interruption stopped working (from https://github.com/gcv/julia-snail/issues/104 and https://github.com/gcv/julia-snail/commit/a88755dcb46380d6df2cf54c8e82d5aa15780768). The trick I used to stop a task on the current thread (schedule(task, InterruptException(), error=true)
) causes all kinds of nasty crashes when used on a different thread.
I'm not sure what to do about it. Interrupting computation seems pretty important, but I don't see a robust way to implement it with Julia's current multithreading primitives.
This could change too many things, but is it possible to have another Julia process for code completion? I'm not quite familiar with how VS Code's Julia extension works, but it seems like it uses SymbolServer.jl to obtain info about packages without loading them.
A two-process solution is out of scope for Snail, but it should be possible to combine it with existing LSP tooling. You can disable Snail's non-REPL features as documented on the wiki (someone asked about this before). Then enable LanguageServer.jl. Emacs 29 comes with Eglot pre-installed, or you can try lsp-mode.
For Snail, I think the right solution is to introduce strict separation between computational commands sent to Julia by Snail itself and those sent by the user. The former would go into the :interactive
threadpool, while the latter would be scheduled as tasks on the regular threadpool (documentation: https://docs.julialang.org/en/v1/manual/multi-threading/#man-threadpools). That would keep task interruption working for user-initiated computation, and should keep responsiveness for code completion.
That requires changing the Snail wire protocol to support tagging commands as :system
and :user
, which is a decent amount of work.
Thanks for the suggestion and explanation. I've been using task interruption and find it very useful, so I will look into the language server option for now.
I often run functions that take a lot of time to evaluate (such as simulation and optimization) in Julia's REPL. When REPL is busy, emacs can hang up when
company-mode
automatically tries completion or if I manually invokecompletion-at-point
. I have to repeatedly pressC-g
to unfreeze emacs. I imagine this happens because completion relies on REPL? Is there a way to avoid this other than disablingcompany-mode
?