unofficial mirror of bug-gnu-emacs@gnu.org 
 help / color / mirror / code / Atom feed
* bug#67536: 29.1; Calc mode's math-read-preprocess-string conses unnecessarily
@ 2023-11-29 21:29 Raffael Stocker
  2023-11-30  7:00 ` Eli Zaretskii
  0 siblings, 1 reply; 20+ messages in thread
From: Raffael Stocker @ 2023-11-29 21:29 UTC (permalink / raw)
  To: 67536


Org table re-calculation is very slow, partly due to
math-read-preprocess-string of calc mode consing unnecessarily.  For
example, in one (large) table, I get the following memory usage from the
profiler:

...
     60,252,646  96%   - org-ctrl-c-ctrl-c
     60,248,166  96%    - org-table-calc-current-TBLFM
     60,216,431  96%     - funcall-interactively
     60,205,119  96%      - org-table-recalculate
     49,094,651  78%       - org-table-eval-formula
     32,624,631  52%        - calc-eval
     32,624,631  52%         - calc-do-calc-eval
     32,620,487  52%          - calc-do-calc-eval
     32,611,151  52%           - math-read-exprs
     29,388,838  47%            + math-read-preprocess-string
      2,343,257   3%            + math-read-expr-list
...

The reason for the slow-down seems to be that
math-read-preprocess-string conses a lot, keeping the GC busy.  This is
due to heavy use of replace-regexp-in-string in this function:

(defun math-read-preprocess-string (str)
  "Replace some substrings of STR by Calc equivalents."
  (setq str
        (replace-regexp-in-string (concat "[" math-read-superscripts "]+")
                                  "^(\\&)" str))
  (setq str
        (replace-regexp-in-string (concat "[" math-read-subscripts "]+")
                                  "_(\\&)" str))
  (let ((rep-list math-read-replacement-list))
    (while rep-list
      ;; consing like a mad-man here:
      (setq str
            (replace-regexp-in-string (nth 0 (car rep-list))
                                      (nth 1 (car rep-list)) str))
      (setq rep-list (cdr rep-list))))
  str)

I would like to propose using a temp buffer instead of kneading the
string into submission:

(defun math-read-preprocess-string (str)
  "Replace some substrings of STR by Calc equivalents."
  (with-temp-buffer
    (insert str)
    (goto-char 0)
    (while (re-search-forward (concat "[" math-read-superscripts "]+") nil t)
      (replace-match "^(\\&)"))
    (goto-char 0)
    (while (re-search-forward (concat "[" math-read-subscripts "]+") nil t)
      (replace-match "_(\\&)"))
    (goto-char 0)
    (let ((rep-list math-read-replacement-list))
      (while rep-list
        (while (re-search-forward (nth 0 (car rep-list)) nil t)
          (replace-match (nth 1 (car rep-list))))
        (goto-char 0)
        (setq rep-list (cdr rep-list))))
    (buffer-string)))

With this replacement, the profiler shows much less memory usage on the
same org table:

...
     30,411,804  91%   - org-ctrl-c-ctrl-c
     30,407,324  91%    - org-table-calc-current-TBLFM
     30,363,932  91%     - funcall-interactively
     30,331,900  91%      - org-table-recalculate
     20,430,223  61%       - org-table-eval-formula
      6,751,852  20%        + org-table-justify-field-maybe
      4,598,523  13%        - calc-eval
      4,586,091  13%         - calc-do-calc-eval
      4,569,619  13%          - calc-do-calc-eval
      4,547,971  13%           - math-read-exprs
      2,297,453   6%            + math-read-expr-list
      1,347,377   4%            + math-read-preprocess-string
          7,296   0%              math-read-token
...

Only I am not sure the replacement is correct in all possible edge cases
(or whether it uses so much less memory because I have overlooked
something).

What do you think? Can a calc-mode expert weigh in here?

Regards,
Raffael





^ permalink raw reply	[flat|nested] 20+ messages in thread

end of thread, other threads:[~2023-12-19 18:15 UTC | newest]

Thread overview: 20+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2023-11-29 21:29 bug#67536: 29.1; Calc mode's math-read-preprocess-string conses unnecessarily Raffael Stocker
2023-11-30  7:00 ` Eli Zaretskii
2023-11-30 18:28   ` Raffael Stocker
2023-11-30 19:14     ` Eli Zaretskii
2023-12-01 17:34       ` Raffael Stocker
2023-12-01 18:12         ` Eli Zaretskii
2023-12-01 21:10           ` Raffael Stocker
2023-12-02  8:03             ` Eli Zaretskii
2023-12-02 14:56               ` Mattias Engdegård
2023-12-02 19:26                 ` Raffael Stocker
2023-12-03 10:43                   ` Mattias Engdegård
2023-12-03 11:13                     ` Raffael Stocker
2023-12-03 11:58                       ` Mattias Engdegård
2023-12-05 18:14                     ` Raffael Stocker
2023-12-16  9:40                       ` Eli Zaretskii
2023-12-18 10:55                         ` Mattias Engdegård
2023-12-18 11:39                           ` Raffael Stocker
2023-12-19 16:16                             ` Mattias Engdegård
2023-12-19 17:09                               ` Raffael Stocker
2023-12-19 18:15                                 ` Mattias Engdegård

Code repositories for project(s) associated with this public inbox

	https://git.savannah.gnu.org/cgit/emacs.git

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).