Beschleunigen Sie Org-Map-Einträge beim Abgleich nach Eigenschaften

8

Frage : Warum ist der org-map-entriesImmobilienabgleich so langsam und was kann ich tun, um ihn zu beschleunigen?

Hintergrund : Ich habe eine relativ einfache Verwendung für org-map-entries: Ergreifen Sie den Aufwand (in ganzzahligen Minuten) aus allen Einträgen der Organisationsagenda mit einem Tag goalund einer bestimmten Priorität (z B. B. ).

(org-map-entries #'hw-org-get-effort-in-minutes "goal+PRIORITY=\"B\"" 'agenda)

Dies ist furchtbar langsam und dauert über eine Minute für meine Agenda-Datei mit ~ 12.000 Zeilen.

Wenn ich das jedoch PRIORITYaus dem Filter entferne , damit ein goalsmarkiertes Element ausgewählt wird, wird es fast sofort abgeschlossen.

Ich kann auch Filter wie einstellen goal/DONEund sie werden sehr schnell abgeschlossen, aber wenn ich so etwas mache, nehmen goals+EFFORT>0wir wieder mehr als eine Minute Zeit. Es scheint, dass Eigenschaften im Allgemeinen sehr langsam übereinstimmen.

Ich habe eine Cheat-Problemumgehung gefunden : Ich kann Eigenschaften innerhalb der zugeordneten Funktion sehr schnell mit abgleichen org-entry-get. Wenn ich das mache, dauert die Ausführung weniger als eine Sekunde. Das scheint albern, hoffentlich gibt es einen besseren Weg, aber zumindest funktioniert es!

Bereits ausprobiert : Seit der (benchmark 1000 (hw-org-effort-to-minutes "1:20"))Rückkehr "Elapsed time: 0.000019s"glaube ich nicht, dass meine Funktion viel dazu beiträgt.

Entsprechend profilerwerden ~ 40% der CPU-Zeit von verwendet cond, wobei ~ 29% aus der Elementanalyse ( org-element--current-element) stammen. Die nächsten beiden größten Beiträge sind insgesamt 14% und 13%, so dass die 40% condden größten Teil des Problems ausmachen. Ich bin mir nicht sicher, warum das Parsen von Elementen mit Eigenschafts-Matchern häufiger durchgeführt wird, es sei denn, der Unterschied besteht darin, dass nur Header (Tags, TODO) und Header + Body (Eigenschaften) analysiert werden.

Holocronweber
quelle

Antworten:

2

Eine Möglichkeit, die Geschwindigkeit zu verbessern, besteht darin, den Inhalt Ihrer Agenda-Dateien einmal in einem temporären Puffer zu analysieren, um den Aufwand aller übereinstimmenden Einträge zu erfassen goal+PRIORITY="B"(siehe Test 1). Mit ~ 10K-Zeilen erhalte ich "Verstrichene Zeit: 0,052280s" im Vergleich zu "Verstrichene Zeit: 1,340006s" mit org-map-entries(Test 2), was meiner Meinung nach das ist, was Sie versucht haben. Für bessere Ergebnisse können org-map-entriesSie Test 3 ausprobieren, der auch ziemlich schnell ist. Getestet mit Emacs Version 26.2 und Org Mode Version 9.2.4.

Test 1 (am schnellsten)

(org-duration-from-minutes
 (apply '+ (let (efforts
                 (regexp (concat org-effort-property ":\s*\\(.+\\)")))
             (with-temp-buffer
               (mapcar #'insert-file-contents org-agenda-files)
               (goto-char (point-min))
               (while (re-search-forward regexp nil t)
                 (let ((effort (match-string 1)))
                   (save-excursion
                     (outline-previous-heading)
                     (when (and (member "goal" (org-get-tags))
                                (= (and (looking-at org-heading-regexp)
                                        (org-get-priority (match-string 0)))
                                1000))
                    (push (org-duration-to-minutes effort) efforts))))))
          efforts)))

Test 2 (am langsamsten)

(org-duration-from-minutes
 (apply '+ (org-map-entries
            (lambda ()
              (org-duration-to-minutes
               (org-entry-get nil org-effort-property)))
            "goal+PRIORITY=\"B\""
            'agenda)))

Test 3 (ziemlich gut)

(org-duration-from-minutes
 (apply '+ (org-map-entries
            (lambda ()
              (if (re-search-forward (concat org-effort-property ":\s*\\(.+\\)")
                                     (save-excursion
                                       (org-end-of-meta-data)
                                       (point))
                                     t)
                  (let ((effort (match-string 1)))
                    (outline-previous-heading)
                    (when (looking-at org-complex-heading-regexp)
                      (let ((priority (match-string 3))
                            (tags (match-string 5)))
                        (if (and (string= priority "[#B]")
                                 (string-match ":goal:" tags))
                            (org-duration-to-minutes effort)
                          0))))
                0))
            nil 'agenda)))
jagrg
quelle