Mempercepat entri-peta-org ketika dicocokkan dengan properti

8

Pertanyaan : Mengapa org-map-entriespencocokan properti sangat lambat, dan apa yang bisa saya lakukan untuk mempercepatnya?

Latar belakang : Saya memiliki penggunaan yang relatif sederhana untuk org-map-entries: ambil upaya (dalam menit integer) dari semua entri agenda org dengan tag goaldan prioritas yang diberikan (misalnya B).

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

Ini sangat lambat, mengambil lebih dari satu menit untuk file agenda baris ~ 12k saya.

Namun, jika saya menghapus PRIORITYdari filter sehingga setiap goalsitem yang ditandai dipilih, itu menyelesaikan hampir secara instan.

Saya juga dapat mengatur filter seperti goal/DONEdan mereka selesai dengan sangat cepat, tetapi jika saya melakukan sesuatu seperti goals+EFFORT>0kita kembali mengambil alih satu menit. Tampaknya properti pada umumnya sangat lambat untuk dicocokkan.

Saya menemukan solusi curang : Saya dapat mencocokkan properti di dalam fungsi yang dipetakan dengan sangat cepat org-entry-get. Ketika saya melakukan ini, eksekusi kurang dari satu detik. Ini kelihatannya konyol, semoga ada cara yang lebih baik, tapi setidaknya berhasil!

Sudah mencoba : Sejak (benchmark 1000 (hw-org-effort-to-minutes "1:20"))kembali "Elapsed time: 0.000019s", saya tidak berpikir fungsi saya berkontribusi banyak.

Menurut profiler, ~ 40% dari waktu CPU digunakan oleh cond, dengan ~ 29% berasal dari elemen parsing ( org-element--current-element). Dua kontribusi terbesar berikutnya secara keseluruhan adalah 14% dan 13%, sehingga 40% dari condtampaknya menjadi bagian terbesar dari masalah. Tidak yakin mengapa elemen parsing akan dilakukan lebih sering dengan pencocokan properti, kecuali perbedaannya berasal dari parsing hanya header (tag, TODO) vs header + tubuh (properti).

holocronweaver
sumber

Jawaban:

2

Salah satu cara untuk meningkatkan kecepatan adalah mem-parsing isi file agenda Anda sekali dalam buffer sementara mengumpulkan upaya semua entri yang cocok goal+PRIORITY="B"(lihat Tes 1). Dengan ~ 10K baris, saya mendapatkan "Waktu berlalu: 0,052280" dibandingkan dengan "Waktu berlalu: 1,340006" menggunakan org-map-entries(Uji 2) yang saya pikir adalah apa yang Anda coba lakukan. Untuk hasil yang lebih baik menggunakan org-map-entriesAnda dapat mencoba Tes 3, yang juga cukup cepat. Diuji dengan Emacs versi 26.2 dan Org mode versi 9.2.4.

Tes 1 (tercepat)

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

Tes 2 (paling lambat)

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

Tes 3 (cukup bagus)

(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
sumber