smartparens icon indicating copy to clipboard operation
smartparens copied to clipboard

Slow text insertion in latex-mode (and others)

Open haji-ali opened this issue 3 years ago • 0 comments

Actual behavior

I've had slow text insertion for a while in my emacs setup and I finally traced it back to smartparens. For example, with smartparens-latex loaded, inserting any text is super slow in some documents when smartparens-mode is on

Steps to reproduce the problem

Make sure smartparens-latex is loaded and smartparens-mode is on and simply insert any text almost anywhere in a large latex document.

Profiler

Here's a profiler output

         853 100%           - sp--post-self-insert-hook-handler
         451  52%            - sp--all-pairs-to-insert
         451  52%             - sp--do-action-p
         365  42%              + sp-in-math-p
          84   9%              - my/enable-exmath-paren
          40   4%               + texmathp
           2   0%              + sp-point-in-string
         402  47%            - sp-insert-pair
         402  47%             - sp--pair-to-insert
         402  47%              - sp--all-pairs-to-insert
         402  47%               - sp--do-action-p
         343  40%                + sp-in-math-p
          59   6%                - my/enable-exmath-paren
          39   4%                 + texmathp

Reason and Solution

The reason for the slow behavior is that many latex specific parentheses call sp-in-math-p which calls texmathp which can be slow in certain cases.

A simple solution that I implemented is to change the order in which sp--all-pairs-to-insert checks valid parentheses so that only matching pairs are action-checked. A possible implementation follows:

(defun sp--all-pairs-to-insert (&optional looking-fn action)
  "Return all pairs that can be inserted at point.
..."
  (setq looking-fn (or looking-fn 'sp--looking-back-p))
  (setq action (or action 'insert))
  (-if-let (trigs
            (--filter (and
                       (plist-get it :trigger)
                       (funcall looking-fn (sp--strict-regexp-quote (plist-get it :trigger)))
                       (sp--do-action-p (plist-get it :open) action))
                      sp-local-pairs))
      (cons :trigger trigs)
    (cons :open
          (--filter (and
                     (funcall looking-fn (sp--strict-regexp-quote (plist-get it :open)))
                     (sp--do-action-p (plist-get it :open) action))
                    sp-local-pairs))))

This already improves the performance of smartparen considerably (For example texmathp is called only once per insertion) and more performance can be gained by making sp--strict-regexp-quote faster by caching the regular-expression instead of reconstructing on the fly in sp--strict-regexp-quote.

I am happy to do a pull-request if this solution is suitable. Similar changes are also worth doing in sp--pair-to-wrap.

Environment & version information

  • smartparens version: 8b6a3c3
  • Active major-mode: emacs-lisp-mode
  • Smartparens strict mode: nil
  • Emacs version (M-x emacs-version): GNU Emacs 28.1 (build 2, x86_64-pc-linux-gnu, GTK+ Version 3.24.33, cairo version 1.16.0) of 2022-09-20
  • Starterkit/Distribution: Vanilla
  • OS: gnu/linux

haji-ali avatar Dec 03 '22 10:12 haji-ali