1725 lines
99 KiB
Org Mode
1725 lines
99 KiB
Org Mode
#+PROPERTY: LOGGING nil
|
||
|
||
* Tasks
|
||
|
||
** TODO Update commentary
|
||
|
||
** TODO [#B] Default sort
|
||
|
||
Would probably be useful to have a default sort option.
|
||
|
||
** TODO ~org-agenda-skip-function~
|
||
|
||
As discussed [[https://www.reddit.com/r/emacs/comments/cnrt2d/orgqlblock_integrates_orgql_into_org_agenda/ewi1q36/][here]], this is a cool feature that allows further integration into existing custom agenda commands. Example:
|
||
|
||
#+BEGIN_SRC elisp
|
||
;;; lima-0ac22.el --- -*- lexical-binding: t; -*-
|
||
|
||
(defun org-ql-skip-function (query)
|
||
"Return a function for `org-agenda-skip-function' for QUERY.
|
||
Compared to using QUERY in `org-ql', this effectively turns QUERY
|
||
into (not QUERY)."
|
||
(let* ((predicate (org-ql--query-predicate '(regexp "ryo-modal"))))
|
||
(lambda ()
|
||
;; This duplicates the functionality of `org-ql--select'.
|
||
(let (orig-fns)
|
||
(--each org-ql-predicates
|
||
;; Save original function mappings.
|
||
(let ((name (plist-get it :name)))
|
||
(push (list :name name :fn (symbol-function name)) orig-fns)))
|
||
(unwind-protect
|
||
(progn
|
||
(--each org-ql-predicates
|
||
;; Set predicate functions.
|
||
(fset (plist-get it :name) (plist-get it :fn)))
|
||
;; Run query.
|
||
;; FIXME: "If this function returns nil, the current match should not be skipped.
|
||
;; Otherwise, the function must return a position from where the search
|
||
;; should be continued."
|
||
(funcall predicate))
|
||
(--each orig-fns
|
||
;; Restore original function mappings.
|
||
(fset (plist-get it :name) (plist-get it :fn))))))))
|
||
|
||
(let ((org-agenda-custom-commands
|
||
'(("z" "Z"
|
||
((tags-todo "PRIORITY=\"A\"+Emacs/!SOMEDAY"))
|
||
((org-agenda-skip-function (org-ql-skip-function '(regexp "ryo-modal")))))
|
||
((org-agenda-files ("~/org/inbox.org"))))))
|
||
(org-agenda nil "z"))
|
||
#+END_SRC
|
||
|
||
I should benchmark it to see how much difference it makes, because all those ~fset~ calls on each heading isn't free. But if a macro were used to rewrite the built-in predicates to their full versions, all of that could be avoided...
|
||
|
||
** TODO [#A] Tools for saving queries and accessing them
|
||
|
||
*** TODO Save query from ql-agenda buffer
|
||
|
||
*** TODO Access saved query from saved query list
|
||
|
||
*** TODO Org link types
|
||
:PROPERTIES:
|
||
:ID: 4db73c1c-a4ed-425e-9e38-8d334ed03e1e
|
||
:END:
|
||
|
||
This would be useful for having a menu of saved queries as Org links, or even bookmarking saved queries.
|
||
|
||
**** TODO For all parameters
|
||
|
||
**** TODO For saved queries
|
||
|
||
*** TODO Bookmarks
|
||
|
||
** TODO [#A] Store query for refreshing ql-agenda buffer
|
||
|
||
** DONE [#B] Dual matching with regexp and predicates
|
||
:PROPERTIES:
|
||
:ID: 39972bb5-fdd0-4754-93ba-c85796a67ccf
|
||
:END:
|
||
|
||
/Note: This is underway in the =preamble-re= branch./
|
||
|
||
Searching and matching could be sped up by constructing a regexp that searches directly to the next possible match, and then matching with predicate functions.
|
||
|
||
For example, a search like:
|
||
|
||
#+BEGIN_SRC elisp
|
||
(org-ql (org-agenda-files)
|
||
(and (regexp "lisp")
|
||
(scheduled < today)))
|
||
#+END_SRC
|
||
|
||
Only entries that contain the word =lisp= can be matches, and searching each entry for that word is wasteful. Instead, we could search the buffer for the next occurrence of =lisp=, then check the scheduled date for that entry.
|
||
|
||
This would require processing the predicate to pull out matchers that can be done as buffer-wide regexps, e.g. =regexp=, =heading-regexp=, =todo=, and possibly =tags=. Org has some regexp-building functions that might make this fairly easy, and then we could probably use ~rx~ to make an optimized version of the regexp. It would also require some refactoring to the searching that would go directly to regexp matches when possible, rather than checking every entry with the predicate.
|
||
|
||
[2019-07-16 Tue 11:14] Made new branch =preamble-re-new= based on current =master=. Seems to work well. Here's some code for testing and comparing performance (~bench-multi-lets~ is from [[https://github.com/alphapapa/emacs-package-dev-handbook#bench-multi-lets][here]]).
|
||
|
||
[2019-07-16 Tue 11:56] Going to merge to =master= as 0.2, so marking this as done, even though there's a bit more that can be done from here.
|
||
|
||
*** Benchmark code
|
||
|
||
#+BEGIN_SRC elisp
|
||
(cl-defmacro org-ql-preamble-bench (&key query (file "tests/data.org") (times 10))
|
||
`(bench-multi-lets :times ,times :ensure-equal t
|
||
:lets (("preamble" ((org-ql-use-preamble t)))
|
||
("no preamble" ((org-ql-use-preamble nil))))
|
||
:forms ((,(prin1-to-string query) (org-ql-query ,file
|
||
',query
|
||
:action (lambda () (org-get-heading t t)))))))
|
||
#+END_SRC
|
||
|
||
#+BEGIN_SRC elisp
|
||
(org-ql-preamble-bench :query (regexp "Emacs") :times 100)
|
||
#+END_SRC
|
||
|
||
#+RESULTS:
|
||
| Form | x faster than next | Total runtime | # of GCs | Total GC runtime |
|
||
|-------------------------------+--------------------+---------------+----------+------------------|
|
||
| preamble: (regexp "Emacs") | 1.22 | 0.141767 | 0 | 0 |
|
||
| no preamble: (regexp "Emacs") | slowest | 0.172398 | 0 | 0 |
|
||
|
||
#+BEGIN_SRC elisp
|
||
(org-ql-preamble-bench :file "~/org/inbox.org" :query (regexp "Emacs") :times 5)
|
||
#+END_SRC
|
||
|
||
#+RESULTS:
|
||
| Form | x faster than next | Total runtime | # of GCs | Total GC runtime |
|
||
|-------------------------------+--------------------+---------------+----------+------------------|
|
||
| preamble: (regexp "Emacs") | 1.59 | 2.011043 | 0 | 0 |
|
||
| no preamble: (regexp "Emacs") | slowest | 3.206370 | 0 | 0 |
|
||
|
||
#+BEGIN_SRC elisp
|
||
(org-ql-preamble-bench :file "~/org/inbox.org" :query (and (regexp "Emacs") (todo)) :times 5)
|
||
#+END_SRC
|
||
|
||
#+RESULTS:
|
||
| Form | x faster than next | Total runtime | # of GCs | Total GC runtime |
|
||
|--------------------------------------------+--------------------+---------------+----------+------------------|
|
||
| preamble: (and (regexp "Emacs") (todo)) | 1.59 | 2.211503 | 0 | 0 |
|
||
| no preamble: (and (regexp "Emacs") (todo)) | slowest | 3.512741 | 0 | 0 |
|
||
|
||
#+BEGIN_SRC elisp
|
||
(org-ql-preamble-bench :file "~/org/inbox.org" :query (and (regexp "Emacs") (todo) (scheduled)) :times 5)
|
||
#+END_SRC
|
||
|
||
#+RESULTS:
|
||
| Form | x faster than next | Total runtime | # of GCs | Total GC runtime |
|
||
|--------------------------------------------------------+--------------------+---------------+----------+------------------|
|
||
| preamble: (and (regexp "Emacs") (todo) (scheduled)) | 1.69 | 2.042456 | 0 | 0 |
|
||
| no preamble: (and (regexp "Emacs") (todo) (scheduled)) | slowest | 3.453756 | 0 | 0 |
|
||
|
||
#+BEGIN_SRC elisp
|
||
(org-ql-preamble-bench :file "~/org/inbox.org" :query (todo "WAITING") :times 2)
|
||
#+END_SRC
|
||
|
||
#+RESULTS:
|
||
| Form | x faster than next | Total runtime | # of GCs | Total GC runtime |
|
||
|-------------------------------+--------------------+---------------+----------+------------------|
|
||
| preamble: (todo "WAITING") | 15.60 | 0.070684 | 0 | 0 |
|
||
| no preamble: (todo "WAITING") | slowest | 1.102722 | 0 | 0 |
|
||
|
||
Wow, that's a huge improvement!
|
||
|
||
** TODO Normalize queries
|
||
|
||
[2019-07-16 Tue 11:49] This serves two purposes:
|
||
|
||
1. Equivalent queries will return the same results from the cache.
|
||
2. The selectors that can be converted to the fastest preamble regexps will be sorted first, so the fastest preamble will be used. Although this may not always be straightforward. For example, in a file with only a few =TODO= items, the ~(todo "TODO")~ selector would convert to a preamble that would quickly search through the file. But if there were a thousand =TODO= items, it wouldn't be as much of a benefit, and a ~(regexp "something")~ selector's preamble might be much faster, depending on how many times =something= appears in the file.
|
||
|
||
So the second purpose might actually be a drawback, because it would prevent users from optimizing their queries with knowledge of their data. Maybe there should be an option to not normalize queries, so advanced users can order their selectors manually.
|
||
|
||
** TODO [#A] Publish to MELPA
|
||
|
||
** TODO Add more sorters?
|
||
|
||
+ [ ] =category=
|
||
+ [ ] Any date :: e.g. it would search for timestamps (active/inactive?) anywhere in an entry
|
||
|
||
** TODO Document matchers/selectors/predicates
|
||
|
||
And maybe pick a single name for them...
|
||
|
||
+ =deadline= :: Be sure to explain how it works with regard to the implied date and =today=.
|
||
+ =date=, =scheduled= :: No implied date, but supports =today=.
|
||
|
||
** TODO Document sorters
|
||
|
||
Note that the built-in sorting only works on Org elements, which is the default ~:action~. So if a different action is used, sorting will not work. In that case, the action should be mapped across the Org element results from outside the ~org-ql~ form.
|
||
|
||
** TODO Document/figure out tag inheritance
|
||
|
||
I think it should probably be enabled in most cases, to avoid missing results that users would expect to find, but it will reduce performance in some cases, so users should be able to turn it off when they don't need it.
|
||
|
||
[2018-06-12 Tue 14:32] The docstring for ~org-map-entries~ says:
|
||
|
||
#+BEGIN_QUOTE
|
||
If your function needs to retrieve the tags including inherited tags at the *current* entry, you can use the value of the variable ‘org-scanner-tags’ which will be much faster than getting the value with ‘org-get-tags-at’. If your function gets properties with ‘org-entry-properties’ at the *current* entry, bind ‘org-trust-scanner-tags’ to t around the call to ‘org-entry-properties’ to get the same speedup. Note that if your function moves around to retrieve tags and properties at a *different* entry, you cannot use these techniques.
|
||
#+END_QUOTE
|
||
|
||
** MAYBE Date predicate that searches entire entry
|
||
|
||
Because the existing ones only search the special date property line.
|
||
|
||
** MAYBE Fancier searching for inherited tags
|
||
|
||
When tag inheritance is enabled, and the given tags aren't file-level tags, we could search directly to headings containing the matching tags, and then only do per-heading matching on the subtrees. Sometimes that would be much faster. However, that might make the logic special-cased and complicated. Might need a redesign of the whole matching/predicate system to do cleanly.
|
||
|
||
** DONE Byte-compile lambdas
|
||
CLOSED: [2018-05-09 Wed 17:30]
|
||
:LOGBOOK:
|
||
- State "DONE" from [2018-05-09 Wed 17:30]
|
||
:END:
|
||
|
||
=elfeed-search--update-list= byte-compiles lambdas returned by =elfeed-search-compile-filter=. Maybe I could do something like this too.
|
||
|
||
If I can get this working, I should profile it to see what difference it makes.
|
||
|
||
*** Profiling
|
||
|
||
Going to try byte-compiling the predicate function:
|
||
|
||
#+BEGIN_SRC elisp
|
||
(elp-profile 10 nil (org-agenda-ng "~/src/emacs/org-super-agenda/test/test.org"
|
||
(and (or (date :date '= (org-today))
|
||
(date :deadline '<= (+ org-deadline-warning-days (org-today)))
|
||
(date :scheduled '<= (org-today)))
|
||
(not (apply #'todo org-done-keywords-for-agenda)))))
|
||
#+END_SRC
|
||
|
||
#+RESULTS:
|
||
| Function | Times called | Total time | Average time |
|
||
|-------------------------------------------+--------------+--------------+--------------|
|
||
| org-agenda-ng--agenda | 10 | 0.8370581039 | 0.0837058104 |
|
||
| org-agenda-finalize-entries | 10 | 0.652886608 | 0.0652886608 |
|
||
| org-super-agenda--filter-finalize-entries | 10 | 0.641794501 | 0.0641794501 |
|
||
| org-super-agenda--group-items | 10 | 0.636057006 | 0.0636057006 |
|
||
| org-super-agenda--group-dispatch | 130 | 0.631911849 | 0.0048608603 |
|
||
| org-super-agenda--group-tag | 50 | 0.592883869 | 0.0118576773 |
|
||
| list | 2720 | 0.5792795169 | 0.0002129704 |
|
||
| mapcar | 331 | 0.2333591920 | 0.0007050126 |
|
||
| org-agenda-ng--filter-buffer | 10 | 0.09247626 | 0.009247626 |
|
||
| org-agenda-ng--format-element | 150 | 0.0649320479 | 0.0004328803 |
|
||
| org-entry-get | 860 | 0.0408285349 | 4.747...e-05 |
|
||
| org-agenda-ng--date-p | 910 | 0.0385646249 | 4.237...e-05 |
|
||
| org-element-headline-parser | 150 | 0.0374417470 | 0.0002496116 |
|
||
| org-is-habit-p | 270 | 0.0290107389 | 0.0001074471 |
|
||
| org--property-local-values | 270 | 0.0268615979 | 9.948...e-05 |
|
||
| org-get-property-block | 270 | 0.0244613309 | 9.059...e-05 |
|
||
| org-get-tags-at | 150 | 0.017875864 | 0.0001191724 |
|
||
| org-super-agenda--group-habit | 10 | 0.015910656 | 0.0015910655 |
|
||
| mapc | 2540 | 0.0158616290 | 6.244...e-06 |
|
||
| org-agenda-ng--add-faces | 150 | 0.0143329670 | 9.555...e-05 |
|
||
|
||
|
||
Now the same thing without byte-compiling:
|
||
|
||
#+BEGIN_SRC elisp
|
||
(elp-profile 10 nil (org-agenda-ng "~/src/emacs/org-super-agenda/test/test.org"
|
||
(and (or (date :date '= (org-today))
|
||
(date :deadline '<= (+ org-deadline-warning-days (org-today)))
|
||
(date :scheduled '<= (org-today)))
|
||
(not (apply #'todo org-done-keywords-for-agenda)))))
|
||
#+END_SRC
|
||
|
||
#+RESULTS:
|
||
| Function | Times called | Total time | Average time |
|
||
|-------------------------------------------+--------------+--------------+--------------|
|
||
| org-agenda-ng--agenda | 10 | 0.846645537 | 0.0846645537 |
|
||
| org-agenda-finalize-entries | 10 | 0.662896805 | 0.0662896805 |
|
||
| sort | 40 | 0.591123256 | 0.0147780814 |
|
||
| org-entries-lessp | 400 | 0.5901201620 | 0.0014753004 |
|
||
| mapcar | 201 | 0.2318270599 | 0.0011533684 |
|
||
| org-agenda-ng--filter-buffer | 10 | 0.092519787 | 0.0092519787 |
|
||
| org-super-agenda--filter-finalize-entries | 10 | 0.0664278040 | 0.0066427804 |
|
||
| org-agenda-ng--format-element | 150 | 0.064658994 | 0.0004310599 |
|
||
| org-super-agenda--group-items | 10 | 0.0602504089 | 0.0060250408 |
|
||
| org-super-agenda--group-dispatch | 130 | 0.0561904470 | 0.0004322342 |
|
||
| org-entry-get | 860 | 0.0437458889 | 5.086...e-05 |
|
||
| org-agenda-ng--date-p | 910 | 0.0382623409 | 4.204...e-05 |
|
||
| org-element-headline-parser | 150 | 0.0374662920 | 0.0002497752 |
|
||
| org-is-habit-p | 270 | 0.0320861079 | 0.0001188374 |
|
||
| org--property-local-values | 270 | 0.0298690430 | 0.0001106260 |
|
||
| org-get-property-block | 270 | 0.0274716649 | 0.0001017469 |
|
||
| org-super-agenda--group-habit | 10 | 0.019117901 | 0.0019117901 |
|
||
| org-get-tags-at | 150 | 0.0178958930 | 0.0001193059 |
|
||
| mapc | 2470 | 0.0150361130 | 6.087...e-06 |
|
||
| org-agenda-ng--add-faces | 150 | 0.0143092169 | 9.539...e-05 |
|
||
|
||
Virtually indistinguishable. Going to try moving the =byte-compile= call from the =org-agenda-ng= macro to other places...
|
||
|
||
#+BEGIN_SRC elisp
|
||
(elp-profile 10 nil (org-agenda-ng "~/src/emacs/org-super-agenda/test/test.org"
|
||
(and (or (date :date '= (org-today))
|
||
(date :deadline '<= (+ org-deadline-warning-days (org-today)))
|
||
(date :scheduled '<= (org-today)))
|
||
(not (apply #'todo org-done-keywords-for-agenda)))))
|
||
#+END_SRC
|
||
|
||
#+RESULTS:
|
||
| Function | Times called | Total time | Average time |
|
||
|-------------------------------------------+--------------+--------------+--------------|
|
||
| org-agenda-ng--agenda | 10 | 0.8476316779 | 0.0847631678 |
|
||
| mapcar | 331 | 0.8159452220 | 0.0024650913 |
|
||
| org-agenda-ng--filter-buffer | 10 | 0.674217912 | 0.0674217912 |
|
||
| org-element-headline-parser | 150 | 0.6171195889 | 0.0041141305 |
|
||
| line-beginning-position | 620 | 0.5802579680 | 0.0009358999 |
|
||
| org-agenda-finalize-entries | 10 | 0.082065157 | 0.0082065157 |
|
||
| org-super-agenda--filter-finalize-entries | 10 | 0.0708772279 | 0.0070877227 |
|
||
| org-super-agenda--group-items | 10 | 0.065523103 | 0.0065523103 |
|
||
| org-agenda-ng--format-element | 150 | 0.0652783740 | 0.0004351891 |
|
||
| org-super-agenda--group-dispatch | 130 | 0.0614253589 | 0.0004725027 |
|
||
| org-entry-get | 860 | 0.0494023029 | 5.744...e-05 |
|
||
| org-agenda-ng--date-p | 910 | 0.0388435519 | 4.268...e-05 |
|
||
| org-is-habit-p | 270 | 0.0375687549 | 0.0001391435 |
|
||
| org--property-local-values | 270 | 0.0353892929 | 0.0001310714 |
|
||
| org-get-property-block | 270 | 0.0329700440 | 0.0001221112 |
|
||
| org-super-agenda--group-habit | 10 | 0.024468601 | 0.0024468601 |
|
||
| re-search-backward | 1500 | 0.0186344089 | 1.242...e-05 |
|
||
| org-get-tags-at | 150 | 0.0180038809 | 0.0001200258 |
|
||
| mapc | 2540 | 0.0156518099 | 6.162...e-06 |
|
||
| org-agenda-ng--add-faces | 150 | 0.0144141080 | 9.609...e-05 |
|
||
|
||
Doesn't seem to make any difference.
|
||
|
||
** DONE Operate on list of heading positions
|
||
CLOSED: [2018-05-10 Thu 15:02]
|
||
:LOGBOOK:
|
||
- State "DONE" from [2018-05-10 Thu 15:02]
|
||
:END:
|
||
|
||
[2017-12-31 Sun 17:54] I wonder if, instead of parsing the whole buffer with =org-element-parse-buffer=, we could simply work on a list of heading positions, e.g. a loop would search forward to the next heading position, then call whatever predicates it needed at the heading's position, using =save-excursion= around each function call. The predicates would need to be updated to get their data from the buffer, instead of using =org-element-property=, but that wouldn't be hard.
|
||
|
||
[2018-05-10 Thu 15:01] I already changed to using buffer-parsing predicates instead of =org-element-parse-buffer=.
|
||
|
||
** DONE Use macros for =date=
|
||
CLOSED: [2018-05-10 Thu 14:59]
|
||
:LOGBOOK:
|
||
- State "DONE" from [2018-05-10 Thu 14:59]
|
||
:END:
|
||
|
||
If I made the =date= selector a macro, I could avoid the need to quote the comparator.
|
||
|
||
Also, maybe instead of having a single =date= selector, I should have =scheduled=, =deadline=, etc.
|
||
|
||
* References
|
||
|
||
** [[https://m00natic.github.io/lisp/manual-jit.html][Uniform Structured Syntax, Metaprogramming and Run-time Compilation]]
|
||
:PROPERTIES:
|
||
:archive.is: http://archive.is/33R9M
|
||
:END:
|
||
|
||
+ [[https://github.com/m00natic/cl-fdbq][GitHub - m00natic/cl-fdbq: SQL-like operations over fixed field DBs]]
|
||
|
||
* Examples / testing
|
||
|
||
#+BEGIN_SRC elisp
|
||
(org-agenda-ng org-agenda-files
|
||
(and (or (date :deadline '<= (org-today))
|
||
(date :scheduled '<= (org-today)))
|
||
(not (apply #'todo org-done-keywords-for-agenda)))
|
||
((group (tags "bills"))
|
||
(group (todo "SOMEDAY"))))
|
||
|
||
(org-agenda-ng org-agenda-files
|
||
(and (or (date :deadline '<= (org-today))
|
||
(date :scheduled '<= (org-today)))
|
||
(not (apply #'todo org-done-keywords-for-agenda))))
|
||
|
||
(org-agenda-ng "~/org/main.org"
|
||
(and (or (date :deadline '<= (org-today))
|
||
(date :scheduled '<= (org-today)))
|
||
(not (apply #'todo org-done-keywords-for-agenda))))
|
||
|
||
(org-ql org-agenda-files
|
||
(and (todo "SOMEDAY")
|
||
(tags "Emacs")))
|
||
(org-ql org-agenda-files
|
||
(and (todo "SOMEDAY")
|
||
(tags "Emacs")
|
||
(priority >= "B")))
|
||
(org-ql "~/org/main.org"
|
||
(and (or (tags "Emacs")
|
||
(priority >= "B"))
|
||
(not (done))))
|
||
(org-ql "~/org/main.org"
|
||
(and (or (tags "Emacs")
|
||
(priority >= "B"))
|
||
(done)))
|
||
#+END_SRC
|
||
|
||
** Sorting
|
||
|
||
#+BEGIN_SRC elisp
|
||
(org-ql "~/src/emacs/org-super-agenda/test/test.org"
|
||
(regexp "over")
|
||
:sort (priority deadline scheduled))
|
||
|
||
(org-ql "~/src/emacs/org-super-agenda/test/test.org"
|
||
(regexp "over")
|
||
:sort (date))
|
||
|
||
(org-ql "~/src/emacs/org-super-agenda/test/test.org"
|
||
(todo)
|
||
:sort (todo))
|
||
#+END_SRC
|
||
|
||
** Regexp matching
|
||
|
||
#+BEGIN_SRC elisp
|
||
(org-ql "~/src/emacs/org-super-agenda/test/test.org"
|
||
(regexp "over"))
|
||
|
||
(org-agenda-ng "~/src/emacs/org-super-agenda/test/test.org"
|
||
(regexp "over"))
|
||
#+END_SRC
|
||
|
||
** Property matching
|
||
|
||
#+BEGIN_SRC elisp
|
||
(org-agenda-ng "~/src/emacs/org-super-agenda/test/test.org"
|
||
(property "agenda-group"))
|
||
|
||
(org-agenda-ng "~/src/emacs/org-super-agenda/test/test.org"
|
||
(property "agenda-group" "plans"))
|
||
#+END_SRC
|
||
|
||
** Screenshot code
|
||
|
||
#+BEGIN_SRC elisp
|
||
(org-super-agenda--test-with-org-today-date "2017-07-08 00:00"
|
||
(org-agenda-ng "~/src/emacs/org-super-agenda/test/test.org"
|
||
(and (or (date = today)
|
||
(deadline <=)
|
||
(scheduled <= today))
|
||
(not (done)))))
|
||
#+END_SRC
|
||
|
||
* Profiling
|
||
|
||
** Preambles
|
||
|
||
Not sure if clearing the cache is necessary here, because it seemed to make nearly no difference in the results, but I don't know why.
|
||
|
||
#+BEGIN_SRC elisp :results silent
|
||
(cl-defmacro org-ql-preamble-bench (&key query (file "tests/data.org") (times 10))
|
||
`(bench-multi-lets :times ,times :ensure-equal t
|
||
:lets (("preamble" ((org-ql-use-preamble t)
|
||
(org-ql-cache (ht))))
|
||
("no preamble" ((org-ql-use-preamble nil)
|
||
(org-ql-cache (ht)))))
|
||
:forms ((,(prin1-to-string query) (org-ql-select ,file
|
||
',query
|
||
:action '(org-get-heading t t))))))
|
||
#+END_SRC
|
||
|
||
*** =closed=
|
||
|
||
#+BEGIN_SRC elisp
|
||
(org-ql-preamble-bench :times 1
|
||
:file "~/org/inbox.org"
|
||
:query (closed))
|
||
#+END_SRC
|
||
|
||
#+RESULTS:
|
||
| Form | x faster than next | Total runtime | # of GCs | Total GC runtime |
|
||
|-----------------------+--------------------+---------------+----------+------------------|
|
||
| preamble: (closed) | 4.80 | 0.086553 | 0 | 0 |
|
||
| no preamble: (closed) | slowest | 0.415165 | 0 | 0 |
|
||
|
||
#+BEGIN_SRC elisp
|
||
(org-ql-preamble-bench :times 1
|
||
:file "~/org/inbox.org"
|
||
:query (closed <= "2019-01-01"))
|
||
#+END_SRC
|
||
|
||
#+RESULTS:
|
||
| Form | x faster than next | Total runtime | # of GCs | Total GC runtime |
|
||
|---------------------------------------+--------------------+---------------+----------+------------------|
|
||
| preamble: (closed <= "2019-01-01") | 4.21 | 0.105782 | 0 | 0 |
|
||
| no preamble: (closed <= "2019-01-01") | slowest | 0.445374 | 0 | 0 |
|
||
|
||
*** =deadline=
|
||
|
||
#+BEGIN_SRC elisp
|
||
(org-ql-preamble-bench :times 1
|
||
:file "~/org/inbox.org"
|
||
:query (deadline))
|
||
#+END_SRC
|
||
|
||
#+RESULTS:
|
||
| Form | x faster than next | Total runtime | # of GCs | Total GC runtime |
|
||
|-------------------------+--------------------+---------------+----------+------------------|
|
||
| preamble: (deadline) | 27.63 | 0.014656 | 0 | 0 |
|
||
| no preamble: (deadline) | slowest | 0.404952 | 0 | 0 |
|
||
|
||
#+BEGIN_SRC elisp
|
||
(org-ql-preamble-bench :times 1
|
||
:file "~/org/inbox.org"
|
||
:query (deadline <= "2019-01-01"))
|
||
#+END_SRC
|
||
|
||
#+RESULTS:
|
||
| Form | x faster than next | Total runtime | # of GCs | Total GC runtime |
|
||
|-----------------------------------------+--------------------+---------------+----------+------------------|
|
||
| preamble: (deadline <= "2019-01-01") | 27.91 | 0.014606 | 0 | 0 |
|
||
| no preamble: (deadline <= "2019-01-01") | slowest | 0.407682 | 0 | 0 |
|
||
|
||
*** =habit=
|
||
|
||
#+BEGIN_SRC elisp
|
||
(org-ql-preamble-bench :times 1
|
||
:file "~/org/inbox.org"
|
||
:query (habit))
|
||
#+END_SRC
|
||
|
||
#+RESULTS:
|
||
| Form | x faster than next | Total runtime | # of GCs | Total GC runtime |
|
||
|----------------------+--------------------+---------------+----------+------------------|
|
||
| preamble: (habit) | 70.09 | 0.016489 | 0 | 0 |
|
||
| no preamble: (habit) | slowest | 1.155649 | 0 | 0 |
|
||
|
||
*** =level=
|
||
|
||
#+BEGIN_SRC elisp
|
||
(org-ql-preamble-bench :times 1
|
||
:file "~/org/inbox.org"
|
||
:query (level 1))
|
||
#+END_SRC
|
||
|
||
#+RESULTS:
|
||
| Form | x faster than next | Total runtime | # of GCs | Total GC runtime |
|
||
|------------------------+--------------------+---------------+----------+------------------|
|
||
| preamble: (level 1) | 1.34 | 0.562950 | 0 | 0 |
|
||
| no preamble: (level 1) | slowest | 0.754050 | 0 | 0 |
|
||
|
||
*** =property=
|
||
|
||
#+BEGIN_SRC elisp
|
||
(org-ql-preamble-bench :times 1
|
||
:file "~/org/inbox.org"
|
||
:query (property "agenda-group"))
|
||
#+END_SRC
|
||
|
||
#+RESULTS:
|
||
| Form | x faster than next | Total runtime | # of GCs | Total GC runtime |
|
||
|----------------------------------------+--------------------+---------------+----------+------------------|
|
||
| preamble: (property "agenda-group") | 70.44 | 0.016571 | 0 | 0 |
|
||
| no preamble: (property "agenda-group") | slowest | 1.167203 | 0 | 0 |
|
||
|
||
#+BEGIN_SRC elisp
|
||
(org-ql-preamble-bench :times 1
|
||
:file "~/org/inbox.org"
|
||
:query (property "ID"))
|
||
#+END_SRC
|
||
|
||
#+RESULTS:
|
||
| Form | x faster than next | Total runtime | # of GCs | Total GC runtime |
|
||
|------------------------------+--------------------+---------------+----------+------------------|
|
||
| preamble: (property "ID") | 3.51 | 0.369830 | 0 | 0 |
|
||
| no preamble: (property "ID") | slowest | 1.299684 | 0 | 0 |
|
||
|
||
#+BEGIN_SRC elisp
|
||
(org-ql-preamble-bench :times 1
|
||
:file "~/org/inbox.org"
|
||
:query (property "agenda-group" "plans"))
|
||
#+END_SRC
|
||
|
||
#+RESULTS:
|
||
| Form | x faster than next | Total runtime | # of GCs | Total GC runtime |
|
||
|------------------------------------------------+--------------------+---------------+----------+------------------|
|
||
| preamble: (property "agenda-group" "plans") | 72.54 | 0.016862 | 0 | 0 |
|
||
| no preamble: (property "agenda-group" "plans") | slowest | 1.223197 | 0 | 0 |
|
||
|
||
*** =scheduled=
|
||
|
||
#+BEGIN_SRC elisp
|
||
(org-ql-preamble-bench :times 1
|
||
:file "~/org/inbox.org"
|
||
:query (scheduled))
|
||
#+END_SRC
|
||
|
||
#+RESULTS:
|
||
| Form | x faster than next | Total runtime | # of GCs | Total GC runtime |
|
||
|--------------------------+--------------------+---------------+----------+------------------|
|
||
| preamble: (scheduled) | 4.45 | 0.100968 | 0 | 0 |
|
||
| no preamble: (scheduled) | slowest | 0.449321 | 0 | 0 |
|
||
|
||
#+BEGIN_SRC elisp
|
||
(org-ql-preamble-bench :times 1
|
||
:file "~/org/inbox.org"
|
||
:query (scheduled <= "2019-01-01"))
|
||
#+END_SRC
|
||
|
||
#+RESULTS:
|
||
| Form | x faster than next | Total runtime | # of GCs | Total GC runtime |
|
||
|------------------------------------------+--------------------+---------------+----------+------------------|
|
||
| preamble: (scheduled <= "2019-01-01") | 4.13 | 0.111067 | 0 | 0 |
|
||
| no preamble: (scheduled <= "2019-01-01") | slowest | 0.458726 | 0 | 0 |
|
||
|
||
*** =tags=
|
||
|
||
If tag inheritance is enabled, we have to check tags on every heading. When it's disabled, we can search directly to headings with the given tags.
|
||
|
||
#+BEGIN_SRC elisp
|
||
(let ((org-use-tag-inheritance t))
|
||
(org-ql-preamble-bench :times 1
|
||
:file "~/org/inbox.org"
|
||
:query (tags "Emacs")))
|
||
#+END_SRC
|
||
|
||
#+RESULTS:
|
||
| Form | x faster than next | Total runtime | # of GCs | Total GC runtime |
|
||
|-----------------------------+--------------------+---------------+----------+------------------|
|
||
| no preamble: (tags "Emacs") | 1.01 | 1.899647 | 0 | 0 |
|
||
| preamble: (tags "Emacs") | slowest | 1.921799 | 0 | 0 |
|
||
|
||
#+BEGIN_SRC elisp
|
||
(let ((org-use-tag-inheritance nil))
|
||
(org-ql-preamble-bench :times 1
|
||
:file "~/org/inbox.org"
|
||
:query (tags "Emacs")))
|
||
#+END_SRC
|
||
|
||
#+RESULTS:
|
||
| Form | x faster than next | Total runtime | # of GCs | Total GC runtime |
|
||
|-----------------------------+--------------------+---------------+----------+------------------|
|
||
| preamble: (tags "Emacs") | 2.08 | 0.274555 | 0 | 0 |
|
||
| no preamble: (tags "Emacs") | slowest | 0.570116 | 0 | 0 |
|
||
|
||
*** ~ts~
|
||
|
||
#+BEGIN_SRC elisp
|
||
(org-ql-preamble-bench :times 1
|
||
:file "~/org/inbox.org"
|
||
:query (ts))
|
||
#+END_SRC
|
||
|
||
#+RESULTS:
|
||
| Form | x faster than next | Total runtime | # of GCs | Total GC runtime |
|
||
|-------------------+--------------------+---------------+----------+------------------|
|
||
| preamble: (ts) | 1.13 | 0.475646 | 0 | 0 |
|
||
| no preamble: (ts) | slowest | 0.535950 | 0 | 0 |
|
||
|
||
#+BEGIN_SRC elisp
|
||
(org-ql-preamble-bench :times 1
|
||
:file "~/org/inbox.org"
|
||
:query (ts :from "2019-01-01"))
|
||
#+END_SRC
|
||
|
||
#+RESULTS:
|
||
| Form | x faster than next | Total runtime | # of GCs | Total GC runtime |
|
||
|--------------------------------------+--------------------+---------------+----------+------------------|
|
||
| no preamble: (ts :from "2019-01-01") | 1.11 | 0.537445 | 0 | 0 |
|
||
| preamble: (ts :from "2019-01-01") | slowest | 0.594534 | 0 | 0 |
|
||
|
||
#+BEGIN_SRC elisp
|
||
(org-ql-preamble-bench :times 1
|
||
:file "~/org/inbox.org"
|
||
:query (ts :from "2017-01-01"))
|
||
#+END_SRC
|
||
|
||
#+RESULTS:
|
||
| Form | x faster than next | Total runtime | # of GCs | Total GC runtime |
|
||
|--------------------------------------+--------------------+---------------+----------+------------------|
|
||
| no preamble: (ts :from "2017-01-01") | 1.13 | 0.526891 | 0 | 0 |
|
||
| preamble: (ts :from "2017-01-01") | slowest | 0.594360 | 0 | 0 |
|
||
|
||
Not sure why that one is slower with preamble.
|
||
|
||
#+BEGIN_SRC elisp
|
||
(org-ql-preamble-bench :times 10
|
||
:query (ts :from "2017-01-01"))
|
||
#+END_SRC
|
||
|
||
#+RESULTS:
|
||
| Form | x faster than next | Total runtime | # of GCs | Total GC runtime |
|
||
|--------------------------------------+--------------------+---------------+----------+------------------|
|
||
| no preamble: (ts :from "2017-01-01") | 1.04 | 0.025688 | 0 | 0 |
|
||
| preamble: (ts :from "2017-01-01") | slowest | 0.026642 | 0 | 0 |
|
||
|
||
#+BEGIN_SRC elisp
|
||
(org-ql-preamble-bench :times 1
|
||
:file "~/org/inbox.org"
|
||
:query (ts :to "2010-01-01"))
|
||
#+END_SRC
|
||
|
||
#+RESULTS:
|
||
| Form | x faster than next | Total runtime | # of GCs | Total GC runtime |
|
||
|------------------------------------+--------------------+---------------+----------+------------------|
|
||
| no preamble: (ts :to "2010-01-01") | 1.10 | 0.538603 | 0 | 0 |
|
||
| preamble: (ts :to "2010-01-01") | slowest | 0.593466 | 0 | 0 |
|
||
|
||
*** ~ts-active~
|
||
|
||
#+BEGIN_SRC elisp
|
||
(org-ql-preamble-bench :times 1
|
||
:file "~/org/inbox.org"
|
||
:query (ts-a))
|
||
#+END_SRC
|
||
|
||
#+RESULTS:
|
||
| Form | x faster than next | Total runtime | # of GCs | Total GC runtime |
|
||
|---------------------+--------------------+---------------+----------+------------------|
|
||
| preamble: (ts-a) | 4.77 | 0.071489 | 0 | 0 |
|
||
| no preamble: (ts-a) | slowest | 0.340896 | 0 | 0 |
|
||
|
||
#+BEGIN_SRC elisp
|
||
(org-ql-preamble-bench :times 1
|
||
:file "~/org/inbox.org"
|
||
:query (ts-a :from "2017-07-06"))
|
||
#+END_SRC
|
||
|
||
#+RESULTS:
|
||
| Form | x faster than next | Total runtime | # of GCs | Total GC runtime |
|
||
|----------------------------------------+--------------------+---------------+----------+------------------|
|
||
| preamble: (ts-a :from "2017-07-06") | 1.78 | 0.188369 | 0 | 0 |
|
||
| no preamble: (ts-a :from "2017-07-06") | slowest | 0.335975 | 0 | 0 |
|
||
|
||
#+BEGIN_SRC elisp
|
||
(org-ql-preamble-bench :times 1
|
||
:file "~/org/inbox.org"
|
||
:query (ts-a :to "2017-07-06"))
|
||
#+END_SRC
|
||
|
||
#+RESULTS:
|
||
| Form | x faster than next | Total runtime | # of GCs | Total GC runtime |
|
||
|--------------------------------------+--------------------+---------------+----------+------------------|
|
||
| preamble: (ts-a :to "2017-07-06") | 4.64 | 0.075307 | 0 | 0 |
|
||
| no preamble: (ts-a :to "2017-07-06") | slowest | 0.349445 | 0 | 0 |
|
||
|
||
#+BEGIN_SRC elisp
|
||
(org-ql-preamble-bench :times 1
|
||
:file "~/org/inbox.org"
|
||
:query (ts-a :on "2017-07-06"))
|
||
#+END_SRC
|
||
|
||
#+RESULTS:
|
||
| Form | x faster than next | Total runtime | # of GCs | Total GC runtime |
|
||
|--------------------------------------+--------------------+---------------+----------+------------------|
|
||
| preamble: (ts-a :on "2017-07-06") | 4.33 | 0.076075 | 0 | 0 |
|
||
| no preamble: (ts-a :on "2017-07-06") | slowest | 0.329106 | 0 | 0 |
|
||
|
||
*** ~ts-inactive~
|
||
|
||
#+BEGIN_SRC elisp
|
||
(org-ql-preamble-bench :times 1
|
||
:file "~/org/inbox.org"
|
||
:query (ts-i))
|
||
#+END_SRC
|
||
|
||
#+RESULTS:
|
||
| Form | x faster than next | Total runtime | # of GCs | Total GC runtime |
|
||
|---------------------+--------------------+---------------+----------+------------------|
|
||
| preamble: (ts-i) | 1.21 | 0.459152 | 0 | 0 |
|
||
| no preamble: (ts-i) | slowest | 0.555632 | 0 | 0 |
|
||
|
||
#+BEGIN_SRC elisp
|
||
(org-ql-preamble-bench :times 1
|
||
:file "~/org/inbox.org"
|
||
:query (ts-i :from "2019-07-06"))
|
||
#+END_SRC
|
||
|
||
#+RESULTS:
|
||
| Form | x faster than next | Total runtime | # of GCs | Total GC runtime |
|
||
|----------------------------------------+--------------------+---------------+----------+------------------|
|
||
| no preamble: (ts-i :from "2019-07-06") | 1.09 | 0.531976 | 0 | 0 |
|
||
| preamble: (ts-i :from "2019-07-06") | slowest | 0.579745 | 0 | 0 |
|
||
|
||
#+BEGIN_SRC elisp
|
||
(org-ql-preamble-bench :times 1
|
||
:file "~/org/inbox.org"
|
||
:query (ts-i :to "2019-07-06"))
|
||
#+END_SRC
|
||
|
||
#+RESULTS:
|
||
| Form | x faster than next | Total runtime | # of GCs | Total GC runtime |
|
||
|--------------------------------------+--------------------+---------------+----------+------------------|
|
||
| no preamble: (ts-i :to "2019-07-06") | 1.34 | 0.553428 | 0 | 0 |
|
||
| preamble: (ts-i :to "2019-07-06") | slowest | 0.743881 | 0 | 0 |
|
||
|
||
** with/without ts.el
|
||
|
||
[2019-08-11 Sun 15:39] These results seem to show a minor performance improvement by using ~ts~, and the code is simpler.
|
||
|
||
#+BEGIN_SRC elisp
|
||
;; (require 'ts)
|
||
|
||
(org-ql--defpred ts-ts (&key from to _on)
|
||
;; The underscore before `on' prevents "unused lexical variable" warnings, because we
|
||
;; pre-process that argument in a macro before this function is called.
|
||
"Return non-nil if current entry has a timestamp in given period.
|
||
If no arguments are specified, return non-nil if entry has any
|
||
timestamp.
|
||
|
||
If FROM, return non-nil if entry has a timestamp on or after
|
||
FROM.
|
||
|
||
If TO, return non-nil if entry has a timestamp on or before TO.
|
||
|
||
If ON, return non-nil if entry has a timestamp on date ON.
|
||
|
||
FROM, TO, and ON should be strings parseable by
|
||
`parse-time-string' but may omit the time value."
|
||
;; TODO: DRY this with the clocked predicate.
|
||
;; NOTE: FROM and TO are actually expected to be Unix timestamps. The docstring is written
|
||
;; for end users, for which the arguments are pre-processed by `org-ql-select'.
|
||
;; FIXME: This assumes every "clocked" entry is a range. Unclosed clock entries are not handled.
|
||
(cl-macrolet ((next-timestamp ()
|
||
`(when (re-search-forward org-element--timestamp-regexp end-pos t)
|
||
(ts-parse-org (match-string 0))))
|
||
(test-timestamps (pred-form)
|
||
`(cl-loop for next-ts = (next-timestamp)
|
||
while next-ts
|
||
thereis ,pred-form)))
|
||
(save-excursion
|
||
(let ((end-pos (org-entry-end-position)))
|
||
(cond ((not (or from to)) (re-search-forward org-element--timestamp-regexp end-pos t))
|
||
((and from to) (test-timestamps (and (ts<= from next-ts)
|
||
(ts<= next-ts to))))
|
||
(from (test-timestamps (ts<= from next-ts)))
|
||
(to (test-timestamps (ts<= next-ts to))))))))
|
||
|
||
#+END_SRC
|
||
|
||
*** Without timestamp argument
|
||
|
||
#+BEGIN_SRC elisp
|
||
(bench-multi-lexical :times 1 :ensure-equal t
|
||
:forms (("old ts" (org-ql "~/org/inbox.org"
|
||
(ts)))
|
||
("ts.el ts" (org-ql "~/org/inbox.org"
|
||
(ts-ts)))))
|
||
#+END_SRC
|
||
|
||
#+RESULTS:
|
||
| Form | x faster than next | Total runtime | # of GCs | Total GC runtime |
|
||
|----------+--------------------+---------------+----------+------------------|
|
||
| ts.el ts | 1.14 | 2.251801 | 0 | 0 |
|
||
| old ts | slowest | 2.560280 | 0 | 0 |
|
||
|
||
#+BEGIN_SRC elisp
|
||
(bench-multi-lexical :times 20 :ensure-equal t
|
||
:forms (("old ts" (org-ql "~/src/emacs/org-ql/tests/data.org"
|
||
(ts)))
|
||
("ts.el ts" (org-ql "~/src/emacs/org-ql/tests/data.org"
|
||
(ts-ts)))))
|
||
#+END_SRC
|
||
|
||
#+RESULTS:
|
||
| Form | x faster than next | Total runtime | # of GCs | Total GC runtime |
|
||
|----------+--------------------+---------------+----------+------------------|
|
||
| ts.el ts | 1.05 | 0.103714 | 0 | 0 |
|
||
| old ts | slowest | 0.108663 | 0 | 0 |
|
||
|
||
*** :from
|
||
|
||
#+BEGIN_SRC elisp
|
||
(bench-multi-lexical :times 1 :ensure-equal t
|
||
:forms (("old ts" (org-ql "~/org/inbox.org"
|
||
(ts :from "2017-01-01")))
|
||
("ts.el ts" (org-ql "~/org/inbox.org"
|
||
(ts-ts :from "2017-01-01")))))
|
||
#+END_SRC
|
||
|
||
#+RESULTS:
|
||
| Form | x faster than next | Total runtime | # of GCs | Total GC runtime |
|
||
|----------+--------------------+---------------+----------+------------------|
|
||
| ts.el ts | 1.32 | 1.299966 | 0 | 0 |
|
||
| old ts | slowest | 1.713027 | 0 | 0 |
|
||
|
||
*** :to
|
||
|
||
#+BEGIN_SRC elisp
|
||
(bench-multi-lexical :times 1 :ensure-equal t
|
||
:forms (("old ts" (org-ql "~/org/inbox.org"
|
||
(ts :to "2019-01-01")))
|
||
("ts.el ts" (org-ql "~/org/inbox.org"
|
||
(ts-ts :to "2019-01-01")))))
|
||
#+END_SRC
|
||
|
||
#+RESULTS:
|
||
| Form | x faster than next | Total runtime | # of GCs | Total GC runtime |
|
||
|----------+--------------------+---------------+----------+------------------|
|
||
| ts.el ts | 1.01 | 1.300084 | 0 | 0 |
|
||
| old ts | slowest | 1.312208 | 0 | 0 |
|
||
|
||
*** :on
|
||
|
||
#+BEGIN_SRC elisp
|
||
(bench-multi-lexical :times 1 :ensure-equal t
|
||
:forms (("old ts" (org-ql "~/org/inbox.org"
|
||
(ts :on "2019-05-14")))
|
||
("ts.el ts" (org-ql "~/org/inbox.org"
|
||
(ts-ts :on "2019-05-14")))))
|
||
#+END_SRC
|
||
|
||
#+RESULTS:
|
||
| Form | x faster than next | Total runtime | # of GCs | Total GC runtime |
|
||
|----------+--------------------+---------------+----------+------------------|
|
||
| ts.el ts | 1.17 | 0.557281 | 0 | 0 |
|
||
| old ts | slowest | 0.652149 | 0 | 0 |
|
||
|
||
** Using =org-element-parse-buffer=
|
||
|
||
This basically works, as a very basic kind of agenda view, but we can already see that it's much slower (at least, for single-day views) because =org-element-parse-buffer= is slow compared to the agenda code.
|
||
|
||
[2018-05-10 Thu 15:03] *Note:* This is the old, much slower code that used =org-element-parse-buffer=.
|
||
|
||
*** Macro
|
||
|
||
#+BEGIN_SRC elisp
|
||
(defmacro elp-profile (times prefixes &rest body)
|
||
(declare (indent defun))
|
||
(let ((prefixes (append '(org- string- s- buffer- append delq map
|
||
list car save- outline- delete-dups
|
||
sort line- nth concat char-to-string
|
||
rx- goto- when search- re-)
|
||
prefixes)))
|
||
`(let (output)
|
||
(dolist (prefix ',prefixes)
|
||
(elp-instrument-package (symbol-name prefix)))
|
||
(dotimes (x ,times)
|
||
,@body)
|
||
(elp-results)
|
||
(elp-restore-all)
|
||
(point-min)
|
||
(forward-line 20)
|
||
(delete-region (point) (point-max))
|
||
(setq output (buffer-substring-no-properties (point-min) (point-max)))
|
||
(kill-buffer)
|
||
(delete-window)
|
||
(let ((rows (s-lines output)))
|
||
(append (list (list "Function" "Times called" "Total time" "Average time")
|
||
'hline)
|
||
(cl-loop for row in rows
|
||
collect (s-split (rx (1+ space)) row 'omit-nulls)))))))
|
||
#+END_SRC
|
||
|
||
[2018-05-09 Wed 17:31] *Note*: I seem to have misplaced the =org-agenda-ng--test-agenda-today= function I used in these tests.
|
||
|
||
*** ng
|
||
|
||
#+BEGIN_SRC elisp
|
||
(elp-profile 1 (org-agenda-ng--test-agenda-today))
|
||
#+END_SRC
|
||
|
||
#+RESULTS:
|
||
#+begin_example
|
||
org-element--parse-elements 5832 18.501891926 0.0031724780
|
||
mapcar 98 6.3412930759 0.0647070722
|
||
org-agenda-ng--test-agenda-today 1 6.30112088 6.30112088
|
||
org-agenda-ng--agenda-multi 1 6.301086333 6.301086333
|
||
org-agenda-ng--get-entries 8 6.249823971 0.7812279963
|
||
mapc 2803 5.9078545849 0.0021076898
|
||
org-element-parse-buffer 8 4.796204625 0.5995255781
|
||
org-element--current-element 6557 3.7164850469 0.0005667965
|
||
org-element-headline-parser 6557 3.5548915590 0.0005421521
|
||
org-end-of-subtree 6557 1.3663438270 0.0002083794
|
||
org-agenda-ng--filter-tree 8 1.3661297829 0.1707662228
|
||
org-element-map 8 1.365995685 0.1707494606
|
||
line-end-position 9503 0.4900104040 5.156...e-05
|
||
org-at-heading-p 12389 0.4574876539 3.692...e-05
|
||
re-search-forward 20193 0.4566419319 2.261...e-05
|
||
outline-on-heading-p 19286 0.4559736580 2.364...e-05
|
||
org-outline-level 6775 0.3970647569 5.860...e-05
|
||
org-back-to-heading 6897 0.3689033409 5.348...e-05
|
||
outline-back-to-heading 6897 0.3587580889 5.201...e-05
|
||
line-beginning-position 11702 0.2887473860 2.467...e-05
|
||
#+end_example
|
||
|
||
*** orig
|
||
|
||
Make sure to kill any existing agenda buffers first.
|
||
|
||
#+BEGIN_SRC elisp
|
||
(elp-profile 1 (org-agenda-list nil nil 'week))
|
||
#+END_SRC
|
||
|
||
#+RESULTS:
|
||
#+begin_example
|
||
org-agenda-list 1 1.717467214 1.717467214
|
||
org-agenda-get-day-entries 7 1.124906724 0.1607009605
|
||
org-agenda-get-scheduled 7 0.9354116170 0.1336302310
|
||
org-get-tags-at 62 0.5598817790 0.0090303512
|
||
org-up-heading-safe 262 0.5531687240 0.0021113310
|
||
org-back-to-heading 2646 0.5316139889 0.0002009123
|
||
org-agenda-finalize 1 0.485185818 0.485185818
|
||
org-agenda-skip 749 0.4059732339 0.0005420203
|
||
org-at-planning-p 921 0.2137141959 0.0002320458
|
||
org-is-habit-p 574 0.1953095319 0.0003402605
|
||
org-entry-get 579 0.195275877 0.0003372640
|
||
org--property-local-values 574 0.1899641870 0.0003309480
|
||
org-get-property-block 574 0.1789142650 0.0003116973
|
||
re-search-backward 3586 0.1769497870 4.934...e-05
|
||
org-inlinetask-in-task-p 1495 0.1639709820 0.0001096795
|
||
outline-back-to-heading 2646 0.1387423440 5.243...e-05
|
||
re-search-forward 3177 0.1353034909 4.258...e-05
|
||
org-agenda-get-deadlines 7 0.1341101260 0.0191585894
|
||
line-beginning-position 2041 0.1000089939 4.899...e-05
|
||
org-get-todo-state 749 0.070545971 9.418...e-05
|
||
org-agenda-prepare 1 0.052788647 0.052788647
|
||
org-agenda-prepare-buffers 1 0.050402675 0.050402675
|
||
org-agenda-get-timestamps 7 0.0428353419 0.0061193345
|
||
org-agenda--timestamp-to-absolute 1498 0.0414448099 2.766...e-05
|
||
org-time-string-to-absolute 1498 0.0385546620 2.573...e-05
|
||
org-agenda-finalize-entries 7 0.03400573 0.0048579614
|
||
org-super-agenda--finalize-entries 7 0.0339819269 0.0048545609
|
||
org-outline-level 505 0.0335176070 6.637...e-05
|
||
org-super-agenda--group-items 7 0.0268096709 0.0038299529
|
||
org-super-agenda--group-dispatch 84 0.024216379 0.0002882902
|
||
org-parse-time-string 1572 0.0211881319 1.347...e-05
|
||
org-closest-date 749 0.0178231690 2.379...e-05
|
||
org-before-first-heading-p 578 0.0142076310 2.458...e-05
|
||
org-refresh-category-properties 1 0.013815263 0.013815263
|
||
org-in-src-block-p 753 0.0135235599 1.795...e-05
|
||
org-refresh-stats-properties 1 0.012230309 0.012230309
|
||
org-habit-parse-todo 5 0.0121474539 0.0024294907
|
||
org-get-limited-outline-regexp 1502 0.0100960829 6.721...e-06
|
||
mapcar 309 0.009495786 3.073...e-05
|
||
org-super-agenda--group-habit 7 0.009318616 0.0013312308
|
||
string-match 6253 0.0090207890 1.442...e-06
|
||
org-super-agenda--group-dispatch-and 7 0.0067444 0.0009634857
|
||
org-agenda-get-blocks 7 0.0060974240 0.0008710605
|
||
outline-on-heading-p 2655 0.0060741090 2.287...e-06
|
||
org-agenda-get-sexps 7 0.0057924309 0.0008274901
|
||
org-super-agenda--group-regexp 7 0.005592509 0.0007989298
|
||
org-refresh-properties 2 0.005461118 0.002730559
|
||
org-super-agenda--get-item-entry 31 0.004812809 0.0001552519
|
||
org-agenda-align-tags 1 0.004677699 0.004677699
|
||
org-set-regexps-and-options 1 0.004533983 0.004533983
|
||
org--setup-collect-keywords 2 0.004499168 0.002249584
|
||
org-agenda-format-item 31 0.0039898020 0.0001287032
|
||
org-date-to-gregorian 420 0.0039648049 9.440...e-06
|
||
org-agenda-highlight-todo 31 0.0039479179 0.0001273521
|
||
string-to-number 8202 0.0031924329 3.892...e-07
|
||
org-end-of-subtree 12 0.003047285 0.0002539404
|
||
org-super-agenda--group-tag 35 0.002941374 8.403...e-05
|
||
org-inlinetask-outline-regexp 1495 0.002887697 1.931...e-06
|
||
org-get-wdays 749 0.0027946290 3.731...e-06
|
||
org-refresh-effort-properties 1 0.002750279 0.002750279
|
||
org-entry-beginning-position 31 0.002345909 7.567...e-05
|
||
sort 25 0.0021000059 8.400...e-05
|
||
mapc 445 0.0018132390 4.074...e-06
|
||
line-end-position 72 0.00177188 2.460...e-05
|
||
mapconcat 341 0.0016574119 4.860...e-06
|
||
org-entries-lessp 60 0.0016203450 2.700...e-05
|
||
concat 336 0.0016188640 4.818...e-06
|
||
org-habit-insert-consistency-graphs 1 0.001368346 0.001368346
|
||
org-add-props 137 0.001291149 9.424...e-06
|
||
org-element-at-point 1 0.001266403 0.001266403
|
||
org-agenda-new-marker 62 0.001253987 2.022...e-05
|
||
outline-next-heading 42 0.001123596 2.675...e-05
|
||
org-split-string 148 0.0011049120 7.465...e-06
|
||
org-element--parse-to 1 0.001074227 0.001074227
|
||
org-get-scheduled-time 5 0.0010200300 0.000204006
|
||
org-super-agenda--group-todo 21 0.001003225 4.777...e-05
|
||
org-time-string-to-time 69 0.0009947770 1.441...e-05
|
||
org-element--current-element 4 0.0009597410 0.0002399352
|
||
org-entry-properties 5 0.0008807149 0.0001761429
|
||
org-at-date-range-p 172 0.0008412679 4.891...e-06
|
||
org-agenda-mode 1 0.000787997 0.000787997
|
||
org-super-agenda--group-log 14 0.0007874939 5.624...e-05
|
||
buffer-substring 31 0.0007650360 2.467...e-05
|
||
org-heading-components 9 0.00071644 7.960...e-05
|
||
org-entry-end-position 31 0.0007046580 2.273...e-05
|
||
string-prefix-p 789 0.0006732279 8.532...e-07
|
||
org-agenda-skip-eval 1498 0.0006586869 4.397...e-07
|
||
org-get-repeat 5 0.000656577 0.0001313153
|
||
org-activate-bracket-links 3 0.000648713 0.0002162376
|
||
org-agenda-fix-displayed-tags 31 0.000636446 2.053...e-05
|
||
s-join 252 0.0006324150 2.509...e-06
|
||
org-element-keyword-parser 4 0.000530311 0.0001325777
|
||
org-in-commented-heading-p 4 0.00051077 0.0001276925
|
||
buffer-substring-no-properties 308 0.0004763350 1.546...e-06
|
||
org-habit-build-graph 5 0.0004689199 9.3784e-05
|
||
car 1626 0.0004469320 2.748...e-07
|
||
org-activate-plain-links 3 0.000382191 0.000127397
|
||
org-super-agenda--transform-groups 7 0.0003747289 5.353...e-05
|
||
org-get-priority 26 0.0003598600 1.384...e-05
|
||
org-agenda-fontify-priorities 1 0.000357076 0.000357076
|
||
org-super-agenda--group-priority 14 0.00035224 2.516e-05
|
||
org-agenda-prepare-window 1 0.00033704 0.00033704
|
||
org-find-text-property-in-string 316 0.0003191880 1.010...e-06
|
||
org-not-nil 821 0.0003016530 3.674...e-07
|
||
list 940 0.0002995150 3.186...e-07
|
||
org-super-agenda--group-time-grid 7 0.0002954999 4.221...e-05
|
||
org-agenda-format-date-aligned 7 0.0002794120 3.991...e-05
|
||
org-super-agenda--get-tags 103 0.0002654610 2.577...e-06
|
||
delq 513 0.0002634709 5.135...e-07
|
||
org-replace-escapes 5 0.0002382050 4.7641e-05
|
||
car-safe 911 0.0002314199 2.540...e-07
|
||
org-today 48 0.0002232539 4.651...e-06
|
||
org-get-time-of-day 19 0.000219044 1.152...e-05
|
||
org-days-to-iso-week 9 0.0002125040 2.361...e-05
|
||
append 433 0.0002083290 4.811...e-07
|
||
org-get-category 31 0.000198604 6.406...e-06
|
||
string-match-p 31 0.0001787880 5.767...e-06
|
||
org-agenda-today-p 21 0.0001658670 7.898...e-06
|
||
org-super-agenda--get-marker 54 0.0001629399 3.017...e-06
|
||
delete-dups 111 0.0001343219 1.210...e-06
|
||
org-at-heading-p 9 0.000128871 1.4319e-05
|
||
string-equal 361 0.0001168969 3.238...e-07
|
||
org-super-agenda--make-agenda-header 13 0.0001151760 8.859...e-06
|
||
org-add-prop-inherited 142 0.0001142290 8.044...e-07
|
||
org-check-agenda-file 8 0.000110448 1.3806e-05
|
||
org-agenda-get-day-face 7 0.000110437 1.577...e-05
|
||
org-get-agenda-file-buffer 8 0.000107414 1.342675e-05
|
||
org-agenda-files 3 0.000102652 3.421...e-05
|
||
org-downcase-keep-props 90 0.0001008230 1.120...e-06
|
||
org-super-agenda--get-priority-cookie 15 9.460...e-05 6.307e-06
|
||
org-get-todo-face 31 9.423...e-05 3.039...e-06
|
||
org-find-base-buffer-visiting 8 8.7492e-05 1.09365e-05
|
||
org-habit-get-faces 140 8.080...e-05 5.771...e-07
|
||
org-remove-uninherited-tags 176 7.580...e-05 4.307...e-07
|
||
goto-char 31 7.1014e-05 2.290...e-06
|
||
org-super-agenda--transform-group-order 7 6.5543e-05 9.363...e-06
|
||
org-agenda-add-time-grid-maybe 7 5.703...e-05 8.147...e-06
|
||
org-compile-prefix-format 1 5.2164e-05 5.2164e-05
|
||
org-link-unescape 4 4.4823e-05 1.120575e-05
|
||
listp 133 3.960...e-05 2.977...e-07
|
||
org-habit-duration-to-days 5 3.9446e-05 7.8892e-06
|
||
org-make-options-regexp 1 3.6054e-05 3.6054e-05
|
||
org-agenda-mark-header-line 1 3.3066e-05 3.3066e-05
|
||
org-element--collect-affiliated-keywords 4 3.2661e-05 8.16525e-06
|
||
org-habit-get-priority 5 2.9857e-05 5.9714e-06
|
||
org-agenda-get-category-icon 31 2.673...e-05 8.624...e-07
|
||
org-face-from-face-or-color 61 2.1803e-05 3.574...e-07
|
||
org-reduced-level 40 2.1692e-05 5.423e-07
|
||
org-link-get-parameter 26 2.062...e-05 7.930...e-07
|
||
buffer-name 57 1.9875e-05 3.486...e-07
|
||
org-defkey 5 1.9835e-05 3.966...e-06
|
||
string-to-char 56 1.929...e-05 3.446...e-07
|
||
org-string-nw-p 5 1.7894e-05 3.578...e-06
|
||
s-wrap 7 1.6955e-05 2.422...e-06
|
||
org-link-expand-abbrev 2 1.5491e-05 7.7455e-06
|
||
map-keymap 2 1.4987e-05 7.4935e-06
|
||
search-forward 7 1.403...e-05 2.004...e-06
|
||
string-lessp 41 1.394...e-05 3.400...e-07
|
||
org-agenda-reset-markers 1 1.3927e-05 1.3927e-05
|
||
org-agenda-deadline-face 7 1.2592e-05 1.798...e-06
|
||
search-backward 5 1.1253e-05 2.2506e-06
|
||
org-agenda-span-name 5 9.758e-06 1.9516e-06
|
||
outline-previous-heading 1 8.678e-06 8.678e-06
|
||
buffer-modified-p 10 4.618e-06 4.617...e-07
|
||
buffer-file-name 13 4.608...e-06 3.544...e-07
|
||
buffer-live-p 11 4.473e-06 4.066...e-07
|
||
buffer-local-value 10 4.278e-06 4.278...e-07
|
||
buffer-base-buffer 10 3.858e-06 3.858...e-07
|
||
org-agenda-set-mode-name 1 3.118e-06 3.118e-06
|
||
org-remove-flyspell-overlays-in 4 2.926...e-06 7.315...e-07
|
||
buffer-size 8 2.791...e-06 3.489...e-07
|
||
org-key 5 2.707e-06 5.414e-07
|
||
org-unbracket-string 1 2.692e-06 2.692e-06
|
||
save-place-to-alist 1 2.276e-06 2.276e-06
|
||
org-element--cache-put 4 1.907e-06 4.7675e-07
|
||
org-property-inherit-p 2 1.414e-06 7.07e-07
|
||
org-agenda-ndays-to-span 2 1.293...e-06 6.465...e-07
|
||
maphash 1 1.171e-06 1.171e-06
|
||
org-set-sorting-strategy 1 1.165e-06 1.165e-06
|
||
org-file-menu-entry 1 1.12e-06 1.12e-06
|
||
string-width 2 1.093e-06 5.465e-07
|
||
org-time-stamp-format 1 1.054e-06 1.054e-06
|
||
org-agenda-fit-window-to-buffer 1 9.31e-07 9.31e-07
|
||
org-font-lock-add-tag-faces 1 9.13e-07 9.13e-07
|
||
org-agenda-span-to-ndays 1 8.3e-07 8.3e-07
|
||
org-element-property 2 8.12e-07 4.06e-07
|
||
org-agenda-mark-clocking-task 1 8.03e-07 8.03e-07
|
||
org-tag-alist-to-groups 1 7.55e-07 7.55e-07
|
||
org-element-type 1 6.14e-07 6.14e-07
|
||
org-agenda-use-sticky-p 1 4.73e-07 4.73e-07
|
||
mapatoms 1 0 0.0
|
||
#+end_example
|
||
|
||
*** Profile org-element-map
|
||
|
||
#+BEGIN_SRC elisp
|
||
(elp-profile 1 (with-current-buffer (find-buffer-visiting "~/org/main.org")
|
||
(org-element-parse-buffer 'headline)))
|
||
#+END_SRC
|
||
|
||
#+RESULTS:
|
||
#+begin_example
|
||
org-element--parse-elements 1002 4.1612395469 0.0041529336
|
||
org-element-parse-buffer 1 0.859981956 0.859981956
|
||
org-element--current-element 1225 0.8236391779 0.0006723585
|
||
org-element-headline-parser 1225 0.7952382879 0.0006491741
|
||
org-end-of-subtree 1225 0.5557043549 0.0004536362
|
||
line-end-position 1995 0.0751104350 3.764...e-05
|
||
re-search-forward 3743 0.0516547359 1.380...e-05
|
||
org-outline-level 1225 0.0477962079 3.901...e-05
|
||
org-back-to-heading 1225 0.0469223529 3.830...e-05
|
||
outline-back-to-heading 1225 0.0450936199 3.681...e-05
|
||
org-element--get-node-properties 1225 0.0434517140 3.547...e-05
|
||
line-beginning-position 2003 0.0334129610 1.668...e-05
|
||
org-element--get-time-properties 1225 0.0306394040 2.501...e-05
|
||
org-get-limited-outline-regexp 2072 0.0140703559 6.790...e-06
|
||
org-element-timestamp-parser 249 0.0124751890 5.010...e-05
|
||
outline-next-heading 847 0.0115396399 1.362...e-05
|
||
org-at-heading-p 2227 0.0109473260 4.915...e-06
|
||
outline-on-heading-p 3452 0.0101107139 2.928...e-06
|
||
string-match 4594 0.0064121759 1.395...e-06
|
||
mapcar 30 0.0041008740 0.0001366958
|
||
#+end_example
|
||
|
||
** Profiling position-based
|
||
|
||
*** Macro
|
||
|
||
#+BEGIN_SRC elisp
|
||
(defmacro elp-profile (times &rest body)
|
||
(declare (indent defun))
|
||
`(let ((prefixes '("org-" "string-" "s-" "buffer-" "append" "delq" "map"
|
||
"list" "car" "save-" "outline-" "delete-dups"
|
||
"sort" "line-" "nth" "concat" "char-to-string"
|
||
"rx-" "goto-" "when" "search-" "re-"))
|
||
output)
|
||
(dolist (prefix prefixes)
|
||
(elp-instrument-package prefix))
|
||
(dotimes (x ,times)
|
||
,@body)
|
||
(elp-results)
|
||
(elp-restore-all)
|
||
(point-min)
|
||
(forward-line 20)
|
||
(delete-region (point) (point-max))
|
||
(setq output (buffer-substring-no-properties (point-min) (point-max)))
|
||
(kill-buffer)
|
||
(delete-window)
|
||
output))
|
||
#+END_SRC
|
||
|
||
|
||
*** orig
|
||
|
||
Make sure to kill any existing agenda buffers first.
|
||
|
||
#+BEGIN_SRC elisp
|
||
(elp-profile 1 (org-agenda-list nil nil 'week))
|
||
#+END_SRC
|
||
|
||
#+RESULTS:
|
||
#+begin_example
|
||
org-agenda-list 1 9.693596196 9.693596196
|
||
org-agenda-get-day-entries 56 8.630330659 0.1541130474
|
||
org-agenda-get-scheduled 56 6.6207980570 0.1182285367
|
||
org-is-habit-p 2792 2.2907458449 0.0008204677
|
||
org-entry-get 2798 2.287390186 0.0008175090
|
||
org-agenda--timestamp-to-absolute 7708 2.0970420100 0.0002720604
|
||
org-agenda-get-deadlines 56 1.6941886389 0.0302533685
|
||
org-at-planning-p 4399 1.3993312159 0.0003181021
|
||
org--property-local-values 2793 1.2699226760 0.0004546805
|
||
org-get-property-block 2794 1.2182695930 0.0004360306
|
||
org-time-string-to-absolute 7708 1.1513844880 0.0001493752
|
||
org-inlinetask-in-task-p 6969 1.139932302 0.0001635718
|
||
org-parse-time-string 7880 1.0635759220 0.0001349715
|
||
org-closest-date 3864 1.0383435800 0.0002687224
|
||
re-search-forward 15199 0.9607921779 6.321...e-05
|
||
org-back-to-heading 12667 0.8564486210 6.761...e-05
|
||
outline-back-to-heading 12667 0.8362207570 6.601...e-05
|
||
line-beginning-position 10333 0.7998346869 7.740...e-05
|
||
org-agenda-format-item 279 0.7552402350 0.0027069542
|
||
re-search-backward 16726 0.5694224969 3.404...e-05
|
||
#+end_example
|
||
|
||
*** ng-funcall
|
||
|
||
#+BEGIN_SRC elisp
|
||
(elp-profile 5 (org-agenda-ng--test-agenda-today))
|
||
#+END_SRC
|
||
|
||
#+RESULTS:
|
||
#+begin_example
|
||
mapcar 121 0.1296645480 0.0010716078
|
||
org-agenda-ng--test-agenda-today 5 0.086714029 0.0173428058
|
||
org-agenda-ng--agenda 5 0.086584611 0.0173169222
|
||
org-agenda-ng--format-element 75 0.0307461019 0.0004099480
|
||
org-agenda-ng--filter-buffer 5 0.027136826 0.0054273652
|
||
org-agenda-ng--date-p 455 0.0213037090 4.682...e-05
|
||
org-element-headline-parser 75 0.016251755 0.0002166900
|
||
org-get-tags-at 75 0.008959605 0.0001194614
|
||
org-agenda-ng--add-faces 75 0.0072381410 9.650...e-05
|
||
org-element-timestamp-interpreter 150 0.0069832960 4.655...e-05
|
||
org-entry-get 290 0.0061220340 2.111...e-05
|
||
org-up-heading-safe 210 0.0057036860 2.716...e-05
|
||
org-agenda-finalize-entries 5 0.005372899 0.0010745798
|
||
org-element-timestamp-parser 150 0.0050518689 3.367...e-05
|
||
org-entry-properties 290 0.0049517209 1.707...e-05
|
||
org-agenda-ng--add-deadline-face 75 0.0039273909 5.236...e-05
|
||
org-element--get-time-properties 75 0.0039059429 5.207...e-05
|
||
org-back-to-heading 725 0.0037793259 5.212...e-06
|
||
org-parse-time-string 300 0.0032196259 1.073...e-05
|
||
org-agenda-ng--add-scheduled-face 75 0.0031410580 4.188...e-05
|
||
#+end_example
|
||
|
||
*** ng-flet
|
||
|
||
#+BEGIN_SRC elisp
|
||
(elp-profile 5 (org-agenda-ng--test-agenda-today))
|
||
#+END_SRC
|
||
|
||
#+RESULTS:
|
||
#+begin_example
|
||
mapcar 121 0.1292609089 0.0010682719
|
||
org-agenda-ng--test-agenda-today 5 0.0860146149 0.017202923
|
||
org-agenda-ng--agenda 5 0.0858901769 0.0171780353
|
||
org-agenda-ng--format-element 75 0.0308815090 0.0004117534
|
||
org-agenda-ng--filter-buffer 5 0.026709027 0.0053418054
|
||
org-agenda-ng--date-p 455 0.0210552310 4.627...e-05
|
||
org-element-headline-parser 75 0.016209908 0.0002161321
|
||
org-get-tags-at 75 0.008953666 0.0001193822
|
||
org-agenda-ng--add-faces 75 0.0072834109 9.711...e-05
|
||
org-element-timestamp-interpreter 150 0.0068781430 4.585...e-05
|
||
org-entry-get 290 0.0060815609 2.097...e-05
|
||
org-up-heading-safe 210 0.005708647 2.718...e-05
|
||
org-agenda-finalize-entries 5 0.005201221 0.0010402442
|
||
org-element-timestamp-parser 150 0.005191617 3.461078e-05
|
||
org-entry-properties 290 0.0048787450 1.682...e-05
|
||
org-element--get-time-properties 75 0.004112675 5.483...e-05
|
||
org-agenda-ng--add-deadline-face 75 0.0039314910 5.241...e-05
|
||
org-back-to-heading 725 0.0037559990 5.180...e-06
|
||
org-agenda-ng--add-scheduled-face 75 0.0031766149 4.235...e-05
|
||
org-parse-time-string 300 0.0031740200 1.058...e-05
|
||
#+end_example
|
||
|
||
** Profiling =org-trust-scanner-tags=
|
||
|
||
[2018-05-10 Thu 12:59] Turned on =org-trust-scanner-tags=, going to try profiling again:
|
||
|
||
#+BEGIN_SRC elisp
|
||
;; (elp-profile 1 nil (org-agenda-ng "~/src/emacs/org-super-agenda/test/test.org"
|
||
;; (tags "world")))
|
||
|
||
(elp-profile 10 nil (org-agenda-ng org-agenda-files
|
||
(tags "Emacs")))
|
||
#+END_SRC
|
||
|
||
#+RESULTS:
|
||
| Function | Times called | Total time | Average time |
|
||
|-------------------------------------------+--------------+--------------+--------------|
|
||
| org-agenda-ng--agenda | 10 | 44.092598282 | 4.4092598282 |
|
||
| mapcar | 282 | 40.234516707 | 0.1426755911 |
|
||
| org-agenda-ng--filter-buffer | 80 | 26.895492471 | 0.3361936558 |
|
||
| org-element-headline-parser | 3980 | 10.387614362 | 0.0026099533 |
|
||
| org-agenda-finalize-entries | 10 | 9.194458252 | 0.9194458252 |
|
||
| org-agenda-ng--tags-p | 70250 | 8.1897379849 | 0.0001165799 |
|
||
| org-agenda-ng--format-element | 3980 | 6.5944325679 | 0.0016568926 |
|
||
| outline-next-heading | 70320 | 6.1190180490 | 8.701...e-05 |
|
||
| re-search-forward | 97050 | 5.8706467829 | 6.049...e-05 |
|
||
| org-get-tags-at | 74230 | 5.4078158059 | 7.285...e-05 |
|
||
| org-super-agenda--filter-finalize-entries | 10 | 5.2320123400 | 0.5232012340 |
|
||
| org-super-agenda--group-items | 10 | 5.1260959210 | 0.5126095921 |
|
||
| org-super-agenda--group-dispatch | 130 | 5.119333624 | 0.0393794894 |
|
||
| sort | 20 | 3.8204368569 | 0.1910218428 |
|
||
| org-element--parse-objects | 6180 | 3.5386578929 | 0.0005725983 |
|
||
| org-is-habit-p | 5970 | 3.2497755920 | 0.0005443510 |
|
||
| org-entry-get | 5970 | 3.2347964049 | 0.0005418419 |
|
||
| org--property-local-values | 5970 | 3.1796357319 | 0.0005326023 |
|
||
| org-get-property-block | 5970 | 3.0767919680 | 0.0005153755 |
|
||
| org-entries-lessp | 20020 | 2.6563960079 | 0.0001326871 |
|
||
|
||
Now trying again without it:
|
||
|
||
#+BEGIN_SRC elisp
|
||
;; (elp-profile 1 nil (org-agenda-ng "~/src/emacs/org-super-agenda/test/test.org"
|
||
;; (tags "world")))
|
||
|
||
(elp-profile 10 nil (org-agenda-ng org-agenda-files
|
||
(tags "Emacs")))
|
||
#+END_SRC
|
||
|
||
#+RESULTS:
|
||
| Function | Times called | Total time | Average time |
|
||
|-------------------------------------------+--------------+--------------+--------------|
|
||
| mapcar | 1791 | 57.096304538 | 0.0318795670 |
|
||
| org-agenda-ng--agenda | 10 | 54.232133506 | 5.4232133505 |
|
||
| org-agenda-ng--filter-buffer | 80 | 30.065167040 | 0.3758145880 |
|
||
| org-get-tags-at | 74230 | 13.840202495 | 0.0001864502 |
|
||
| org-agenda-ng--format-element | 3980 | 13.429297797 | 0.0033741954 |
|
||
| org-element-headline-parser | 3980 | 12.771776652 | 0.0032089891 |
|
||
| org-agenda-finalize-entries | 10 | 9.1439433990 | 0.9143943399 |
|
||
| org-agenda-ng--tags-p | 70250 | 9.0249653730 | 0.0001284692 |
|
||
| org-super-agenda--filter-finalize-entries | 10 | 7.300515859 | 0.7300515859 |
|
||
| outline-next-heading | 70320 | 7.2384435649 | 0.0001029357 |
|
||
| org-super-agenda--group-items | 10 | 4.918585855 | 0.4918585855 |
|
||
| org-super-agenda--group-dispatch | 130 | 4.9125893509 | 0.0377891488 |
|
||
| re-search-forward | 101020 | 4.6294823850 | 4.582...e-05 |
|
||
| org-up-heading-safe | 7370 | 4.4629885620 | 0.0006055615 |
|
||
| org-is-habit-p | 5960 | 4.2772351910 | 0.0007176569 |
|
||
| org-entry-get | 5960 | 4.2595350800 | 0.0007146870 |
|
||
| org-super-agenda--group-tag | 50 | 3.8942044929 | 0.0778840898 |
|
||
| re-search-backward | 26150 | 3.3660083490 | 0.0001287192 |
|
||
| org--property-local-values | 5960 | 3.1793476329 | 0.0005334475 |
|
||
| org-get-property-block | 5960 | 3.0662425979 | 0.0005144702 |
|
||
|
||
Wow, using =org-trust-scanner-tags= saves a /lot/ of time.
|
||
|
||
** Profiling flet across all agenda files
|
||
|
||
*** Without flet
|
||
|
||
#+BEGIN_SRC elisp
|
||
(elp-profile 5 (org-agenda-ng--agenda
|
||
:files org-agenda-files
|
||
:pred (lambda ()
|
||
(and (org-agenda-ng--todo-p)
|
||
(or (org-agenda-ng--date-p :deadline '<= (org-today))
|
||
(org-agenda-ng--date-p :scheduled '<= (org-today)))
|
||
(not (apply #'org-agenda-ng--todo-p org-done-keywords-for-agenda))))))
|
||
#+END_SRC
|
||
|
||
#+RESULTS:
|
||
#+begin_example
|
||
mapcar 711 26.910164986 0.0378483333
|
||
org-agenda-ng--agenda 5 21.012501837 4.2025003674
|
||
org-agenda-ng--filter-buffer 40 13.751964650 0.3437991162
|
||
org-agenda-ng--todo-p 37080 5.8788306440 0.0001585445
|
||
org-agenda-ng--format-element 1180 4.5712275970 0.0038739216
|
||
org-get-todo-state 37080 4.1661659069 0.0001123561
|
||
org-agenda-ng--date-p 21595 4.1442710769 0.0001919088
|
||
org-entry-get 22730 2.8275069239 0.0001243953
|
||
org-entry-properties 21595 2.6558403739 0.0001229840
|
||
outline-next-heading 34625 2.0894695999 6.034...e-05
|
||
org-element-headline-parser 1180 1.9110445780 0.0016195293
|
||
re-search-forward 42280 1.6994989150 4.019...e-05
|
||
org-agenda-ng--add-faces 1180 1.6172592580 0.0013705586
|
||
org-agenda-ng--add-scheduled-face 1180 1.607386145 0.0013621916
|
||
org-get-tags-at 1180 1.1521010509 0.0009763568
|
||
org-back-to-heading 64530 1.1005834200 1.705...e-05
|
||
org-up-heading-safe 2360 1.0182265390 0.0004314519
|
||
outline-back-to-heading 64530 1.0086056729 1.563...e-05
|
||
org-parse-time-string 7560 0.8314918499 0.0001099856
|
||
org-time-string-to-absolute 3780 0.8277485280 0.0002189810
|
||
#+end_example
|
||
|
||
|
||
*** With flet
|
||
|
||
#+BEGIN_SRC elisp
|
||
(elp-profile 5 (org-agenda-ng--agenda
|
||
:files org-agenda-files
|
||
:pred (lambda ()
|
||
(and (todo)
|
||
(or (date :deadline '<= (org-today))
|
||
(date :scheduled '<= (org-today)))
|
||
(not (apply #'todo org-done-keywords-for-agenda))))))
|
||
#+END_SRC
|
||
|
||
#+RESULTS:
|
||
#+begin_example
|
||
mapcar 711 25.608392569 0.0360174297
|
||
org-agenda-ng--agenda 5 24.019318793 4.8038637586
|
||
org-agenda-ng--filter-buffer 40 14.160293256 0.3540073313
|
||
org-agenda-ng--date-p 21595 4.2111783960 0.0001950071
|
||
org-agenda-finalize-entries 5 4.0930243110 0.8186048622
|
||
org-super-agenda--filter-finalize-entries 5 3.937522006 0.7875044012
|
||
org-agenda-ng--todo-p 37080 3.5687476730 9.624...e-05
|
||
org-get-todo-state 37080 3.4737076600 9.368...e-05
|
||
outline-next-heading 34625 3.4689080650 0.0001001850
|
||
re-search-forward 42280 3.0743315830 7.271...e-05
|
||
org-agenda-ng--format-element 1180 2.9511605820 0.0025009835
|
||
org-element-headline-parser 1180 2.6757063699 0.0022675477
|
||
org-super-agenda--group-items 5 2.187362092 0.4374724183
|
||
org-super-agenda--group-dispatch 70 2.184685662 0.0312097951
|
||
org-entry-get 22730 2.0711872869 9.112...e-05
|
||
org-entry-properties 21595 1.8958912070 8.779...e-05
|
||
org-super-agenda--group-tag 25 1.8498977799 0.0739959111
|
||
org-element-timestamp-parser 3785 1.8234333229 0.0004817525
|
||
org-parse-time-string 7560 1.7121709579 0.0002264776
|
||
org-element--get-time-properties 1180 1.1814058020 0.0010011913
|
||
#+end_example
|
||
|
||
** Profiling flet on a single file
|
||
|
||
This shows that the difference between them, if any, is so small as to be irrelevant. The convenience and clarity are a big win.
|
||
|
||
*** Without flet
|
||
|
||
#+BEGIN_SRC elisp
|
||
(elp-profile 5 (org-agenda-ng--agenda
|
||
:files "~/org/main.org"
|
||
:pred (lambda ()
|
||
(and (org-agenda-ng--todo-p)
|
||
(or (org-agenda-ng--date-p :deadline '<= (org-today))
|
||
(org-agenda-ng--date-p :scheduled '<= (org-today)))
|
||
(not (apply #'org-agenda-ng--todo-p org-done-keywords-for-agenda))))))
|
||
#+END_SRC
|
||
|
||
#+RESULTS:
|
||
#+begin_example
|
||
mapcar 526 3.7766218089 0.0071798893
|
||
org-agenda-ng--agenda 5 2.75718831 0.551437662
|
||
org-agenda-ng--filter-buffer 5 1.402551392 0.2805102784
|
||
org-agenda-ng--format-element 265 0.8864161399 0.0033449665
|
||
org-get-tags-at 265 0.7896260759 0.0029797210
|
||
org-up-heading-safe 1150 0.7589292910 0.0006599385
|
||
re-search-backward 3700 0.5956338739 0.0001609821
|
||
org-agenda-ng--todo-p 6690 0.5781650060 8.642...e-05
|
||
org-get-todo-state 6690 0.5603983020 8.376...e-05
|
||
org-agenda-ng--date-p 5940 0.5209897369 8.770...e-05
|
||
org-entry-get 6195 0.4158440950 6.712...e-05
|
||
org-entry-properties 5940 0.3640524090 6.128...e-05
|
||
org-element-headline-parser 265 0.2810144710 0.0010604319
|
||
outline-next-heading 6195 0.2485497380 4.012...e-05
|
||
org-back-to-heading 14565 0.1957209180 1.343...e-05
|
||
re-search-forward 7850 0.1927130979 2.454...e-05
|
||
outline-back-to-heading 14565 0.1751091780 1.202...e-05
|
||
org-outline-level 2300 0.1680958539 7.308...e-05
|
||
org-agenda-finalize-entries 5 0.1610422239 0.0322084448
|
||
org-super-agenda--filter-finalize-entries 5 0.132423043 0.0264846085
|
||
#+end_example
|
||
|
||
|
||
*** With flet
|
||
|
||
#+BEGIN_SRC elisp
|
||
(elp-profile 5 (org-agenda-ng--agenda
|
||
:files "~/org/main.org"
|
||
:pred (lambda ()
|
||
(and (todo)
|
||
(or (date :deadline '<= (org-today))
|
||
(date :scheduled '<= (org-today)))
|
||
(not (apply #'todo org-done-keywords-for-agenda))))))
|
||
#+END_SRC
|
||
|
||
#+RESULTS:
|
||
#+begin_example
|
||
mapcar 526 3.7898506779 0.0072050393
|
||
org-agenda-ng--agenda 5 2.7695176850 0.5539035370
|
||
org-agenda-ng--filter-buffer 5 1.414347774 0.2828695548
|
||
org-agenda-ng--format-element 265 0.8871611419 0.0033477778
|
||
org-get-tags-at 265 0.7891641319 0.0029779778
|
||
org-up-heading-safe 1150 0.7581951110 0.0006593000
|
||
re-search-backward 3700 0.5948686769 0.0001607753
|
||
org-agenda-ng--todo-p 6690 0.5840980579 8.730...e-05
|
||
org-get-todo-state 6690 0.5666448919 8.470...e-05
|
||
org-agenda-ng--date-p 5940 0.5196037069 8.747...e-05
|
||
org-entry-get 6195 0.4144106150 6.689...e-05
|
||
org-entry-properties 5940 0.3640680380 6.129...e-05
|
||
org-element-headline-parser 265 0.2810144920 0.0010604320
|
||
outline-next-heading 6195 0.2495287770 4.027...e-05
|
||
org-back-to-heading 14565 0.1959557380 1.345...e-05
|
||
re-search-forward 7850 0.1933439489 2.462...e-05
|
||
outline-back-to-heading 14565 0.1753121230 1.203...e-05
|
||
org-outline-level 2300 0.1676228200 7.287...e-05
|
||
org-agenda-finalize-entries 5 0.1607656930 0.0321531386
|
||
org-super-agenda--filter-finalize-entries 5 0.1316961509 0.0263392301
|
||
#+end_example
|
||
|
||
** Profiling tags matching
|
||
|
||
*** ng
|
||
|
||
#+BEGIN_SRC elisp
|
||
(elp-profile 1 nil
|
||
(org-agenda-ng "~/org/main.org"
|
||
(tags "computer")))
|
||
#+END_SRC
|
||
|
||
#+RESULTS:
|
||
| Function | Times called | Total time | Average time |
|
||
|--------------------------------+--------------+--------------+--------------|
|
||
| mapcar | 4217 | 12.612716455 | 0.0029909216 |
|
||
| org-agenda-ng--agenda | 1 | 9.721410651 | 9.721410651 |
|
||
| org-get-tags-at | 1845 | 7.4793860389 | 0.0040538677 |
|
||
| org-up-heading-safe | 9361 | 6.4622674019 | 0.0006903394 |
|
||
| re-search-backward | 25001 | 5.3399866239 | 0.0002135909 |
|
||
| org-agenda-ng--filter-buffer | 1 | 4.874598854 | 4.874598854 |
|
||
| org-agenda-ng--tags-p | 1238 | 4.8067623430 | 0.0038826836 |
|
||
| org-agenda-ng--format-element | 607 | 3.6325626609 | 0.0059844524 |
|
||
| org-outline-level | 17484 | 1.0298924459 | 5.890...e-05 |
|
||
| org-add-props | 2074 | 0.8305549259 | 0.0004004604 |
|
||
| org-element-headline-parser | 607 | 0.2092664829 | 0.0003447553 |
|
||
| org-back-to-heading | 11813 | 0.1252112960 | 1.059...e-05 |
|
||
| outline-back-to-heading | 11813 | 0.1100693780 | 9.317...e-06 |
|
||
| org-end-of-subtree | 607 | 0.0721986340 | 0.0001189433 |
|
||
| outline-on-heading-p | 11813 | 0.0675261030 | 5.716...e-06 |
|
||
| outline-next-heading | 1239 | 0.0627980999 | 5.068...e-05 |
|
||
| re-search-forward | 3273 | 0.0612446620 | 1.871...e-05 |
|
||
| org-agenda-finalize-entries | 1 | 0.041846274 | 0.041846274 |
|
||
| buffer-substring-no-properties | 6329 | 0.0308716979 | 4.877...e-06 |
|
||
| line-end-position | 903 | 0.0280484950 | 3.106...e-05 |
|
||
|
||
*** ng without inheritance
|
||
|
||
#+BEGIN_SRC elisp
|
||
(elp-profile 1 nil
|
||
(org-agenda-ng "~/org/main.org"
|
||
(tags "computer")))
|
||
#+END_SRC
|
||
|
||
#+RESULTS:
|
||
| Function | Times called | Total time | Average time |
|
||
|--------------------------------+--------------+--------------+--------------|
|
||
| mapcar | 4217 | 12.580246839 | 0.0029832219 |
|
||
| org-agenda-ng--agenda | 1 | 8.777776059 | 8.777776059 |
|
||
| org-get-tags-at | 1845 | 8.2853503299 | 0.0044907047 |
|
||
| org-up-heading-safe | 9361 | 7.2710981889 | 0.0007767437 |
|
||
| re-search-backward | 25001 | 5.3360082060 | 0.0002134317 |
|
||
| org-agenda-ng--filter-buffer | 1 | 4.865602689 | 4.865602689 |
|
||
| org-agenda-ng--tags-p | 1238 | 4.7983754310 | 0.0038759090 |
|
||
| org-agenda-ng--format-element | 607 | 3.6273825100 | 0.0059759184 |
|
||
| org-outline-level | 17484 | 1.0284417919 | 5.882...e-05 |
|
||
| org-back-to-heading | 11813 | 0.9390534479 | 7.949...e-05 |
|
||
| org-split-string | 4940 | 0.833825087 | 0.0001687905 |
|
||
| string-match | 9102 | 0.8231629100 | 9.043...e-05 |
|
||
| org-element-headline-parser | 607 | 0.2034305819 | 0.0003351409 |
|
||
| outline-back-to-heading | 11813 | 0.1096120189 | 9.278...e-06 |
|
||
| org-end-of-subtree | 607 | 0.0710802559 | 0.0001171009 |
|
||
| outline-on-heading-p | 11813 | 0.0670029359 | 5.671...e-06 |
|
||
| outline-next-heading | 1239 | 0.0622323519 | 5.022...e-05 |
|
||
| re-search-forward | 3273 | 0.0603102519 | 1.842...e-05 |
|
||
| org-agenda-finalize-entries | 1 | 0.037286496 | 0.037286496 |
|
||
| buffer-substring-no-properties | 6329 | 0.0285818689 | 4.516...e-06 |
|
||
|
||
|
||
*** original
|
||
|
||
#+BEGIN_SRC elisp
|
||
(elp-profile 1 nil
|
||
(with-current-buffer "main.org"
|
||
(org-tags-view nil "computer")))
|
||
#+END_SRC
|
||
|
||
#+RESULTS:
|
||
| Function | Times called | Total time | Average time |
|
||
|-----------------------------+--------------+--------------+--------------|
|
||
| org-tags-view | 1 | 2.620578129 | 2.620578129 |
|
||
| org-scan-tags | 1 | 1.448883817 | 1.448883817 |
|
||
| org-agenda-format-item | 607 | 0.9273893060 | 0.0015278242 |
|
||
| org-add-props | 2042 | 0.8877267209 | 0.0004347339 |
|
||
| org-agenda-finalize | 1 | 0.144506782 | 0.144506782 |
|
||
| re-search-forward | 2154 | 0.1367046650 | 6.346...e-05 |
|
||
| string-match | 8742 | 0.1002517259 | 1.146...e-05 |
|
||
| org-get-priority | 607 | 0.0961996220 | 0.0001584837 |
|
||
| org-agenda-align-tags | 1 | 0.095166495 | 0.095166495 |
|
||
| org-agenda-prepare | 1 | 0.081724472 | 0.081724472 |
|
||
| org-outline-level | 1246 | 0.0771033170 | 6.188...e-05 |
|
||
| org-agenda-finalize-entries | 1 | 0.071707404 | 0.071707404 |
|
||
| org-agenda-prepare-buffers | 1 | 0.057903921 | 0.057903921 |
|
||
| org-get-heading | 607 | 0.0517784369 | 8.530...e-05 |
|
||
| mapcar | 3738 | 0.0418641110 | 1.119...e-05 |
|
||
| org-agenda-highlight-todo | 607 | 0.0273123070 | 4.499...e-05 |
|
||
| mapconcat | 609 | 0.024743305 | 4.062...e-05 |
|
||
| sort | 2 | 0.02117069 | 0.010585345 |
|
||
| org-activate-plain-links | 132 | 0.0203558980 | 0.0001542113 |
|
||
| org-activate-bracket-links | 78 | 0.0198589680 | 0.0002546021 |
|
||
|
||
** More profiling
|
||
|
||
[2018-05-10 Thu 15:02] I think these are decent improvements.
|
||
|
||
#+BEGIN_SRC elisp
|
||
(elp-profile 1 nil (org-agenda-ng "~/org/main.org"
|
||
(or (habit)
|
||
(and (or (date '= (org-today))
|
||
(deadline '<=)
|
||
(scheduled '<= (org-today)))
|
||
(not (apply #'todo org-done-keywords-for-agenda)))
|
||
(and (todo "DONE" "CANCELLED")
|
||
(closed '= (org-today))))))
|
||
#+END_SRC
|
||
|
||
#+RESULTS:
|
||
| Function | Times called | Total time | Average time |
|
||
|-------------------------------+--------------+--------------+--------------|
|
||
| mapcar | 164 | 1.5004585290 | 0.0091491373 |
|
||
| org-agenda-ng--agenda | 1 | 1.348231247 | 1.348231247 |
|
||
| org-agenda-ng--filter-buffer | 1 | 1.1391189879 | 1.1391189879 |
|
||
| org-agenda-ng--date-plain-p | 1267 | 0.6198571040 | 0.0004892321 |
|
||
| org-entry-get | 3983 | 0.2979337370 | 7.480...e-05 |
|
||
| org-is-habit-p | 1365 | 0.2049101109 | 0.0001501172 |
|
||
| org--property-local-values | 1365 | 0.1940614150 | 0.0001421695 |
|
||
| org-agenda-ng--habit-p | 1272 | 0.1911009179 | 0.0001502365 |
|
||
| org-agenda-ng--format-element | 52 | 0.177965411 | 0.0034224117 |
|
||
| org-get-property-block | 1365 | 0.1760004519 | 0.0001289380 |
|
||
| org-get-tags-at | 52 | 0.1362824969 | 0.0026208172 |
|
||
| org-agenda-ng--date-p | 3880 | 0.1351176629 | 3.482...e-05 |
|
||
| org-up-heading-safe | 226 | 0.1276747609 | 0.0005649325 |
|
||
| re-search-backward | 2028 | 0.1144211070 | 5.642...e-05 |
|
||
| org-entry-properties | 2618 | 0.0848660999 | 3.241...e-05 |
|
||
| org-agenda-ng--todo-p | 1319 | 0.081952653 | 6.213...e-05 |
|
||
| org-get-todo-state | 1319 | 0.0796836810 | 6.041...e-05 |
|
||
| re-search-forward | 3754 | 0.0739803739 | 1.970...e-05 |
|
||
| org-inlinetask-in-task-p | 1365 | 0.0657829330 | 4.819...e-05 |
|
||
| org-agenda-ng--scheduled-p | 1247 | 0.0619497850 | 4.967...e-05 |
|
||
|
||
** Intersecting query results
|
||
|
||
An idea that /might/ be helpful for performance in /some/ cases, depending on the query, the data, and whether the query has a preamble. But it looks like it would very rarely be helpful.
|
||
|
||
#+BEGIN_SRC elisp
|
||
(cl-defun org-ql-agenda-intersection (buffers-files queries &key entries sort buffer narrow super-groups)
|
||
"Like `org-ql-agenda', but intersects multiple queries."
|
||
(declare (indent defun))
|
||
(let* ((entries (->> queries
|
||
(--map (org-ql-select buffers-files
|
||
it
|
||
:action 'element-with-markers
|
||
:narrow narrow
|
||
:sort sort))
|
||
(-reduce #'-intersection))))
|
||
(org-ql-agenda--agenda buffers-files queries
|
||
:entries entries :super-groups super-groups)))
|
||
|
||
(bench-multi-lexical :times 1
|
||
:forms (("intersection" (let ((org-use-tag-inheritance nil))
|
||
(org-ql-agenda-intersection (org-agenda-files)
|
||
'((todo "TODO")
|
||
(tags "Emacs"))
|
||
:sort '(priority deadline)
|
||
:super-groups org-super-agenda-groups)))
|
||
("normal" (let ((org-use-tag-inheritance nil))
|
||
(org-ql-agenda (org-agenda-files)
|
||
(and (todo "TODO")
|
||
(tags "Emacs"))
|
||
:sort (priority deadline)
|
||
:super-groups org-super-agenda-groups)))))
|
||
#+END_SRC
|
||
|
||
#+RESULTS:
|
||
| Form | x faster than next | Total runtime | # of GCs | Total GC runtime |
|
||
|--------------+--------------------+---------------+----------+------------------|
|
||
| normal | 4.03 | 0.275053 | 0 | 0 |
|
||
| intersection | slowest | 1.109169 | 0 | 0 |
|