Skip to content
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

Allow to buffer more input messages #2879

Closed
bkchr opened this issue Jan 20, 2020 · 12 comments
Closed

Allow to buffer more input messages #2879

bkchr opened this issue Jan 20, 2020 · 12 comments

Comments

@bkchr
Copy link
Contributor

bkchr commented Jan 20, 2020

Not sure about the title, but let me explain what I mean. I'm often experiencing some freezes of Emacs when using rust-analzyer. When Emacs freezes, rust-analyzer is normally under high load. I suspected that lsp-mode is not doing some in async fashion, but AFAIK the do the best. They use process-send-string in lisp which can block when the process pipe is full. I suspected that rust-analyzer is not cleaning up stdin fast enough, when the process is under high load. So, I dig a little bit into rust-analyzer and found this: https://github.com/rust-analyzer/lsp-server/blob/master/src/stdio.rs#L19
The stdin thread blocks until the message was consumed. Do you think we could at least add some buffer, maybe 100 messages? Could also be configurable. Or does lsp support throwing away messages and notifying the client?

@ruabmbua
Copy link
Contributor

bounded::<Message>(0) is a special case. cap of 0 means, that both the sender and receiver have to do the operation at the same time. The channel has no actual internal buffer.

See https://docs.rs/crossbeam-channel/0.4.0/crossbeam_channel/fn.bounded.html

I just tried adjusting the channel, which resulted in much higher latency for lsp requests.

I suspect, that the problem is here: https://github.com/rust-analyzer/rust-analyzer/blob/ad10d0c8b91e1db600adb1f323cd71a9ab8dbaac/crates/ra_lsp_server/src/main_loop.rs#L182

When multiple messages are in the queue from the stdio thread to the main loop, it will select over the stdio message channel, and a bunch of other stuff. The select! may not be fair, and randomly select bad things, when multiple recv() are ready at once. I think the 0 sized stdio channel is probably a design choice.

I suggest patching the lsp-mode in emacs, to push requests to the ra_lsp_server in a non blocking fashion. You can write to a pipe in non blocking mode with (O_NONBLOCK) flag set on the file descriptor. No idea how that works in emacs.

@bkchr
Copy link
Contributor Author

bkchr commented Jan 22, 2020

Yeah, I have read the documentation. The latency sounds bad.

The problem with Emacs, AFAIU they are do the best what they in the plugin with async in Emacs. This "async" interface of Emacs just blocks when the pipe is full.

@matklad
Copy link
Member

matklad commented Jan 22, 2020 via email

@bkchr
Copy link
Contributor Author

bkchr commented Jan 22, 2020

Yeah no problem @matklad :)
I just observe rust-analyzer running with like 100%+ cpu usage and my Emacs freezes. Ctrl + g works for a moment and it freezes again. Killing the rust-analyzer process let's it unfreeze directly and I don't encounter them anymore. I already "debugged" where it hangs in Emacs and it is always process-send-string.

@ruabmbua
Copy link
Contributor

Yeah no problem @matklad :)
I just observe rust-analyzer running with like 100%+ cpu usage and my Emacs freezes. Ctrl + g works for a moment and it freezes again. Killing the rust-analyzer process let's it unfreeze directly and I don't encounter them anymore. I already "debugged" where it hangs in Emacs and it is always process-send-string.

@bkchr Could you try to take a backtrace of the running ra_lsp_server?

E.g. with gdb -p $(pidof ra_lsp_server) -ex "backtrace".

I think there is a currently a known issue, where all threads get stuck somewhere, and only one thread is working at 100%: #2812

@bkchr
Copy link
Contributor Author

bkchr commented Jan 23, 2020

@ruabmbua I will do when I encounter it.

However, I will test this now: #2898

The pr description about cargo and responsiveness sounds like it could be related to the problems I see.

@bkchr
Copy link
Contributor Author

bkchr commented Jan 23, 2020

@ruabmbua still with my old version:

