smartparens
smartparens copied to clipboard
Use input-pending-p to short-circuit sp-show--pair-function
sp-show--pair-function
can be relatively slow (150ms in some of my files). When using show-smartparens-mode
this can be stutters in moving around or typing if it kicks in.
I've had a lot of success increasing perceived performance by monitoring (input-pending-p)
in tight loops for things that become irrelevant after the point moves. For example: https://github.com/company-mode/company-mode/pull/720
I tried adding a (not (input-pending-p))
to the and
in the while
of sp--looking-back
and it fixed the stutter for me. I don't know if that's the most appropriate place to put it and/or if that will have bad effects in other was (it probably will). So I'm curious if there's somewhere off of sp-show--pair-function
that would be more appropriate to short circuit when there is pending input?
Thanks!
Here's a profile fwiw:
- timer-event-handler 1737 83%
- apply 1737 83%
- sp-show--pair-function 1596 76%
- when 1596 76%
- if 1595 76%
- progn 1595 76%
- sp--with-case-sensitive 1595 76%
- if 1595 76%
- let 1593 76%
- save-match-data 1593 76%
- let 1593 76%
- unwind-protect 1593 76%
- progn 1593 76%
- cl-labels 1586 76%
- let 1586 76%
- let* 1586 76%
- cond 1583 75%
- funcall 1583 75%
- #<lambda 0x170d4ad7f9184e28> 1581 75%
- let 1581 75%
- sp-get-thing 1581 75%
- sp--with-case-sensitive 1581 75%
- if 1581 75%
- cond 1581 75%
- if 1581 75%
- if 1581 75%
- save-excursion 1581 75%
- cond 1581 75%
- cond 1581 75%
- and 1578 75%
- or 1578 75%
- and 1578 75%
- sp--looking-back 1578 75%
- sp--with-case-sensitive 1578 75%
- if 1578 75%
- let 1578 75%
- if 1578 75%
- save-excursion 1578 75%
- save-match-data 1578 75%
- let 1578 75%
- unwind-protect 1578 75%
- progn 1578 75%
- while 1577 75%
- if 1552 74%
- and 1528 73%
save-excursion 1489 71%
Oh this is interesting.
We are using a timer to start the "show job" after 0.125s of inactivity which is enough for most people's typing speed, but when navigating around I can see how you might fall into that interval and get blocked.
I don't know where to put the short circuit, but I would most definitely not put it inside the sp--looking-back
function. I'm probably misunderstanding you though.
Can you open a pull request with your change? I like the proposal and it seems you have a solution so I'll be very happy to move this forward.
I think another question is... why does this js file (rjsx-mode
) that I have run so many loop iterations:
;; within the sp--looking-at-p while loop:
(message "%S %S %S" regexp limit sp-max-pair-length)
"\\(?:\\(?:\\(?:\\\\\\(?:\\\\[()]\\|[(){}]\\)\\|[]()<>[{}]\\)\\)\\)" 10 10 [10 times]
"\\(?:\\\\\"\\|[\"'`]\\)" 10 10 [10 times]
">" 10 10 [10 times]
"</?" 15222 10 [15222 times]
"\\\\" 2 10 [2 times]
I've been experiencing dropped keystrokes on Windows when typing quickly and bisecting led me to suspect smartparens. Adding this change eliminated the drops in buffers. Now Emacs hangs for a second but then will finish accepting characters. Before it would ignore any keystrokes from during the hang. However, I'm still experiencing dropped keystrokes while isearching which may or may not be related. I know that some of my packages have exhibited weird performance due to Windows Emacs' GC peculiarities.
In any case would like to move this issue forward, let me know what the best way to help is.
/cc #943
Not on Windows any more so I can't say if it fixed my usecase or not. I'll update and cross my fingers though!
What's the current status on this? As far as I could find, the while-no-input
solution was merged and reverted because it was causing bugs. The solution suggested here might not be as pretty, but it seems to do the job. Does it cause the same bugs?
I guess that the best solution to the underlying problem would be to run it asynchronously and interrupt it if no longer necessary (e.g. point moved or text inserted), but it is also a lot more complicated. Adding short-circuits seems to work as a cheaper work-around.
The emacs manual has this warning:
Do not write an idle timer function containing a loop which does a certain amount of processing each time around, and exits when (input-pending-p) is non-nil. This approach seems very natural but has two problems:
- It blocks out all process output (since Emacs accepts process output only while waiting).
- It blocks out any idle timers that ought to run during that time.
It's not quite the same situation, but it means that the function will still block some emacs functions while running. Sadly, the manual doesn't seem to offer any alternative.
@ThibautVerron It's likely that https://github.com/Fuco1/smartparens/pull/958 is still the best option. Now that Emacs 27 is released, we could pull the actual release version if it's any different and use that.
I've rebased the PR and confirmed that while-no-input
is the same version as in Emacs 27.1