Subject: bug#59641: term is very slow

From: Akib Azmain Turja <[email-masked]>
Date: Sat, 17 Dec 2022 18:32:09 +0600

I missed this again!  There is definitely something wrong.  Anyway...

Eli Zaretskii <[email-masked]> writes:

>> From: Akib Azmain Turja <[email-masked]>
>> Cc: [email-masked]
>> Date: Sat, 17 Dec 2022 00:29:02 +0600
>> 
>> >> Here are the reports (attached), but don't seem to be human readable:
>> >
>> > Copy them from the display shown by profiler-report, after you expand it
>> > completely.
>> >
>> > And the "cpu" profile is enough; the "mem" one doesn't add anything useful.
>> 
>> Sorry, I missed this reply.  I found this in debbugs.gnu.org.  :O
>> 
>> Here is the data:  (I didn't redo the steps, I just did
>> 'M-x profiler-find-profile RET path/to/profile'.  ;)  )
>> 
>> --8<---------------cut here---------------start------------->8---
>>         9397  95% - term-emulate-terminal
>>         2710  27%  - term-handle-ansi-escape
>>         1831  18%   - term-down
>>            8   0%      term-move-columns
>>          765   7%   - term-goto
>
> Doesn't surprise me: most of the time is spent in term.el's business
> logic, not in Emacs display primitives.

I know that very well.

>
> If you want to work on speeding up term.el, I suggest to start by
> loading term.el (not term.elc) manually, and repeating the profiling
> session.  That could tell you in more detail where are the hot sports
> in those functions at the top of the profile.  Then some clever
> optimization ideas are needed to make it significantly faster.
>
> Thanks.

I guess the hot spot here is 'vertical-motion'.  'vertical-motion' takes
various things into account, which are unnecessary for a terminal
emulator.  Eat implements its own motion functions, which make their own
assumptions (e.g. each character takes exactly one column, each line
finishes with a newline, etc).  I guess this might be a reason why Eat
is faster.

Note that I'm the author of Eat, and Term is a direct competitor of Eat.
So although I want Term to be faster, I will be of course biased if I
try to improve Term.  But don't get me wrong, I really want Term to do
better; competition is fun when you have tough competitors!

Here is the CPU profile data, with 'term.el' loaded:

