unofficial mirror of emacs-devel@gnu.org 
 help / color / mirror / code / Atom feed
* 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).