From: Dmitry Gutov <dgutov@yandex.ru>
To: Helmut Eller <eller.helmut@gmail.com>, 50906@debbugs.gnu.org
Subject: bug#50906: xref-find-references blocks Emacs: asynchronous operation?
Date: Tue, 5 Oct 2021 19:38:36 +0300 [thread overview]
Message-ID: <6f2c07d4-3e29-44c0-bb7f-c37905b3e12b@yandex.ru> (raw)
In-Reply-To: <m2a6jo0ytj.fsf@gmail.com>
On 05.10.2021 09:29, Helmut Eller wrote:
> On Tue, Oct 05 2021, Dmitry Gutov wrote:
>
>> What can be done here:
>>
>> - Design an "asynchronous" format for xref-show-xrefs-function to
>> consume. FETCHER of a different shape. Not sure how it's going to
>> work in the end -- maybe a simple-ish iterator (call a function
>> again for more results), but ideally it would look synchronous
>> somehow, and the concurrency would be achieved through the use of
>> threads. Not sure if that's realistic.
>>
>> - The new kind of fetcher would need to provide a way to abort the
>> search, since 'C-g' would not be available anymore.
>>
>> - Implement it for the common searches of course.
>
> I think promises, as used in the Javascript world, would be a good fit
> for this kind of problem. Something like this:
> https://github.com/chuntaro/emacs-promise.
A promise is something that resolves once. We could build on top of this
concept, but what's really needed is some sort of a lazy sequence
(Clojure-style), or a sequence of chunks.
>> Downsides:
>>
>> - No way to quickly 'C-g' out of a search, supposedly one would have
>> to switch to the results buffer (maybe it will be selected right
>> away) and type 'C-c C-c'. And then kill the buffer, I guess?
>
> Maybe we could have some "promise framework" that solves this problem
> more generally, e.g., a list-promises command that works like
> list-processes and offers a command to cancel promises.
It would need be accessible by the code handling the "abort" command,
not just by some special UI accessible to the user separately.
But some Promise/Future implementations include the "abort"
functionality, so it can work together.
>> - The size threshold of a project where the improvement will be
>> significant is pretty big -- for instance, searching across the
>> Emacs checkout takes about 100-200ms (just the time the external
>> process uses). If the search results in many matches (1000s or
>> 10000s) the results will take a while to display, but most of the
>> time is taken up by processing of results which is implemented in
>> Lisp. We might have Emacs which shows the first results soon, but
>> then remains sluggish until all search results are processed. This
>> problem could be worked around, however, by limiting the displayed
>> number of results and having buttons like the ones at the bottom of
>> vc-print-root-log output buffer.
>>
>> - Search results come in unsorted, and, in the case of ripgrep, sorted
>> randomly every time the search is performed (the files, at
>> least). We sort them now at the bottom of xref-matches-in-files, but
>> asynchronous search results would make that infeasible.
>
> This is a good point and probably quite difficult to solve. I'm
> wondering if it would be possible to build some kind of index, like
> search engines do. So instead of grepping, we'd use the index and maybe
> invest more effort in ranking the results?
For xref-find-references in particular, you can build an index using 'ID
Utils' already, and the search will be fast. The downside is you will
need to update this index manually when the project changes. E.g. when
you switch to a different repository branch.
And the ripgrep devs are working on something similar:
https://github.com/BurntSushi/ripgrep/issues/1497
Not sure how far off in the future that is, though.
A really fast searcher solves the biggest part of the problem, but we'd
still be left with very imprecise searches (many matches) locking up
Emacs for seconds, since the Lisp overhead processing a match is
unavoidably larger than the time it takes for a search program to print
it. Using lazy sequences could allow us some leeway as well -- namely,
processing only the first N hits initially, and then processing the rest
only if the user requests that.
If we only target this kind of improvement, the "abort" functionality
could wait. We'd still need to choose between sorting the results and
saving on parsing the output buffer eagerly, though.
next prev parent reply other threads:[~2021-10-05 16:38 UTC|newest]
Thread overview: 9+ messages / expand[flat|nested] mbox.gz Atom feed top
2021-09-29 22:49 bug#50906: xref-find-references blocks Emacs: asynchronous operation? Stefan Kangas
2021-09-30 7:44 ` Daniel Martín via Bug reports for GNU Emacs, the Swiss army knife of text editors
2021-10-05 1:59 ` Dmitry Gutov
2021-10-05 5:18 ` Arthur Miller
2021-10-05 15:11 ` Dmitry Gutov
2021-10-05 6:29 ` Helmut Eller
2021-10-05 16:38 ` Dmitry Gutov [this message]
2021-10-05 18:09 ` Helmut Eller
2021-10-05 19:24 ` Dmitry Gutov
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=6f2c07d4-3e29-44c0-bb7f-c37905b3e12b@yandex.ru \
--to=dgutov@yandex.ru \
--cc=50906@debbugs.gnu.org \
--cc=eller.helmut@gmail.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
Code repositories for project(s) associated with this external index
https://git.savannah.gnu.org/cgit/emacs.git
https://git.savannah.gnu.org/cgit/emacs/org-mode.git
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.