--8<---------------cut here---------------start------------->8---
        1551  87% - term-emulate-terminal
        1551  87%  - if
        1551  87%   - progn
        1551  87%    - save-current-buffer
        1515  85%     - let*
        1515  85%      - let
        1515  85%       - save-current-buffer
        1515  85%        - unwind-protect
        1515  85%         - progn
        1361  76%          - save-restriction
        1361  76%           - while
        1341  75%            - let
        1130  63%             - let*
        1126  63%              - cond
        1126  63%               - let
         586  33%                - funcall
         108   6%                 - vertical-motion
         100   5%                  - jit-lock-function
          84   4%                   - jit-lock-fontify-now
          64   3%                    - jit-lock--run-functions
          24   1%                     - #<compiled -0x1546ff15e132d103>
          24   1%                      - font-lock-fontify-region
          24   1%                         font-lock-default-fontify-region
          20   1%                     - #<compiled -0x1540f7d5aaa5a503>
          20   1%                        font-lock-fontify-region
           4   0%                     - #<compiled -0x1546e4779f110a03>
           4   0%                      - font-lock-fontify-region
           4   0%                       - font-lock-default-fontify-region
           4   0%                        - font-lock-extend-region-wholelines
           4   0%                           syntax-propertize-wholelines
           4   0%                       #<compiled -0x15468ebfcfc1d703>
           4   0%                     - #<compiled -0x15464f08f89a1f03>
           4   0%                      - font-lock-fontify-region
           4   0%                       - font-lock-default-fontify-region
           4   0%                          #<compiled -0x7e8feab343044be>
         532  30%                - if
         528  29%                 - term-down
         528  29%                  - let
         344  19%                   - if
         304  17%                    - if
         304  17%                     - progn
         304  17%                      - setq
         300  16%                       - -
         300  16%                        - funcall
          56   3%                         - vertical-motion
          52   2%                          - jit-lock-function
          48   2%                           - jit-lock-fontify-now
          32   1%                            - jit-lock--run-functions
          12   0%                             - #<compiled -0x1546ecc8334f3d03>
          12   0%                                font-lock-fontify-region
           8   0%                             - #<compiled -0x1546d143afc77e03>
           8   0%                              - font-lock-fontify-region
           8   0%                                 font-lock-default-fontify-region
           8   0%                             - #<compiled -0x1546c17e6a2d8c03>
           8   0%                              - font-lock-fontify-region
           8   0%                               - font-lock-default-fontify-region
           8   0%                                  font-lock-extend-region-wholelines
          28   1%                    - progn
          28   1%                     - term-move-columns
          28   1%                      - term-move-to-column
          28   1%                         let
           4   0%                    - and
           4   0%                       =
           4   0%                      term-adjust-current-row-cache
         184  10%                   - cond
         176   9%                    - term-insert-char
         172   9%                     - let
          56   3%                      - put-text-property
          20   1%                         jit-lock-after-change
           4   0%                         syntax-ppss-flush-cache
          48   2%                      - insert-char
          20   1%                         jit-lock-after-change
           4   0%                and
         203  11%             - if
         187  10%              - progn
         147   8%               - let
          24   1%                - progn
          24   1%                   setq
          24   1%                - put-text-property
           8   0%                   jit-lock-after-change
          20   1%                - insert
           8   0%                   jit-lock-after-change
           4   0%                - term-horizontal-column
           4   0%                 - -
           4   0%                  - term-current-column
           4   0%                   - cond
           4   0%                      setq
           8   0%                 setq
           8   0%                 if
          16   0%              setq
         136   7%          - if
         136   7%           - progn
         136   7%            - term-handle-deferred-scroll
         136   7%             - let
         136   7%              - if
         136   7%               - progn
         136   7%                - save-excursion
         136   7%                   funcall
          18   1%          - while
          18   1%           - progn
          18   1%            - if
          18   1%             - progn
          18   1%              - let
          18   1%               - if
          18   1%                - progn
          18   1%                 - if
          18   1%                    not
          36   2%     - if
          36   2%      - progn
          36   2%       - redisplay
           4   0%        - redisplay_internal (C function)
           4   0%         - eval
           4   0%            if
         171   9% - ...
         171   9%    Automatic GC
          40   2% - command-execute
          22   1%  - byte-code
          22   1%   - read-extended-command
          22   1%    - read-extended-command-1
           8   0%       completing-read-default
          18   1%  - funcall-interactively
          10   0%   - minibuffer-complete
          10   0%    - completion-in-region
          10   0%     - completion--in-region
           6   0%      - #<compiled -0x737dfeebbd42962>
           6   0%       - apply
           6   0%        - #<compiled 0x147bf53b9756e246>
           6   0%         - completion--in-region-1
           6   0%          - completion--do-completion
           6   0%           - completion-try-completion
           6   0%            - completion--nth-completion
           6   0%             - completion--some
           6   0%              - #<compiled -0xb70f507d86b95cc>
           6   0%               - completion-basic-try-completion
           6   0%                - #<subr F616e6f6e796d6f75732d6c616d626461_anonymous_lambda_54>
           6   0%                   complete-with-action
           4   0%      - #<compiled -0x737dfeebbd42962>
           4   0%       - apply
           4   0%        - #<compiled 0x147bf53b9756e246>
           4   0%         - completion--in-region-1
           4   0%          - completion--do-completion
           4   0%           - completion-try-completion
           4   0%            - completion--nth-completion
           4   0%             - completion--some
           4   0%              - #<compiled -0xb70f507d86b95cc>
           4   0%               - completion-pcm-try-completion
           4   0%                - completion-pcm--find-all-completions
           4   0%                 - completion-pcm--all-completions
           4   0%                  - #<subr F616e6f6e796d6f75732d6c616d626461_anonymous_lambda_54>
           4   0%                     complete-with-action
           8   0%   - execute-extended-command
           8   0%    - command-execute
           8   0%       funcall-interactively
           7   0% - timer-event-handler
           7   0%  - apply
           4   0%     #<compiled -0xabecf6a07658066>
           3   0%   - #<compiled -0xabecf6a07658066>
           3   0%      execute-extended-command--shorter
           2   0% - redisplay_internal (C function)
           2   0%  - term--update-term-menu
           2   0%   - if
           2   0%    - progn
           2   0%     - let
           2   0%      - easy-menu-change
           2   0%       - mapcar
           2   0%        - #<lambda 0x1984cdb809973d69>
           2   0%         - vector
           2   0%            format
--8<---------------cut here---------------end--------------->8---

-- 
Akib Azmain Turja, GPG key: 70018CE5819F17A3BBA666AFE74F0EFA922AE7F5
Fediverse: [email-masked]
Codeberg: akib
emailselfdefense.fsf.org | "Nothing can be secure without encryption."