bug-gnu-emacs
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

bug#41200: Displaying a tooltip with x-show-tip gets very slow as more f


From: Clément Pit-Claudel
Subject: bug#41200: Displaying a tooltip with x-show-tip gets very slow as more faces are defined
Date: Tue, 12 May 2020 22:41:24 -0400
User-agent: Mozilla/5.0 (X11; Linux x86_64; rv:68.0) Gecko/20100101 Thunderbird/68.7.0

On 12/05/2020 11.27, Eli Zaretskii wrote:
> (The code is actually in a subroutine called by internal-lisp-face-p.)
> Which means face-set-after-frame-default, which loops over all of the
> faces, runs with O(n²) complexity in the number of faces.
> 
> So I think if we want to support such large amounts of faces, we
> should not store them in alists, but in a more efficient data
> structure.

Indeed, you're completely right; thanks!  Replacing face_alist and 
Vface_new_frame_defaults with hash tables makes the worst example about 10 
times faster, and with that change tooltips now take 30 to 50ms to display 
instead of 500-600ms in my real-life use case (my usual config).  I have 
attached a patch.

I left a few questions in the code; I hope that's OK.  I have a few more 
questions that are not part of the code:

* I removed the function frame-face-alist and changed the type of the variable 
face-new-frame-defaults.  Both were documented as internal.  Should I add an 
ELisp implementation of frame-face-alist for compatibility?  (It wouldn't be a 
perfect shim, since modifying its return value wouldn't do the same).  For 
face-new-frame-defaults it's a bit trickier, since the variable now holds a 
hash table.  Should I change its name to make the change obvious, at least? 
* The name face_hash isn't ideal, since there's already a distinct notion of 
face hashes (hash codes).  Can you think of a better name? 
* I imagine that this change needs to be advertised somewhere, but I'm not sure 
where; NEWS?

Lastly, do the following new profiles suggest other opportunities for 
improvement?

- ...                                                             499  52%
   Automatic GC                                                   499  52%
- command-execute                                                 454  47%
 - call-interactively                                             454  47%
  - funcall-interactively                                         433  45%
   - eval-defun                                                   427  44%
    - elisp--eval-defun                                           427  44%
     - eval-region                                                426  44%
      - my-bench-x-tip                                            426  44%
       - let                                                      406  42%
        - list                                                    406  42%
         - let                                                    406  42%
          - x-show-tip                                            390  40%
           - face-set-after-frame-default                         387  40%
            - face-spec-recalc                                    374  39%
             - make-face-x-resource-internal                      296  30%
              - set-face-attributes-from-resources                273  28%
               - set-face-attribute-from-resource                 219  22%
                + face-name                                        65   6%
             + face-spec-reset-face                                62   6%
             + face-spec-set-2                                      6   0%
             + face-spec-choose                                     2   0%
            + face-list                                             2   0%
           + frame-windows-min-size                                 1   0%
       + my-def-many-faces                                         20   2%
     + end-of-defun                                                 1   0%
   + execute-extended-command                                       6   0%
  + byte-code                                                      21   2%
+ redisplay_internal (C function)                                   2   0%
  tooltip-hide                                                      1   0%

- command-execute                                                 768  80%
 - call-interactively                                             768  80%
  - apply                                                         768  80%
   - call-interactively@ido-cr+-record-current-command                768  80%
    - apply                                                       768  80%
     - #<subr call-interactively>                                 768  80%
      - funcall-interactively                                     768  80%
       - eval-defun                                               715  74%
        - apply                                                   713  74%
         - #<compiled 0x151e3cbebf653c17>                         712  74%
          - elisp--eval-defun                                     712  74%
           - eval-region                                          709  74%
            - apply                                               709  74%
             - #<lambda 0x32ad1cc4311e0c0>                        709  74%
              - endless/eval-overlay                              709  74%
               - apply                                            709  74%
                - #<subr eval-region>                             707  74%
                 - my-bench-x-tip                                 707  74%
                  - let                                           689  72%
                   - list                                         689  72%
                    - let                                         689  72%
                     - x-show-tip                                 676  70%
                      - face-set-after-frame-default                674  70%
                       - face-spec-recalc                         660  69%
                        - face-spec-set-2                         350  36%
                         - apply                                  348  36%
                          - set-face-attribute                    342  35%
                           - internal-set-lisp-face-attribute                
342  35%
                            - frame-set-background-mode                331  34%
                             - face-spec-recalc                   284  29%
                              - make-face-x-resource-internal                
235  24%
                               - set-face-attributes-from-resources             
   216  22%
                                - set-face-attribute-from-resource              
  174  18%
                                 - face-name                       36   3%
                                  + check-face                     21   2%
                              + face-spec-reset-face                 40   4%
                              + face-spec-set-2                     4   0%
                             + face-attr-match-p                   24   2%
                               face-spec-choose                     1   0%
                             + face-list                            1   0%
                        - make-face-x-resource-internal                248  25%
                         - set-face-attributes-from-resources                
215  22%
                          - set-face-attribute-from-resource                169 
 17%
                           + face-name                             36   3%
                        + face-spec-reset-face                     54   5%
                        + face-spec-choose                          2   0%
                       + face-list                                  1   0%
                  + my-def-many-faces                              18   1%
           + beginning-of-defun                                     1   0%
             end-of-defun                                           1   0%
        + #<lambda 0x159f62efd027a>                                 2   0%
       + smex                                                      53   5%
- ...                                                             182  19%
   Automatic GC                                                   182  19%
+ redisplay_internal (C function)                                   3   0%

Also, since the GC seems to be a significant part, here's a memory profile:

- command-execute                                         305,314,261  99%
 - call-interactively                                     305,314,261  99%
  - funcall-interactively                                 305,262,257  99%
   - eval-defun                                           303,318,241  98%
    - elisp--eval-defun                                   303,317,185  98%
     - eval-region                                        303,296,332  98%
      - my-bench-x-tip                                    303,295,276  98%
       - let                                              273,049,377  89%
        - list                                            273,049,377  89%
         - let                                            273,049,377  89%
          - x-show-tip                                    177,538,262  57%
           - face-set-after-frame-default                 175,519,190  57%
            - face-spec-recalc                            174,935,046  57%
             - make-face-x-resource-internal              138,435,960  45%
              + set-face-attributes-from-resources        138,407,728  45%
             + face-spec-reset-face                        36,126,838  11%
             + face-spec-choose                                74,360   0%
             + face-spec-set-2                                 21,216   0%
            + face-list                                       554,400   0%
           + frame-windows-min-size                             7,676   0%
           + run-at-time                                        4,352   0%
            setq                                                4,224   0%
          + float-time                                          3,888   0%
       + my-def-many-faces                                 30,245,899   9%
      + internal-macroexpand-for-load                           1,056   0%
     + end-of-defun                                             4,160   0%
     + beginning-of-defun                                       2,112   0%
   + execute-extended-command                               1,944,016   0%
  + byte-code                                                  52,004   0%
+ redisplay_internal (C function)                           1,427,117   0%

> No Emacs version information?

Woops. Sorry! GNU Emacs 28.0.50 (build 10, x86_64-pc-linux-gnu, GTK+ Version 
3.22.30, cairo version 1.15.10) of 2020-05-10

Thanks again for the pointers,
Clément.

Attachment: 0001-Store-frame-faces-in-hash-tables-instead-of-alists.patch
Description: Text Data


reply via email to

[Prev in Thread] Current Thread [Next in Thread]