#0  0x0000556afdafd73f in alloc::raw_vec::RawVec<T,A>::reserve ()
#1  0x0000556afd881dc9 in <chalk_rust_ir::ImplDatum<TF> as chalk_solve::clauses::program_clauses::ToProgramClauses<TF>>::to_program_clauses ()
#2  0x0000556afdba8f2e in chalk_solve::clauses::program_clauses_for_goal ()
#3  0x0000556afdbe6c91 in <chalk_solve::solve::slg::SlgContextOps<TF> as chalk_engine::context::ContextOps<chalk_solve::solve::slg::SlgContext<TF>>>::program_clauses ()
#4  0x0000556afd87b130 in chalk_engine::logic::<impl chalk_engine::forest::Forest<C>>::push_initial_strands_instantiated ()
#5  0x0000556afd87e61b in chalk_engine::logic::<impl chalk_engine::forest::Forest<C>>::get_or_create_table_for_ucanonical_goal ()
#6  0x0000556afd874ed1 in chalk_engine::logic::<impl chalk_engine::forest::Forest<C>>::ensure_root_answer ()
#7  0x0000556afd872a97 in <chalk_engine::forest::ForestSolver<C,CO> as chalk_engine::context::AnswerStream<C>>::peek_answer ()
#8  0x0000556afdbe4c69 in chalk_solve::solve::slg::aggregate::<impl chalk_engine::context::AggregateOps<chalk_solve::solve::slg::SlgContext<TF>> for chalk_solve::solve::slg::SlgContextOps<TF>>::make_solution ()
#9  0x0000556afd87e940 in chalk_engine::forest::Forest<C>::solve ()
#10 0x0000556afd84e023 in std::panicking::try::do_call ()
#11 0x0000556afddd03ba in __rust_maybe_catch_panic ()
#12 0x0000556afdb447b1 in ra_hir_ty::traits::trait_solve_query ()
#13 0x0000556afd8de82f in salsa::runtime::Runtime<DB>::execute_query_implementation ()
#14 0x0000556afda6eb5b in salsa::derived::slot::Slot<DB,Q,MP>::read_upgrade ()
#15 0x0000556afdac89da in salsa::derived::slot::Slot<DB,Q,MP>::read ()
#16 0x0000556afdb2a034 in <salsa::derived::DerivedStorage<DB,Q,MP> as salsa::plumbing::QueryStorageOps<DB,Q>>::try_fetch ()
#17 0x0000556afd80bc36 in salsa::QueryTable<DB,Q>::get ()
#18 0x0000556afd97b170 in ra_hir_ty::infer::InferenceContext<D>::resolve_ty_as_possible ()
#19 0x0000556afd988abb in ra_hir_ty::infer::expr::<impl ra_hir_ty::infer::InferenceContext<D>>::infer_expr_coerce ()
#20 0x0000556afd981c64 in ra_hir_ty::infer::expr::<impl ra_hir_ty::infer::InferenceContext<D>>::infer_expr_inner ()
#21 0x0000556afd988868 in ra_hir_ty::infer::expr::<impl ra_hir_ty::infer::InferenceContext<D>>::infer_expr_coerce ()
#22 0x0000556afd97961c in ra_hir_ty::infer::do_infer_query ()
#23 0x0000556afd8e2e36 in salsa::runtime::Runtime<DB>::execute_query_implementation ()
#24 0x0000556afda816e0 in salsa::derived::slot::Slot<DB,Q,MP>::read_upgrade ()
#25 0x0000556afdac5c48 in salsa::derived::slot::Slot<DB,Q,MP>::read ()
#26 0x0000556afdb2740f in <salsa::derived::DerivedStorage<DB,Q,MP> as salsa::plumbing::QueryStorageOps<DB,Q>>::try_fetch ()
#27 0x0000556afd847e37 in ra_hir_ty::db::infer ()
#28 0x0000556afd74e40f in ra_hir::code_model::Function::diagnostics ()
#29 0x0000556afd74d683 in ra_hir::code_model::Module::diagnostics ()
#30 0x0000556afd925c69 in ra_ide::diagnostics::diagnostics ()
#31 0x0000556afd84c52e in std::panicking::try::do_call ()
#32 0x0000556afddd03ba in __rust_maybe_catch_panic ()
#33 0x0000556afd808c3b in ra_db::CheckCanceled::catch_canceled ()
#34 0x0000556afd746db6 in ra_ide::Analysis::diagnostics ()
#35 0x0000556afd5af508 in ra_lsp_server::main_loop::handlers::publish_diagnostics ()
#36 0x0000556afd450934 in ra_lsp_server::main_loop::loop_turn ()
#37 0x0000556afd44d7b1 in ra_lsp_server::main_loop::main_loop ()
#38 0x0000556afd43448b in ra_lsp_server::main ()
#39 0x0000556afd3e8293 in std::rt::lang_start::{{closure}} ()
#40 0x0000556afddbebc3 in std::panicking::try::do_call ()
#41 0x0000556afddd03ba in __rust_maybe_catch_panic ()
#42 0x0000556afddc7989 in std::rt::lang_start_internal ()
#43 0x0000556afd434e12 in main ()

@bkchr
Copy link
Contributor Author

bkchr commented Jan 23, 2020

All the other threads are waiting for some condition.

@ruabmbua
Copy link
Contributor

Yeah looks pretty similar.

@bkchr
Copy link
Contributor Author

bkchr commented Jan 23, 2020

As this also comes from the main_loop, it could explain why stdin is not processed.

@ruabmbua
Copy link
Contributor

Yeah, if there is no thread currently waiting in the mainloop, then nothing will happen. On which OS are you? -> Also, I suggest moving this discussion to #2812

@bkchr
Copy link
Contributor Author

bkchr commented Jan 23, 2020

I'm on Linux. Yeah I close this issue.

@bkchr bkchr closed this as completed Jan 23, 2020
RalfJung pushed a commit to RalfJung/rust-analyzer that referenced this issue Apr 20, 2024
Include the current Crate name in the measureme output name

See https://rust-lang.zulipchat.com/#narrow/stream/182449-t-compiler.2Fhelp/topic/measureme.20flamegraph.20panics/near/356367013
cc `@andjo403`

Currently, attempting to use `MIRIFLAGS=-Zmiri-measureme=miri cargo miri test` on a crate with multiple test targets (which is very common) will produce a corrupted measureme output file, because the various interpreter processes will stomp each other's output.

This change does not entirely prevent this, but the various test targets seem to always have different crate names, so if nothing else this will make the broken measureme files much harder to encounter by accident, while also making it clear what they are all for.
RalfJung pushed a commit to RalfJung/rust-analyzer that referenced this issue Apr 27, 2024
Include the current Crate name in the measureme output name

See https://rust-lang.zulipchat.com/#narrow/stream/182449-t-compiler.2Fhelp/topic/measureme.20flamegraph.20panics/near/356367013
cc `@andjo403`

Currently, attempting to use `MIRIFLAGS=-Zmiri-measureme=miri cargo miri test` on a crate with multiple test targets (which is very common) will produce a corrupted measureme output file, because the various interpreter processes will stomp each other's output.

This change does not entirely prevent this, but the various test targets seem to always have different crate names, so if nothing else this will make the broken measureme files much harder to encounter by accident, while also making it clear what they are all for.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants