Home Download Buy Blog Forum Support

Select All on Mac slow on large files

Select All on Mac slow on large files

Postby natebeaty on Thu Jun 30, 2011 8:08 pm

Seems like this is a pretty recent change (hard to keep up with all the updates!), but I've noticed Select All on files with 2000+ lines will cause the beachball spin for a good 10 seconds before selecting all the text. As I reduce the file by 500 lines or so, it speeds up incrementally until about 500 lines where there's just a small lag.

Wondering if this might have anything to do with the recent change in selections now maintaining syntax highlighting?

I'm on a 2.26ghz C2D MBP with 4GB of memory.

On the other hand I've noticed other operations speeding up dramatically in recent releases, especially scrolling & navigating text.
natebeaty
 
Posts: 120
Joined: Wed Apr 06, 2011 8:28 pm
Location: Chicago, IL

Re: Select All on Mac slow on large files

Postby jps on Fri Jul 01, 2011 12:10 am

Something is seriously wrong if Select All is showing a beachball - at a fundamental level, it doesn't do any more work than moving the cursor with the arrow key. For reference, Select All here on a file with 500k lines has no perceptible delay.

One possible cause is a plugin causing the slow down, by doing work in its on_selection_modified callback. To verify this, you can run with a clean installation:

1. Quit Sublime Text 2
2. Move ~/Library/Application Support/Sublime Text 2 to another location (all customizations are in this folder)
3. Start Sublime Text 2, and everything will be as it was when first installed - verify if the issue is still here

You can restore your settings by reversing the above procedure: delete the new ~/Library/Application Support/Sublime Text 2 folder that will get created in step 3, and move your original one back.
jps
Site Admin
 
Posts: 3062
Joined: Wed Mar 19, 2008 12:33 pm

Re: Select All on Mac slow on large files

Postby natebeaty on Fri Jul 01, 2011 1:51 am

I was going to mention what I believed was the culprit, and you are 100% correct. I found it by starting with a fresh settings dir as you suggested, and testing after adding each plugin. It's this plugin causing the hang:

Code: Select all
"""
DRAW OUTLINED
   "word_highlights_draw_outlined" : true
      Add this to your user prefs to make the highlights be drawn as outlines
      instead of as filled highlights.

HIGHLIGHT WORDS WHEN SELECTION IS EMPTY
   "word_highlights_when_selection_is_empty" : true
      Add this to your user prefs to make words highlight when the insertion point
      is inside of them but they're not actually selected.

COLOR OPTIONS
   "word_highlights_color_scope_name" : "wordhighlight"
      Normally the color of the highlights is the same as the color of comments
      in your code. If you'd like to customize the color, add the below to your
      color scheme file and change EDF2E9 to whatever color you want, then add
      this to your user file preferences.
---ADD TEXT BELOW THIS LINE TO YOUR COLOR SCHEME FILE---
      <dict>
            <key>name</key>
            <string>WordHighlight</string>
            <key>scope</key>
            <string>wordhighlight</string>
            <key>settings</key>
            <dict>
               <key>foreground</key>
               <string>#EDF2E9</string>
          </dict>
      </dict>
---ADD TEXT ABOVE THIS LINE TO YOUR COLOR SCHEME FILE---
"""

import sublime
import sublime_plugin

DEFAULT_COLOR_SCOPE_NAME = "comment"

def regex_escape(string):
   outstring = ""
   for c in string:
      if c != '\\':
         outstring += '['+c+']'
      else:
         outstring += '\\'
   return outstring

class WordHighlightListener(sublime_plugin.EventListener):
   def on_selection_modified(self,view):
      settings = view.settings()
      color_scope_name = settings.get('word_highlights_color_scope_name', DEFAULT_COLOR_SCOPE_NAME)
      draw_outlined = bool(settings.get('word_highlights_draw_outlined')) * sublime.DRAW_OUTLINED
      word_separators = settings.get('word_separators')
      
      regions = []
      for sel in view.sel():
         #If we directly compare sel and view.word(sel), then in compares their
         #a and b values rather than their begin() and end() values. This means
         #that a leftward selection (with a > b) will never match the view.word()
         #of itself.
         #As a workaround, we compare the lengths instead.
         if len(sel) == len(view.word(sel)):
            string = view.substr(sel).strip()
            if len(string):
               regions += view.find_all('\\b'+regex_escape(string)+'\\b')
         elif len(sel) == 0 and bool(settings.get('word_highlights_when_selection_is_empty')):
            string = view.substr(view.word(sel)).strip()
            if len(string) and all([not c in word_separators for c in string]):
               regions += view.find_all('\\b'+regex_escape(string)+'\\b')
      view.add_regions("WordHighlight", regions, color_scope_name, draw_outlined)


I changed this line:
Code: Select all
if len(sel) == len(view.word(sel)):

to:
Code: Select all
if len(sel)<=100 and len(sel) == len(view.word(sel)):

and all is well now. Thanks again for the quick response.
natebeaty
 
Posts: 120
Joined: Wed Apr 06, 2011 8:28 pm
Location: Chicago, IL

Re: Select All on Mac slow on large files

Postby adzenith on Fri Jul 01, 2011 7:13 am

Is there a reason view.word() takes so long? It seems like it could work backward from the beginning of the selection and forward from the end and in either case just bail at a non-word character.
adzenith
 
Posts: 1214
Joined: Mon Oct 19, 2009 9:12 pm

Re: Select All on Mac slow on large files

Postby jps on Fri Jul 01, 2011 7:51 am

That is the way view.word() operates. I suspect the slowdown comes from constructing or matching the very long regex that will be passed to view.find_all().

view.word(region) will expand the begin and end portions of the region to be on word boundaries - it'll happily return a selection consisting of the whole file, for example, rather than containing just a single word. The method name doesn't clearly indicate this, unfortunately.

A better check than:
Code: Select all
if len(sel) == len(view.word(sel)):

would be:
Code: Select all
if view.word(sel.a) == view.word(sel.b):

this would check that the selection is either a whole or portion of a single word, which I think was the original intention.
jps
Site Admin
 
Posts: 3062
Joined: Wed Mar 19, 2008 12:33 pm

Re: Select All on Mac slow on large files

Postby adzenith on Fri Jul 01, 2011 5:01 pm

jps wrote:That is the way view.word() operates. I suspect the slowdown comes from constructing or matching

Oh of course—when natebeaty said that adding "len(sel)<=100" fixed things, I assumed from glancing at the line that it fixed things by shortcutting the view.word() call, but it also obviously skipped over the entire body of the if statement.

The original intention was actually to check that an entire word was selected: i.e. if I select the variable "sel", I would see all instances of it highlighted, but if I select the "sel" at the beginning of the word "select" in this sentence, I wouldn't want any highlights.
I guess I could do this:
Code: Select all
if len(sel) == len(view.words(sel.a))

That seems like it should work unless the word itself is really quite long.
adzenith
 
Posts: 1214
Joined: Mon Oct 19, 2009 9:12 pm

Re: Select All on Mac slow on large files

Postby adzenith on Fri Jul 01, 2011 5:07 pm

Really I think the best answer actually is just limiting the length of the input word like natebeaty did—I find that I actually like being able to select multiple consecutive words (like "settings.get") and having all occurrences highlight.
adzenith
 
Posts: 1214
Joined: Mon Oct 19, 2009 9:12 pm


Return to Technical Support

Who is online

Users browsing this forum: Alexa [Bot], Google [Bot] and 28 guests