From mboxrd@z Thu Jan 1 00:00:00 1970 From: Adam Porter Subject: Re: Faster version of org-find-olp Date: Fri, 16 Aug 2019 19:10:50 -0500 Message-ID: <87wofcslbp.fsf@alphapapa.net> References: <871rxku0po.fsf@alphapapa.net> Mime-Version: 1.0 Content-Type: multipart/mixed; boundary="=-=-=" Return-path: Received: from eggs.gnu.org ([2001:470:142:3::10]:55548) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1hymJG-0002Hh-VN for emacs-orgmode@gnu.org; Fri, 16 Aug 2019 20:11:08 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1hymJF-00076u-Po for emacs-orgmode@gnu.org; Fri, 16 Aug 2019 20:11:06 -0400 Received: from 195-159-176-226.customer.powertech.no ([195.159.176.226]:56824 helo=blaine.gmane.org) by eggs.gnu.org with esmtps (TLS1.0:RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1hymJF-00076W-Ir for emacs-orgmode@gnu.org; Fri, 16 Aug 2019 20:11:05 -0400 Received: from list by blaine.gmane.org with local (Exim 4.89) (envelope-from ) id 1hymJA-000RFu-6Y for emacs-orgmode@gnu.org; Sat, 17 Aug 2019 02:11:00 +0200 List-Id: "General discussions about Org-mode." List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: emacs-orgmode-bounces+geo-emacs-orgmode=m.gmane.org@gnu.org Sender: "Emacs-orgmode" To: emacs-orgmode@gnu.org --=-=-= Content-Type: text/plain I see that using an "inline" attachment was a bad idea. At least, the lists.gnu.org Web UI wraps the lines. Here it is as an "attachment" attachment, in case that helps. --=-=-= Content-Type: text/x-org Content-Disposition: attachment; filename=delta-895b2.org Content-Description: Code and benchmark results #+BEGIN_SRC elisp :results silent (defun org-olp-marker (olp &optional this-buffer unique) "Return a marker pointing to outline path OLP. Return nil if not found. If THIS-BUFFER, search current buffer; otherwise search file found at path in first element of OLP. If UNIQUE, display a warning if OLP points to multiple headings." ;; NOTE: Disabling `case-fold-search' is important to avoid voluntary hair loss. (let* ((case-fold-search nil) (file (unless this-buffer (pop olp))) (buffer (if this-buffer (current-buffer) (or (find-file-noselect file) (error "File in outline path not found: %s" file))))) (cl-labels ((find-at (level headings) (let ((re (rx-to-string `(seq bol (repeat ,level "*") (1+ blank) (optional (1+ upper) (1+ blank)) ; To-do keyword (optional "[#" (in "ABC") "]" (1+ blank)) ; Priority ,(car headings) (0+ blank) (or eol ":"))))) (when (re-search-forward re nil t) (when (and unique (save-excursion (save-restriction (when (re-search-forward re nil t) (if (cdr headings) (find-at (1+ level) (cdr headings)) t))))) (display-warning 'org-recent-headings (format "Multiple headings found in %S for outline path: %S" (current-buffer) olp) :warning)) (if (cdr headings) (progn (org-narrow-to-subtree) (find-at (1+ level) (cdr headings))) (copy-marker (point-at-bol))))))) (with-current-buffer buffer (org-with-wide-buffer (goto-char (point-min)) (find-at 1 olp)))))) (defun org-olp-marker* (olp &optional this-buffer unique) ;; NOTE: This version uses `org-complex-heading-regexp-format'. "Return a marker pointing to outline path OLP. Return nil if not found. If THIS-BUFFER, search current buffer; otherwise search file found at path in first element of OLP. If UNIQUE, display a warning if OLP points to multiple headings." ;; NOTE: Disabling `case-fold-search' is important to avoid voluntary hair loss. (let* ((case-fold-search nil) (file (unless this-buffer (pop olp))) (buffer (if this-buffer (current-buffer) (or (find-file-noselect file) (error "File in outline path not found: %s" file))))) (cl-labels ((find-at (level headings) (let ((re (format org-complex-heading-regexp-format (regexp-quote (car headings))))) (when (re-search-forward re nil t) (when (and unique (save-excursion (save-restriction (when (re-search-forward re nil t) (if (cdr headings) (find-at (1+ level) (cdr headings)) t))))) (display-warning 'org-recent-headings (format "Multiple headings found in %S for outline path: %S" (current-buffer) olp) :warning)) (if (cdr headings) (progn (org-narrow-to-subtree) (find-at (1+ level) (cdr headings))) (copy-marker (point-at-bol))))))) (with-current-buffer buffer (org-with-wide-buffer (goto-char (point-min)) (find-at 1 olp)))))) #+END_SRC #+BEGIN_SRC elisp (let* ((content "* Text before [[Test heading]] Text after 1 blah blah ,** Text before [[Test heading]] Text after 2 foo bar ,*** Text before [[Test heading]] Text after 3 buzz ") (olp '("Text before [[Test heading]] Text after 1" "Text before [[Test heading]] Text after 2" "Text before [[Test heading]] Text after 3"))) (with-temp-buffer (org-mode) (dotimes (_ 2000) (insert "* Heading 1 text ,** Heading 2 text ,*** Heading 3 text ")) (insert content) (bench-multi-lexical :times 500 :ensure-equal t :forms (("org-find-olp" (org-find-olp olp t)) ("org-olp-marker" (org-olp-marker olp t t)) ("org-olp-marker*" (org-olp-marker* olp t t)))))) #+END_SRC #+RESULTS: | Form | x faster than next | Total runtime | # of GCs | Total GC runtime | |-----------------+--------------------+---------------+----------+------------------| | org-olp-marker | 2.66 | 0.857414 | 0 | 0 | | org-olp-marker* | 1.29 | 2.283076 | 0 | 0 | | org-find-olp | slowest | 2.946619 | 0 | 0 | --=-=-=--