GNU bug report logs - #15295
which-func-mode slow in long Python tuple

Previous Next

Package: emacs;

Reported by: Dale <dale <at> codefu.org>

Date: Sat, 7 Sep 2013 00:48:02 UTC

Severity: normal

Done: fgallina <at> gnu.org (Fabián Ezequiel Gallina)

Bug is archived. No further changes may be made.

Full log


View this message in rfc822 format

From: help-debbugs <at> gnu.org (GNU bug Tracking System)
To: fgallina <at> gnu.org (Fabián Ezequiel Gallina)
Cc: tracker <at> debbugs.gnu.org
Subject: bug#15295: closed (which-func-mode slow in long Python tuple)
Date: Tue, 24 Dec 2013 20:09:02 +0000
[Message part 1 (text/plain, inline)]
Your message dated Tue, 24 Dec 2013 17:08:09 -0300
with message-id <87sitij9li.fsf <at> tata.lan>
and subject line 
has caused the debbugs.gnu.org bug report #15295,
regarding which-func-mode slow in long Python tuple
to be marked as done.

(If you believe you have received this mail in error, please contact
help-debbugs <at> gnu.org.)


-- 
15295: http://debbugs.gnu.org/cgi/bugreport.cgi?bug=15295
GNU Bug Tracking System
Contact help-debbugs <at> gnu.org with problems
[Message part 2 (message/rfc822, inline)]
From: Dale <dale <at> codefu.org>
To: bug-gnu-emacs <at> gnu.org
Subject: which-func-mode slow in long Python tuple
Date: Fri, 06 Sep 2013 19:47:19 -0500
	I happen to have a Python source file that has a relatively long tuple 
at the module top level, i.e. a Python source file containing:

----------
foo = (
    "item 1",
    "item 2",
    # ...and so on for ~500 lines
)
----------

I also use which-function-mode.  If I go to the end of that tuple and 
move the cursor in to it, Emacs becomes unusably slow.  It will appear 
to lock up and eat 100% CPU for 10-20 seconds each time I move the 
cursor within the end of that tuple.  Emacs remains responsive at the 
top of the tuple.

	I think this is happening because python-info-current-defun is slow 
when dealing with long tuples.  (Maybe lists, dicts, and other things 
too; I only tested tuples.)  Here's some elisp to produce a test case 
and benchmark python-info-current-defun:

----------
(progn
  (set-buffer (generate-new-buffer "*test*"))
  (python-mode)
  (insert "foo = (\n")
  (dotimes (_ 500) (insert "    \"bar\",\n"))
  (insert ")\n")
  (forward-line -2)
  (message "%S" (benchmark-run (python-info-current-defun))))
----------

This makes a python-mode buffer named "*test*" containing only a 
500-item Python tuple, as in my above example.  On my hardware, the 
above benchmark-run yields a result such as "(7.364507 131 
0.9572049999999979)", i.e. 7.3 seconds to run.

	Once that *test* buffer is created, feel free to turn on 
which-function-mode in there and see that Emacs locks up every time you 
move the cursor around in the end of that tuple.  (which-function-mode 
seems to be taking about twice the time reported by benchmark-run. 
Perhaps it's calling python-info-current-defun twice?)

	I have reproduced this behavior with "emacs -Q" using an Emacs I just 
built from trunk, looks like revision 114162.  (I get Emacs from Git, 
where the master branch is 0f1532f2fe2.)  I have also reproduced this 
with python.el from the emacs-24 branch, looks like revision 111403.

	Thanks to everyone who develops Emacs, an indispensable tool for me!

Dale


[Message part 3 (message/rfc822, inline)]
From: fgallina <at> gnu.org (Fabián Ezequiel Gallina)
To: 15295-done <at> debbugs.gnu.org
Date: Tue, 24 Dec 2013 17:08:09 -0300
Fixed in revno 115736.

Thanks Dale for such detailed recipe.

This patch banishes initial thoughts of `python-syntax-context' being a
bad idea.  `python-syntax-context' is nothing than a thin semantic
wrapper over `syntax-ppss'. It makes code easier to grasp for newcomers
to Elisp and has almost no impact on itself, it's optional argument is a
`syntax-ppss' list which can be used instead to lower the amount of
calls to it (as it is happening in this new patch I've just committed).

The problem here was that `python-nav-beginning-of-statement' was coded
awfully (looking for the statement beginning line by line). Now it
should be extremely fast compared to that.

Using OP's suggested recipe, here are the elp results for when
which-func is triggered inside the big tuple:

    python-info-current-defun                      2           0.003719249   0.0018596245
    python-nav-beginning-of-defun                  2           0.0036946010  0.0018473005
    python-nav--beginning-of-defun                 2           0.003685751   0.0018428755
    python-nav-backward-block                      2           0.001836524   0.000918262
    python-nav-forward-block                       2           0.0018315750  0.0009157875
    python-info-looking-at-beginning-of-defun      6           0.000889166   0.0001481943
    python-nav-beginning-of-statement              4           0.000437251   0.0001093127
    python-syntax-context-type                     6           5.009e-06     8.348...e-07

And this is the benchmark-run result: (0.020715153 0 0.0)


Regards,
Fabián.


This bug report was last modified 11 years and 229 days ago.

Previous Next


GNU bug tracking system
Copyright (C) 1999 Darren O. Benham, 1997,2003 nCipher Corporation Ltd, 1994-97 Ian Jackson.