* Lazy printing in tabulated-list-mode @ 2015-04-30 16:11 Artur Malabarba 2015-04-30 16:13 ` Artur Malabarba 2015-05-01 13:43 ` Stefan Monnier 0 siblings, 2 replies; 16+ messages in thread From: Artur Malabarba @ 2015-04-30 16:11 UTC (permalink / raw) To: emacs-devel The followin patch implements (optional) lazy printing in tabulated-list-mode. When used, the tabulated-list-print function will print enough entries to fill a window, redisplay, and then will finish printing in a way that's interruptible by user input. The outcome is that very large buffers (with entries around the thousands) will come up instantaneously, where they would normally take a couple of seconds to print. I'm attaching the patch before pushing because I ^ permalink raw reply [flat|nested] 16+ messages in thread
* Re: Lazy printing in tabulated-list-mode 2015-04-30 16:11 Lazy printing in tabulated-list-mode Artur Malabarba @ 2015-04-30 16:13 ` Artur Malabarba 2015-05-01 13:43 ` Stefan Monnier 1 sibling, 0 replies; 16+ messages in thread From: Artur Malabarba @ 2015-04-30 16:13 UTC (permalink / raw) To: emacs-devel ... because I wans't absolutely sure it would be well received or seen as "a litle too much". From: Artur Malabarba <bruce.connor.am@gmail.com> Date: Thu, 30 Apr 2015 16:18:24 +0100 Subject: [PATCH] * lisp/emacs-lisp/tabulated-list.el: Implement lazy printing (tabulated-list--timer): New variable. (tabulated-list--cancel-timer, tabulated-list--print-in-buffer): New functions. (tabulated-list-print): Use them. Accept a second argument, lazy. If it is non-nil, only the first page of entries is printed immediately, the rest of the entries are printed on idle timers. * lisp/emacs-lisp/package.el (package-menu--generate): Use it. (list-packages): Reorder buffer switching to make use of lazy printing. --- lisp/emacs-lisp/package.el | 11 ++--- lisp/emacs-lisp/tabulated-list.el | 88 +++++++++++++++++++++++++++++++-------- 2 files changed, 77 insertions(+), 22 deletions(-) diff --git a/lisp/emacs-lisp/package.el b/lisp/emacs-lisp/package.el index db61aba..21af0a3 100644 --- a/lisp/emacs-lisp/package.el +++ b/lisp/emacs-lisp/package.el @@ -2648,7 +2648,7 @@ shown." (define-key package-menu-mode-map "q" 'package-show-package-list) (define-key package-menu-mode-map "q" 'quit-window)) (tabulated-list-init-header) - (tabulated-list-print remember-pos)) + (tabulated-list-print remember-pos 'redisplay)) (defun package-menu--print-info (pkg) "Return a package entry suitable for `tabulated-list-entries'. @@ -3056,12 +3056,13 @@ The list is displayed in a buffer named `*Packages*'." ;; Fetch the remote list of packages. (unless no-fetch (package-menu-refresh)) + ;; The package menu buffer has keybindings. If the user types + ;; `M-x list-packages', that suggests it should become current. + (switch-to-buffer buf) + ;; If we're not async, this would be redundant. (when package-menu-async - (package-menu--generate nil t))) - ;; The package menu buffer has keybindings. If the user types - ;; `M-x list-packages', that suggests it should become current. - (switch-to-buffer buf))) + (package-menu--generate nil t))))) ;;;###autoload (defalias 'package-list-packages 'list-packages) diff --git a/lisp/emacs-lisp/tabulated-list.el b/lisp/emacs-lisp/tabulated-list.el index b12edc8..f9b5a8f 100644 --- a/lisp/emacs-lisp/tabulated-list.el +++ b/lisp/emacs-lisp/tabulated-list.el @@ -273,19 +273,61 @@ It runs `tabulated-list-revert-hook', then calls `tabulated-list-print'." (or found (error "No column named %s" name)))) -(defun tabulated-list-print (&optional remember-pos) +(defvar-local tabulated-list--timer nil + "Timer being used for lazy printing.") + +(defun tabulated-list--cancel-timer () + "Ensure that `tabulated-list--timer' is canceled and nil." + (when (timerp tabulated-list--timer) + (cancel-timer tabulated-list--timer) + (setq tabulated-list--timer nil))) + +(defun tabulated-list--print-in-buffer (entries buffer &optional lazy) + "Print list of ENTRIES at the end of BUFFER. +If LAZY is non-nil, user input will interrupt the printing, in +which case printing is resumed after some idle time. If LAZY is +a number, just print that many entries and return. +Return the list of entries left to print." + (with-current-buffer buffer + (save-excursion + (goto-char (point-max)) + (let ((inhibit-read-only t)) + (while (and entries + (if (numberp lazy) + (< -1 (setq lazy (1- lazy))) + (or (not lazy) + (not (input-pending-p))))) + (apply tabulated-list-printer (pop entries))))) + (set-buffer-modified-p nil) + ;; If we're leaving before we finish printing, setup a timer. + (when (and entries (not (numberp lazy))) + (tabulated-list--cancel-timer) ; just in case + (setq tabulated-list--timer + (run-with-idle-timer + 0.5 nil #'tabulated-list--print-in-buffer + entries buffer t))) + entries)) + +(defun tabulated-list-print (&optional remember-pos lazy) "Populate the current Tabulated List mode buffer. This sorts the `tabulated-list-entries' list if sorting is specified by `tabulated-list-sort-key'. It then erases the buffer and inserts the entries with `tabulated-list-printer'. Optional argument REMEMBER-POS, if non-nil, means to move point -to the entry with the same ID element as the current line." +to the entry with the same ID element as the current line. + +If REMEMBER-POS is nil and LAZY is non-nil, allow the printing to +be interrupted by used input, in which case it is resumed after +some idle time. If LAZY is the symbol redisplay, `redisplay' is +called once after enough entries have been printed to fill a +window." + (tabulated-list--cancel-timer) (let ((inhibit-read-only t) (entries (if (functionp tabulated-list-entries) (funcall tabulated-list-entries) tabulated-list-entries)) - entry-id saved-pt saved-col) + entry-id saved-col) (and remember-pos (setq entry-id (tabulated-list-get-id)) (setq saved-col (current-column))) @@ -312,20 +354,32 @@ to the entry with the same ID element as the current line." (setq entries (nreverse entries))) (unless (functionp tabulated-list-entries) (setq tabulated-list-entries entries))))) - ;; Print the resulting list. - (dolist (elt entries) - (and entry-id - (equal entry-id (car elt)) - (setq saved-pt (point))) - (apply tabulated-list-printer elt)) - (set-buffer-modified-p nil) - ;; If REMEMBER-POS was specified, move to the "old" location. - (if saved-pt - (progn (goto-char saved-pt) - (move-to-column saved-col) - (when (eq (window-buffer) (current-buffer)) - (recenter))) - (goto-char (point-min))))) + (if entry-id + ;; If remember-pos was given, we can't respect that and still + ;; print lazily, so we print the entire list. + (let (elt saved-pt) + (while (and (or (not lazy) + (not (input-pending-p))) + (setq elt (pop entries))) + (when (equal entry-id (car elt)) + (setq saved-pt (point))) + (apply tabulated-list-printer elt)) + ;; If REMEMBER-POS was specified, move to the "old" location. + (if saved-pt + (progn (goto-char saved-pt) + (move-to-column saved-col) + (when (eq (window-buffer) (current-buffer)) + (recenter))) + (goto-char (point-min)))) + + ;; Print the resulting list. + (when (eq lazy 'redisplay) + (setq entries (tabulated-list--print-in-buffer + ;; FIXME: `count-screen-lines' doesn't work + ;; here because the buffer is still empty. + entries (current-buffer) 50)) + (redisplay)) + (tabulated-list--print-in-buffer entries (current-buffer) lazy)))) (defun tabulated-list-print-entry (id cols) "Insert a Tabulated List entry at point. -- 2.3.6 ^ permalink raw reply related [flat|nested] 16+ messages in thread
* Re: Lazy printing in tabulated-list-mode 2015-04-30 16:11 Lazy printing in tabulated-list-mode Artur Malabarba 2015-04-30 16:13 ` Artur Malabarba @ 2015-05-01 13:43 ` Stefan Monnier 2015-05-01 14:03 ` Artur Malabarba 1 sibling, 1 reply; 16+ messages in thread From: Stefan Monnier @ 2015-05-01 13:43 UTC (permalink / raw) To: Artur Malabarba; +Cc: emacs-devel > The outcome is that very large buffers (with entries around the > thousands) will come up instantaneously, where they would normally > take a couple of seconds to print. I'm wondering why it should take that long to print a few thousand entries. Did you profile the code to see where the time is spent? Stefan ^ permalink raw reply [flat|nested] 16+ messages in thread
* Re: Lazy printing in tabulated-list-mode 2015-05-01 13:43 ` Stefan Monnier @ 2015-05-01 14:03 ` Artur Malabarba 2015-05-01 17:27 ` Stefan Monnier 0 siblings, 1 reply; 16+ messages in thread From: Artur Malabarba @ 2015-05-01 14:03 UTC (permalink / raw) To: Stefan Monnier; +Cc: emacs-devel 2015-05-01 14:43 GMT+01:00 Stefan Monnier <monnier@iro.umontreal.ca>: >> The outcome is that very large buffers (with entries around the >> thousands) will come up instantaneously, where they would normally >> take a couple of seconds to print. > > I'm wondering why it should take that long to print a few > thousand entries. Did you profile the code to see where the time > is spent? I did profile, and as far as I could tell it is spent in the printing itself. =P By which I mean I couldn't see any obvious source. All I could tell is that it's not in the sorting of entries. ^ permalink raw reply [flat|nested] 16+ messages in thread
* Re: Lazy printing in tabulated-list-mode 2015-05-01 14:03 ` Artur Malabarba @ 2015-05-01 17:27 ` Stefan Monnier 2015-05-01 18:11 ` Artur Malabarba 0 siblings, 1 reply; 16+ messages in thread From: Stefan Monnier @ 2015-05-01 17:27 UTC (permalink / raw) To: Artur Malabarba; +Cc: emacs-devel > I did profile, and as far as I could tell it is spent in the printing itself. =P You mean it's spent in `insert'? Stefan ^ permalink raw reply [flat|nested] 16+ messages in thread
* Re: Lazy printing in tabulated-list-mode 2015-05-01 17:27 ` Stefan Monnier @ 2015-05-01 18:11 ` Artur Malabarba 2015-05-01 18:12 ` Artur Malabarba 2015-05-01 20:46 ` Stefan Monnier 0 siblings, 2 replies; 16+ messages in thread From: Artur Malabarba @ 2015-05-01 18:11 UTC (permalink / raw) To: Stefan Monnier; +Cc: emacs-devel I mean I didn't look hard enough. I've included the report below, here is what I can infer - command-execute 3383 59% - call-interactively 3383 59% - funcall-interactively 3312 58% - eval-expression 3312 58% - eval 3312 58% - progn 3312 58% - tabulated-list-print 3309 58% - let 3309 58% - let 2676 46% - while 2676 46% - let 2669 46% - apply 2646 46% - tabulated-list-print-entry 2640 46% - let 2624 46% - let 2254 39% - while 2241 39% - let 2164 37% - setq 2151 37% - tabulated-list-print-col 2101 36% - let* 1939 34% + let 965 16% + if 534 9% + setq 50 0% < 33 0% + and 13 0% or 9 0% concat 6 0% setq 4 0% + if 96 1% add-text-properties 21 0% insert 3 0% + if 465 8% + profiler-report 3 0% + byte-code 71 1% + ... 2313 40% 2015-05-01 18:27 GMT+01:00 Stefan Monnier <monnier@iro.umontreal.ca>: >> I did profile, and as far as I could tell it is spent in the printing itself. =P > > You mean it's spent in `insert'? > > > Stefan ^ permalink raw reply [flat|nested] 16+ messages in thread
* Re: Lazy printing in tabulated-list-mode 2015-05-01 18:11 ` Artur Malabarba @ 2015-05-01 18:12 ` Artur Malabarba 2015-05-01 18:31 ` Artur Malabarba 2015-05-01 20:46 ` Stefan Monnier 1 sibling, 1 reply; 16+ messages in thread From: Artur Malabarba @ 2015-05-01 18:12 UTC (permalink / raw) To: Stefan Monnier; +Cc: emacs-devel Damn, that's the second time I hit C-ret accidentally. Gotta disable this keybind.That message is not finished. 2015-05-01 19:11 GMT+01:00 Artur Malabarba <bruce.connor.am@gmail.com>: > I mean I didn't look hard enough. I've included the report below, here > is what I can infer > > > > - command-execute 3383 59% > - call-interactively 3383 59% > - funcall-interactively 3312 58% > - eval-expression 3312 58% > - eval 3312 58% > - progn 3312 58% > - tabulated-list-print 3309 58% > - let 3309 58% > - let 2676 46% > - while 2676 46% > - let 2669 46% > - apply 2646 46% > - tabulated-list-print-entry 2640 46% > - let 2624 46% > - let 2254 39% > - while 2241 39% > - let 2164 37% > - setq 2151 37% > - tabulated-list-print-col 2101 36% > - let* 1939 34% > + let 965 16% > + if 534 9% > + setq 50 0% > < 33 0% > + and 13 0% > or 9 0% > concat 6 0% > setq 4 0% > + if 96 1% > add-text-properties 21 0% > insert 3 0% > + if 465 8% > + profiler-report 3 0% > + byte-code 71 1% > + ... 2313 40% > > 2015-05-01 18:27 GMT+01:00 Stefan Monnier <monnier@iro.umontreal.ca>: >>> I did profile, and as far as I could tell it is spent in the printing itself. =P >> >> You mean it's spent in `insert'? >> >> >> Stefan ^ permalink raw reply [flat|nested] 16+ messages in thread
* Re: Lazy printing in tabulated-list-mode 2015-05-01 18:12 ` Artur Malabarba @ 2015-05-01 18:31 ` Artur Malabarba 0 siblings, 0 replies; 16+ messages in thread From: Artur Malabarba @ 2015-05-01 18:31 UTC (permalink / raw) To: Stefan Monnier; +Cc: emacs-devel > You mean it's spent in `insert'? Here we go. So: 41% of the samples were in garbage collection. I missed that the first time, but it looks like a pretty big deal. 8% are in sorting the entries. 7% disappear somewhere inside tabulated-list-print-entry. 36% are spent inside tabulated-list-print-col (report snippet pasted below). Out of which: 11% are completely unacounted for 9% are in the following `if' form, but only 2% and 1% are spend on the `apply' and the `insert'. So I think that means `get-text-property' is eating up 6% here? (if (stringp col-desc) (insert (if (get-text-property 0 'help-echo label) label (propertize label 'help-echo help-echo))) (apply 'insert-text-button label (cdr col-desc))) 12% are in a `progn', which I think corresponds to the body of this `when', but I don't know what's responsible for this. (when not-last-col (when (> pad-right 0) (insert (make-string pad-right ?\s))) (insert (propertize (make-string (- next-x x label-width pad-right) ?\s) 'display `(space :align-to ,next-x)))) -------------------------------------------------- - tabulated-list-print-col 2101 36% - let* 1939 34% - let 965 16% - if 702 12% - progn 699 12% - if 333 5% - progn 317 5% insert 53 0% + insert 127 2% put-text-property 37 0% - if 534 9% + apply 132 2% + insert 85 1% + setq 50 0% < 33 0% + and 13 0% or 9 0% ^ permalink raw reply [flat|nested] 16+ messages in thread
* Re: Lazy printing in tabulated-list-mode 2015-05-01 18:11 ` Artur Malabarba 2015-05-01 18:12 ` Artur Malabarba @ 2015-05-01 20:46 ` Stefan Monnier 2015-05-02 9:38 ` Artur Malabarba 1 sibling, 1 reply; 16+ messages in thread From: Stefan Monnier @ 2015-05-01 20:46 UTC (permalink / raw) To: Artur Malabarba; +Cc: emacs-devel > - command-execute 3383 59% > - call-interactively 3383 59% > - funcall-interactively 3312 58% > - eval-expression 3312 58% > - eval 3312 58% > - progn 3312 58% > - tabulated-list-print 3309 58% > - let 3309 58% > - let 2676 46% > - while 2676 46% > - let 2669 46% > - apply 2646 46% > - tabulated-list-print-entry 2640 46% > - let 2624 46% > - let 2254 39% > - while 2241 39% > - let 2164 37% > - setq 2151 37% > - tabulated-list-print-col 2101 36% > - let* 1939 34% Clearly, you used non-byte-compiled code here. Can you try again after byte-compiling package.el? Stefan ^ permalink raw reply [flat|nested] 16+ messages in thread
* Re: Lazy printing in tabulated-list-mode 2015-05-01 20:46 ` Stefan Monnier @ 2015-05-02 9:38 ` Artur Malabarba 2015-05-03 16:21 ` Stefan Monnier 0 siblings, 1 reply; 16+ messages in thread From: Artur Malabarba @ 2015-05-02 9:38 UTC (permalink / raw) To: Stefan Monnier; +Cc: emacs-devel [-- Attachment #1: Type: text/plain, Size: 333 bytes --] > Clearly, you used non-byte-compiled code here. Can you try again after > byte-compiling package.el? Yes, sorry about that. Here is another report, bytecompiled. The overall structure still looks the same. There's a little less grabage collection (35%), 27% of the samples are lost in -print-entry somehow, and 13% in -print-col. [-- Attachment #2: tab-list-report --] [-- Type: application/octet-stream, Size: 6457 bytes --] [profiler-profile "24.3" cpu #s(hash-table size 65 test equal rehash-size 1.5 rehash-threshold 0.8 data ([maphash profiler-calltree-build-unified profiler-calltree-build profiler-report-render-calltree-1 profiler-report-rerender-calltree profiler-report-render-calltree profiler-report-setup-buffer profiler-report-profile-other-window profiler-report-cpu profiler-report progn eval eval-expression funcall-interactively call-interactively command-execute] 3 [tabulated-list-print progn eval eval-expression funcall-interactively call-interactively command-execute nil nil nil nil nil nil nil nil nil] 87 [aref progn symbol-name string< package-menu--name-predicate cond let package-menu--status-predicate sort tabulated-list-print progn eval eval-expression funcall-interactively call-interactively command-execute] 26 [memq and progn or progn symbol-name string< package-menu--name-predicate cond let package-menu--status-predicate sort tabulated-list-print progn eval eval-expression] 6 [let package-menu--status-predicate sort tabulated-list-print progn eval eval-expression funcall-interactively call-interactively command-execute nil nil nil nil nil nil] 15 [aref let package-menu--status-predicate sort tabulated-list-print progn eval eval-expression funcall-interactively call-interactively command-execute nil nil nil nil nil] 3 [string< package-menu--name-predicate cond let package-menu--status-predicate sort tabulated-list-print progn eval eval-expression funcall-interactively call-interactively command-execute nil nil nil] 10 [car aref let package-menu--status-predicate sort tabulated-list-print progn eval eval-expression funcall-interactively call-interactively command-execute nil nil nil nil] 14 [sort tabulated-list-print progn eval eval-expression funcall-interactively call-interactively command-execute nil nil nil nil nil nil nil nil] 17 [cond let package-menu--status-predicate sort tabulated-list-print progn eval eval-expression funcall-interactively call-interactively command-execute nil nil nil nil nil] 19 [package-menu--status-predicate sort tabulated-list-print progn eval eval-expression funcall-interactively call-interactively command-execute nil nil nil nil nil nil nil] 21 [and progn or progn symbol-name string< package-menu--name-predicate cond let package-menu--status-predicate sort tabulated-list-print progn eval eval-expression funcall-interactively] 36 [tabulated-list-print-col tabulated-list-print-entry apply tabulated-list-print progn eval eval-expression funcall-interactively call-interactively command-execute nil nil nil nil nil nil] 228 [tabulated-list-print-entry apply tabulated-list-print progn eval eval-expression funcall-interactively call-interactively command-execute nil nil nil nil nil nil nil] 541 [apply tabulated-list-print-col tabulated-list-print-entry apply tabulated-list-print progn eval eval-expression funcall-interactively call-interactively command-execute nil nil nil nil nil] 22 [make-text-button apply insert-text-button apply tabulated-list-print-col tabulated-list-print-entry apply tabulated-list-print progn eval eval-expression funcall-interactively call-interactively command-execute nil nil] 19 [add-text-properties tabulated-list-print-entry apply tabulated-list-print progn eval eval-expression funcall-interactively call-interactively command-execute nil nil nil nil nil nil] 4 [apply tabulated-list-print progn eval eval-expression funcall-interactively call-interactively command-execute nil nil nil nil nil nil nil nil] 103 [put-text-property tabulated-list-print-col tabulated-list-print-entry apply tabulated-list-print progn eval eval-expression funcall-interactively call-interactively command-execute nil nil nil nil nil] 23 [symbol-name string< package-menu--name-predicate cond let package-menu--status-predicate sort tabulated-list-print progn eval eval-expression funcall-interactively call-interactively command-execute nil nil] 17 [or progn symbol-name string< package-menu--name-predicate cond let package-menu--status-predicate sort tabulated-list-print progn eval eval-expression funcall-interactively call-interactively command-execute] 9 [vectorp and progn or progn symbol-name string< package-menu--name-predicate cond let package-menu--status-predicate sort tabulated-list-print progn eval eval-expression] 4 [bidi-string-mark-left-to-right tabulated-list-print-col tabulated-list-print-entry apply tabulated-list-print progn eval eval-expression funcall-interactively call-interactively command-execute nil nil nil nil nil] 18 [apply insert-text-button apply tabulated-list-print-col tabulated-list-print-entry apply tabulated-list-print progn eval eval-expression funcall-interactively call-interactively command-execute nil nil nil] 7 [progn or progn symbol-name string< package-menu--name-predicate cond let package-menu--status-predicate sort tabulated-list-print progn eval eval-expression funcall-interactively call-interactively] 13 [add-text-properties make-text-button apply insert-text-button apply tabulated-list-print-col tabulated-list-print-entry apply tabulated-list-print progn eval eval-expression funcall-interactively call-interactively command-execute nil] 3 [>= and progn or progn symbol-name string< package-menu--name-predicate cond let package-menu--status-predicate sort tabulated-list-print progn eval eval-expression] 3 [progn eval eval-expression funcall-interactively call-interactively command-execute nil nil nil nil nil nil nil nil nil nil] 4 [aref memq and progn or progn symbol-name string< package-menu--name-predicate cond let package-menu--status-predicate sort tabulated-list-print progn eval] 4 [progn symbol-name string< package-menu--name-predicate cond let package-menu--status-predicate sort tabulated-list-print progn eval eval-expression funcall-interactively call-interactively command-execute nil] 3 [length >= and progn or progn symbol-name string< package-menu--name-predicate cond let package-menu--status-predicate sort tabulated-list-print progn eval] 3 [insert-text-button apply tabulated-list-print-col tabulated-list-print-entry apply tabulated-list-print progn eval eval-expression funcall-interactively call-interactively command-execute nil nil nil nil] 3 [profiler-cpu-profile profiler-report-cpu profiler-report progn eval eval-expression funcall-interactively call-interactively command-execute nil nil nil nil nil nil nil] 4 [Automatic\ GC] 725)) (21828 39284 676974 363000) nil] ^ permalink raw reply [flat|nested] 16+ messages in thread
* Re: Lazy printing in tabulated-list-mode 2015-05-02 9:38 ` Artur Malabarba @ 2015-05-03 16:21 ` Stefan Monnier 2015-05-03 17:02 ` Artur Malabarba 0 siblings, 1 reply; 16+ messages in thread From: Stefan Monnier @ 2015-05-03 16:21 UTC (permalink / raw) To: Artur Malabarba; +Cc: emacs-devel > Yes, sorry about that. Here is another report, bytecompiled. > The overall structure still looks the same. There's a little less > garbage collection (35%), 27% of the samples are lost in -print-entry > somehow, and 13% in -print-col. Yes, the time spent in those functions is odd. Maybe it would be worthwhile to run tabulated-list-print 10 times or so, to increase the number of samples. Stefan ^ permalink raw reply [flat|nested] 16+ messages in thread
* Re: Lazy printing in tabulated-list-mode 2015-05-03 16:21 ` Stefan Monnier @ 2015-05-03 17:02 ` Artur Malabarba 2015-05-04 0:19 ` Stefan Monnier 0 siblings, 1 reply; 16+ messages in thread From: Artur Malabarba @ 2015-05-03 17:02 UTC (permalink / raw) To: Stefan Monnier; +Cc: emacs-devel > Yes, the time spent in those functions is odd. Maybe it would be > worthwhile to run tabulated-list-print 10 times or so, to increase the > number of samples. Yep, that's what I was doing (if you consider 7 ~ 10). Here's the command I was running under M-: (progn (profiler-start 'cpu) (tabulated-list-print)(tabulated-list-print)(tabulated-list-print)(tabulated-list-print)(tabulated-list-print)(tabulated-list-print)(tabulated-list-print) (profiler-report) (profiler-stop)) ^ permalink raw reply [flat|nested] 16+ messages in thread
* Re: Lazy printing in tabulated-list-mode 2015-05-03 17:02 ` Artur Malabarba @ 2015-05-04 0:19 ` Stefan Monnier 2015-05-04 8:21 ` Artur Malabarba 0 siblings, 1 reply; 16+ messages in thread From: Stefan Monnier @ 2015-05-04 0:19 UTC (permalink / raw) To: Artur Malabarba; +Cc: emacs-devel > Yep, that's what I was doing (if you consider 7 ~ 10). > Here's the command I was running under M-: > (progn (profiler-start 'cpu) > (tabulated-list-print)(tabulated-list-print)(tabulated-list-print)(tabulated-list-print)(tabulated-list-print)(tabulated-list-print)(tabulated-list-print) > (profiler-report) (profiler-stop)) Hmm... but the numbers I saw seemed to indicate a running time of 1.3s, so that would mean you saw a running time of of 0.2s per call to tabulated-list-print which seems not to justify the addition of laziness. Stefan ^ permalink raw reply [flat|nested] 16+ messages in thread
* Re: Lazy printing in tabulated-list-mode 2015-05-04 0:19 ` Stefan Monnier @ 2015-05-04 8:21 ` Artur Malabarba 2015-05-04 10:46 ` Artur Malabarba 2015-05-04 12:38 ` Stefan Monnier 0 siblings, 2 replies; 16+ messages in thread From: Artur Malabarba @ 2015-05-04 8:21 UTC (permalink / raw) To: Stefan Monnier; +Cc: emacs-devel Firstly, I don't really plan on implementing this lazy-printing anymore, I'm just trying to optimize the printing a bit now. Secondly, how do you see the running time on the profiler? I don't know why it would report 1.3s, given that if I just evaluate (benchmark-run 10 (tabulated-list-print)) I get a result between 6 to 10 seconds total (depending on whether package-hiding is on or off), which means at least 0.6 seconds per run (of course). Maybe the report I sent you was accidentally gathered on a small package-menu (with only Gelpa configured). 0.6s per print is less than the "couple of seconds" I reported earlier, because that was without byte-compiling. Still, I think it's something we can optimize because the benchmark reports 67% of the time was spent garbage collecting. 2015-05-04 1:19 GMT+01:00 Stefan Monnier <monnier@iro.umontreal.ca>: >> Yep, that's what I was doing (if you consider 7 ~ 10). >> Here's the command I was running under M-: > >> (progn (profiler-start 'cpu) >> (tabulated-list-print)(tabulated-list-print)(tabulated-list-print)(tabulated-list-print)(tabulated-list-print)(tabulated-list-print)(tabulated-list-print) >> (profiler-report) (profiler-stop)) > > Hmm... but the numbers I saw seemed to indicate a running time of 1.3s, > so that would mean you saw a running time of of 0.2s per call to > tabulated-list-print which seems not to justify the addition > of laziness. > > > Stefan ^ permalink raw reply [flat|nested] 16+ messages in thread
* Re: Lazy printing in tabulated-list-mode 2015-05-04 8:21 ` Artur Malabarba @ 2015-05-04 10:46 ` Artur Malabarba 2015-05-04 12:38 ` Stefan Monnier 1 sibling, 0 replies; 16+ messages in thread From: Artur Malabarba @ 2015-05-04 10:46 UTC (permalink / raw) To: Stefan Monnier; +Cc: emacs-devel With some investigation, I managed to pinpoint some small problems in -print-col: propertize and concat. By replacing the calls to `propertize' with insert+put-text-properties, and by removing the `concat', the following patch speeds up printing by ~ 20%. The only functional difference is that the help-echo property of an entry's column will be "entry-content" instead of "column-name: entry-content" (the former seems redundant to me anyway). I get another 50% speed-up on top of that if I remove all `put-text-property' calls. :-D I won't do that of course, but at least it shows where most of the work is going. Subject: [PATCH] * lisp/emacs-lisp/tabulated-list.el: Speed optimizations (tabulated-list-print-col): Prefer `put-text-property' to `propertize'. Avoid `concat'. --- lisp/emacs-lisp/tabulated-list.el | 27 ++++++++++++++++++--------- 1 file changed, 18 insertions(+), 9 deletions(-) diff --git a/lisp/emacs-lisp/tabulated-list.el b/lisp/emacs-lisp/tabulated-list.el index b12edc8..173e253 100644 --- a/lisp/emacs-lisp/tabulated-list.el +++ b/lisp/emacs-lisp/tabulated-list.el @@ -346,6 +346,14 @@ of column descriptors." beg (point) `(tabulated-list-id ,id tabulated-list-entry ,cols)))) +(defmacro tabulated-list--insert-space-string (s prop value) + "Insert a propertized string of size S composed of spaces. +Put property PROP with VALUE." + `(let* ((size ,s) + (string (make-string size ?\s))) + (put-text-property 0 size ,prop ,value string) + (insert string))) + (defun tabulated-list-print-col (n col-desc x) "Insert a specified Tabulated List entry at point. N is the column number, COL-DESC is a column descriptor (see @@ -361,7 +369,6 @@ Return the column number after insertion." (right-align (plist-get props :right-align)) (label (if (stringp col-desc) col-desc (car col-desc))) (label-width (string-width label)) - (help-echo (concat (car format) ": " label)) (opoint (point)) (not-last-col (< (1+ n) (length tabulated-list-format)))) ;; Truncate labels if necessary (except last column). @@ -372,22 +379,24 @@ Return the column number after insertion." (setq label (bidi-string-mark-left-to-right label)) (when (and right-align (> width label-width)) (let ((shift (- width label-width))) - (insert (propertize (make-string shift ?\s) - 'display `(space :align-to ,(+ x shift)))) + (tabulated-list--insert-space-string + shift 'display `(space :align-to ,(+ x shift))) (setq width (- width shift)) (setq x (+ x shift)))) (if (stringp col-desc) - (insert (if (get-text-property 0 'help-echo label) - label - (propertize label 'help-echo help-echo))) + (if (get-text-property 0 'help-echo label) + (insert label) + (let ((op (point))) + (insert label) + (put-text-property op (point) 'help-echo label))) (apply 'insert-text-button label (cdr col-desc))) (let ((next-x (+ x pad-right width))) ;; No need to append any spaces if this is the last column. (when not-last-col (when (> pad-right 0) (insert (make-string pad-right ?\s))) - (insert (propertize - (make-string (- next-x x label-width pad-right) ?\s) - 'display `(space :align-to ,next-x)))) + (tabulated-list--insert-space-string + (- next-x x label-width pad-right) + 'display `(space :align-to ,next-x))) (put-text-property opoint (point) 'tabulated-list-column-name name) next-x))) -- 2.3.7 ^ permalink raw reply related [flat|nested] 16+ messages in thread
* Re: Lazy printing in tabulated-list-mode 2015-05-04 8:21 ` Artur Malabarba 2015-05-04 10:46 ` Artur Malabarba @ 2015-05-04 12:38 ` Stefan Monnier 1 sibling, 0 replies; 16+ messages in thread From: Stefan Monnier @ 2015-05-04 12:38 UTC (permalink / raw) To: Artur Malabarba; +Cc: emacs-devel > Secondly, how do you see the running time on the profiler? Supposedly, we have one sample per ms (given the default profiler-sample-interval), so the 1.3s comes from the total number of samples. I'm not actually sure this is accurate. > 0.6s per print is less than the "couple of seconds" I reported > earlier, because that was without byte-compiling. Still, I think it's > something we can optimize because the benchmark reports 67% of the > time was spent garbage collecting. Right, 0.6s is not unbearable, but it's borderline, and there should be optimization opportunities. Stefan ^ permalink raw reply [flat|nested] 16+ messages in thread
end of thread, other threads:[~2015-05-04 12:38 UTC | newest] Thread overview: 16+ messages (download: mbox.gz follow: Atom feed -- links below jump to the message on this page -- 2015-04-30 16:11 Lazy printing in tabulated-list-mode Artur Malabarba 2015-04-30 16:13 ` Artur Malabarba 2015-05-01 13:43 ` Stefan Monnier 2015-05-01 14:03 ` Artur Malabarba 2015-05-01 17:27 ` Stefan Monnier 2015-05-01 18:11 ` Artur Malabarba 2015-05-01 18:12 ` Artur Malabarba 2015-05-01 18:31 ` Artur Malabarba 2015-05-01 20:46 ` Stefan Monnier 2015-05-02 9:38 ` Artur Malabarba 2015-05-03 16:21 ` Stefan Monnier 2015-05-03 17:02 ` Artur Malabarba 2015-05-04 0:19 ` Stefan Monnier 2015-05-04 8:21 ` Artur Malabarba 2015-05-04 10:46 ` Artur Malabarba 2015-05-04 12:38 ` Stefan Monnier
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).