Accelera le voci della mappa dell'org durante la corrispondenza per proprietà


8

Domanda : Perché la org-map-entriescorrispondenza delle proprietà è così lenta e cosa posso fare per accelerarla?

Background : ho un uso relativamente semplice per org-map-entries: afferrare lo sforzo (in minuti interi) da tutte le voci dell'agenda dell'organizzazione con tag goale una data priorità (ad es B.).

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

Questo è terribilmente lento, impiegando più di un minuto per il mio file dell'agenda della linea ~ 12k.

Tuttavia, se rimuovo il PRIORITYfiltro dal filtro in modo che qualsiasi goalselemento taggato sia selezionato, si completa quasi istantaneamente.

Posso anche impostare filtri come goal/DONEe si completano molto rapidamente, ma se faccio qualcosa del genere goals+EFFORT>0, torniamo a prendere più di un minuto. Sembra che le proprietà in generale siano molto lente da abbinare.

Ho trovato una soluzione cheat : posso abbinare le proprietà all'interno della funzione mappata molto rapidamente usando org-entry-get. Quando lo faccio, l'esecuzione è meno di un secondo. Sembra sciocco, speriamo che ci sia un modo migliore, ma almeno funziona!

Già provato : dai (benchmark 1000 (hw-org-effort-to-minutes "1:20"))ritorni "Elapsed time: 0.000019s", non credo che la mia funzione contribuisca molto.

Secondo profiler, viene utilizzato ~ 40% del tempo CPU cond, con ~ 29% proveniente dall'analisi dell'elemento ( org-element--current-element). I prossimi due maggiori contributi complessivi sono il 14% e il 13%, quindi il 40% condsembra essere la maggior parte del problema. Non sono sicuro del motivo per cui l'analisi dell'elemento verrebbe eseguita più spesso con gli abbinamenti delle proprietà, a meno che la differenza non derivi dall'analisi solo dell'intestazione (tag, TODO) rispetto all'intestazione + corpo (proprietà).

Risposte:


2

Un modo per migliorare la velocità è analizzare il contenuto dei file dell'agenda una volta in un buffer temporaneo, raccogliendo lo sforzo di tutte le voci corrispondenti goal+PRIORITY="B"(vedere Test 1). Con ~ 10K righe, ottengo "Tempo trascorso: 0,052280 s" rispetto a "Tempo trascorso: 1,340006 s" usando org-map-entries(Test 2) che penso sia quello che stavi cercando di fare. Per risultati migliori usando org-map-entriespuoi provare Test 3, che è anche abbastanza veloce. Testato con Emacs versione 26.2 e modalità Org versione 9.2.4.

Test 1 (il più veloce)

(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 (il più lento)

(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 (abbastanza buono)

(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)))
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.