emacs-orgmode@gnu.org archives
 help / color / mirror / code / Atom feed
From: Lawrence Mitchell <wence@gmx.li>
To: emacs-orgmode@gnu.org
Subject: [PATCH] ox: Cache locations of fuzzy links
Date: Wed, 01 May 2013 13:18:55 +0100	[thread overview]
Message-ID: <87bo8uyjtc.fsf_-_@gmx.li> (raw)
In-Reply-To: 87zjwhxjla.fsf@Rainer.invalid

* ox.el (org-export-resolve-fuzzy-link): Look for fuzzy link in a
  cache before trying to resolve it in the parse tree.

When a document contains a large number of identical fuzzy links, it
doesn't make sense to continually search for them.  Instead, as
long as we're looking for position independent links, cache the
locations and look there first.
---
 lisp/ox.el | 48 +++++++++++++++++++++++++++++++++++-------------
 1 file changed, 35 insertions(+), 13 deletions(-)

Achim Gratz wrote:
> Lawrence Mitchell writes:
>> I did a bit of digging and here are the results.  No potential
>> fixes though.

I couldn't see how to fix up org-export-data, but here's some
band-aid to speed up resolving fuzzy links.  It works much better
for the fake test case (where there are many identical links)
than the real org manual, but I do get a slight improvement
(about 6%).  As per elp:

Before:

org-latex-export-to-latex      1           373.02289908  373.02289908
org-export-resolve-fuzzy-link  281         42.108304211  0.1498516164

After:

org-latex-export-to-latex      1           349.7238257   349.7238257
org-export-resolve-fuzzy-link  281         19.329938028  0.0687898150

Cheers,
Lawrence

diff --git a/lisp/ox.el b/lisp/ox.el
index 88b4122..bb49512 100644
--- a/lisp/ox.el
+++ b/lisp/ox.el
@@ -3976,27 +3976,49 @@ significant."
 	 ;; Split PATH at white spaces so matches are space
 	 ;; insensitive.
 	 (path (org-split-string
-		(if match-title-p (substring raw-path 1) raw-path))))
+		(if match-title-p (substring raw-path 1) raw-path)))
+	 (link-cache (plist-get info :fuzzy-link-cache)))
+    ;; Cache for locations of fuzzy links that are not position dependent
+    (unless link-cache
+      (setq info (plist-put info :fuzzy-link-cache
+			    (make-hash-table :test 'equal)))
+      (setq link-cache (plist-get info :fuzzy-link-cache)))
     (cond
      ;; First try to find a matching "<<path>>" unless user specified
      ;; he was looking for a headline (path starts with a "*"
      ;; character).
      ((and (not match-title-p)
-	   (org-element-map (plist-get info :parse-tree) 'target
-	     (lambda (blob)
-	       (and (equal (org-split-string (org-element-property :value blob))
-			   path)
-		    blob))
-	     info t)))
+	   (let ((found (gethash (cons 'path path)
+				 link-cache
+				 'fuzzy-link-not-found)))
+	     (or (not (eq found 'fuzzy-link-not-found))
+		 (puthash (cons 'path path)
+			  (org-element-map (plist-get info :parse-tree) 'target
+			    (lambda (blob)
+			      (and (equal (org-split-string
+					   (org-element-property :value blob))
+					  path)
+				   blob))
+			    info t)
+			  link-cache)))))
      ;; Then try to find an element with a matching "#+NAME: path"
      ;; affiliated keyword.
      ((and (not match-title-p)
-	   (org-element-map (plist-get info :parse-tree)
-	       org-element-all-elements
-	     (lambda (el)
-	       (let ((name (org-element-property :name el)))
-		 (when (and name (equal (org-split-string name) path)) el)))
-	     info 'first-match)))
+	   (let ((found (gethash (cons 'name path)
+				 link-cache
+				 'fuzzy-link-not-found)))
+	     (or (not (eq found 'fuzzy-link-not-found))
+		 (puthash (cons 'name path)
+			  (org-element-map (plist-get info :parse-tree)
+			      org-element-all-elements
+			    (lambda (el)
+			      (let ((name (org-element-property :name el)))
+				(when (and name (equal
+						 (org-split-string name)
+						 path))
+				  el)))
+			    info 'first-match)
+			  link-cache)))))
      ;; Last case: link either points to a headline or to nothingness.
      ;; Try to find the source, with priority given to headlines with
      ;; the closest common ancestor.  If such candidate is found,
-- 
1.8.2-rc3

  reply	other threads:[~2013-05-01 12:19 UTC|newest]

Thread overview: 18+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2013-04-27 19:28 Exporting large documents Achim Gratz
2013-04-27 19:35 ` Carsten Dominik
2013-04-29 16:04   ` Lawrence Mitchell
2013-04-29 18:44     ` Achim Gratz
2013-05-01 12:18       ` Lawrence Mitchell [this message]
2013-05-01 21:46         ` [PATCH] ox: Cache locations of fuzzy links Nicolas Goaziou
2013-05-02  9:03           ` [PATCH v2] " Lawrence Mitchell
2013-05-02 12:35             ` Nicolas Goaziou
2013-05-02 12:53               ` Nicolas Goaziou
2013-05-03  8:43     ` Exporting large documents Carsten Dominik
2013-05-03 11:12       ` Lawrence Mitchell
     [not found]         ` <877gjfgnl9.fsf@gmail.com>
     [not found]           ` <0F877AB5-D488-4223-B0E7-F11B4B973614@gmail.com>
     [not found]             ` <87ip2xfd0x.fsf@gmail.com>
2013-05-06 11:07               ` Lawrence Mitchell
2013-05-06 16:15                 ` Lawrence Mitchell
2013-05-07 10:26                   ` Bastien
2013-05-06 18:41                 ` Achim Gratz
2013-05-06 19:17                   ` Nicolas Goaziou
2013-05-06 19:32                     ` Achim Gratz
2013-05-07 14:29                       ` Nicolas Goaziou

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

  List information: https://www.orgmode.org/

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=87bo8uyjtc.fsf_-_@gmx.li \
    --to=wence@gmx.li \
    --cc=emacs-orgmode@gnu.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
Code repositories for project(s) associated with this public inbox

	https://git.savannah.gnu.org/cgit/emacs/org-mode.git

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).