* 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).