Accélérez les entrées de la carte d'organisation lors de la correspondance par propriété

8

Question : Pourquoi la org-map-entriescorrespondance des propriétés est-elle si lente et que puis-je faire pour l'accélérer?

Contexte : J'ai une utilisation relativement simple pour org-map-entries: saisir l'effort (en minutes entières) de toutes les entrées d'agenda de l'organisation avec une balise goalet une priorité donnée (par exemple B).

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

C'est terriblement lent, prenant plus d'une minute pour mon fichier d'agenda de ~ 12k lignes.

Cependant, si je supprime le PRIORITYfiltre pour que tout goalsélément balisé soit sélectionné, il se termine presque instantanément.

Je peux également définir des filtres comme goal/DONEet ils se terminent très rapidement, mais si je fais quelque chose comme ça, goals+EFFORT>0nous reprenons une minute. Il semble que les propriétés en général soient très lentes à correspondre.

J'ai trouvé une solution de contournement : je peux faire correspondre très rapidement les propriétés à l'intérieur de la fonction mappée org-entry-get. Lorsque je fais cela, l'exécution est inférieure à une seconde. Cela semble idiot, j'espère qu'il y a une meilleure façon, mais au moins ça marche!

Déjà essayé : depuis les (benchmark 1000 (hw-org-effort-to-minutes "1:20"))retours "Elapsed time: 0.000019s", je ne pense pas que ma fonction y contribue beaucoup.

Selon profiler, ~ 40% du temps CPU est utilisé par cond, dont ~ 29% provenant de l'analyse des éléments ( org-element--current-element). Les deux prochaines contributions les plus importantes sont de 14% et 13%, de sorte que les 40% condsemblent être le gros du problème. Vous ne savez pas pourquoi l'analyse des éléments se ferait plus souvent avec les comparateurs de propriétés, sauf si la différence vient de l'analyse de l'en-tête uniquement (balises, TODO) par rapport à l'en-tête + corps (propriétés).

holocronweaver
la source

Réponses:

2

Une façon d'améliorer la vitesse consiste à analyser le contenu de vos fichiers d'agenda une fois dans un tampon temporaire en collectant l'effort de toutes les entrées correspondantes goal+PRIORITY="B"(voir Test 1). Avec ~ 10K lignes, j'obtiens "Temps écoulé: 0,052280s" par rapport à "Temps écoulé: 1,340006s" en utilisant org-map-entries(Test 2) qui, je pense, est ce que vous essayez de faire. Pour de meilleurs résultats, org-map-entriesvous pouvez essayer le test 3, qui est également assez rapide. Testé avec Emacs version 26.2 et Org mode version 9.2.4.

Test 1 (le plus rapide)

(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 (le plus lent)

(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 (assez bon)

(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
la source