Source Tree 1.5.6 (App Store) is very slow after hg pull+update
Asked by Bi11:

After hg repo pull+update, view log is very slow to be updated.

Active Monitor shows 10+ python processes consumes full CPU.

On my MacBook Air, Source Tree usually takes 3\~5s to display log view, about 10s to fully display diffs. It is slow but acceptable.

After pull+update dialog closed, Source Tree need 30s+ to make log view updated.

Source Tree 1.5.6 (App Store)

Mac OS X 10.8.2

MacBook Air 11-inch Late 2010, 1.4G Core 2 Duo, 4G DDR3, 64G SSD.


Answers:
author: Bi11
body: I finally make my Source Tree works fast!

The trick is to use System Mercurial instead of Embedded Mercuial!

Embedded version is 2.2.2

My current hg version is 2.2.3+20120707

Now Source Tree only takes 1 to 3s on my MacBook Air when the log view refreshed. Sweet!

comments: author: Bi11
body: On another Mac Mini, change to System Mercurial (2.2.2+20120602) also makes Source Tree much faster. And now it only takes 1 to 2s to do the log view refresh too.


author: stevestreeting
body: Glad you've got it working. This was my suggestion in point 3 of my original reply ;)


author: Bi11
body: Is it not cause by the difference of hg version, but python version?

I remebered that I was using Source Tree which is not from App Store, and I registered it (free). but I changed to App Store version because it is slow. After changed to App Store version, there is no difference, may be even slower, that made me to post a question here. :-(

My /usr/bin/python is 2.7.2.

My Mac OS was updated from 10.6 to 10.7 and now 10.8. Under /usr/bin/, there is python2.5, python2.6 and python2.7, linked to Python.framework. But /usr/bin/python is none of them.

$ /usr/bin/python2.7  
Python 2.7.2 (default, Jun 20 2012, 16:23:33)   
\[GCC 4.2.1 Compatible Apple Clang 4.0 (tags/Apple/clang-418.0.60)\] on darwin

$ /usr/bin/python  
Python 2.7.2 (default, Jun 20 2012, 16:23:33)   
\[GCC 4.2.1 Compatible Apple Clang 4.0 (tags/Apple/clang-418.0.60)\] on darwin

MD5 (/usr/bin/python) = d715a9f1baf67f04265b385ae43fb503  
MD5 (/usr/bin/python2.7) = f04e60346870d7c834352eb58beb1fb8

32 -rwxr-xr-x 2 root wheel 58896 Jul 28 00:47 /usr/bin/python  
8 lrwxr-xr-x 1 root wheel 75 Jul 28 00:47 /usr/bin/python2.7 -\> ../../System/Library/Frameworks/Python.framework/Versions/2.7/bin/python2.7

16 -rwxr-xr-x 1 root wheel 35120 Jul 28 00:47 /System/Library/Frameworks/Python.framework/Versions/2.7/bin/python2.7

Wired.


author: stevestreeting
body: The issue is probably that the embedded Mercurial version is pre-compiled for python 2.7, and further saving of re-compiled Python should your default version be different is disabled, because we're not alllowed to save /update files in the app bundle (it would break the code signature). Using the system Mercurial allows compiled python for whatever version you're using to be saved because that's outside of SourceTree.

If you're on 10.8 now the default Python should be 2.7, but the fact you've upgraded may have left earlier versions as the default. This isn't necessarily controlled by /usr/bin/python for Mac apps, it can be overridden in 2 ways:

1. Setting via defaults, e.g. to override to python 2.6

defaults write com.apple.versioner.python Version 2.6

You can check to see whether yours has been overriden this way via:

defaults read com.apple.versioner.python Version

2. Environment variables, e.g for 2.6:

export VERSIONER_PYTHON_VERSION=2.6

In both cases, running 'python --version' on the command line should tell you which version is the default, which is more reliable than just looking at what versions are on your disk.


author: Bi11
body: 'python --version' return 2.7.2  
The domain/default pair of (com.apple.versioner.python, Version) does not exist  
no VERSIONER_PYTHON_VERSION in Environment variables.

But I found it is really caused by python re-compiling.

In terminal, I run  
python -v /Applications/SourceTree.app/Contents/Resources/mercurial_local/hg_local

In the debug information, I found something like this:

import hgext # directory hgext  
# hgext/__init__.pyc has bad mtime  
import hgext # from hgext/__init__.py  
# wrote hgext/__init__.pyc  
# hgext/mq.pyc has bad mtime  
import hgext.mq # from hgext/mq.py  
# wrote hgext/mq.pyc  
# hgext/graphlog.pyc has bad mtime  
import hgext.graphlog # from hgext/graphlog.py  
# wrote hgext/graphlog.pyc  
# mercurial/revset.pyc has bad mtime  
import mercurial.revset # from mercurial/revset.py  
# wrote mercurial/revset.pyc  
# mercurial/parser.pyc has bad mtime  
import mercurial.parser # from mercurial/parser.py  
# wrote mercurial/parser.pyc

Yes, lots of pyc files updated.

Guess what, I switched back to embedded version, it got almost same fast speed as System version.

And yes, the app bundle is failed of codesign -v because of pyc modified. But I can still run it.


author: stevestreeting
body: Interesting, because we pre-compile all the python as part of our release script, however because of a bug in XCode on Mountain Lion (which is now fixed, but still affects some people who haven't updated yet) we have to do this on Lion, where the python version is 2.7.1 rather than 2.7.2. I didn't think a minor version difference would matter here but perhaps it does.


author: Bi11
body: I tested on another Mac, it's takes 5s to do a log view refresh.

Mac mini (Mid 2011) 2.3 Core i5, 4G memory.

406G Disk Free Space, Repo 300M.

Hg works fast, but Source Tree log view refresh if very slow (after commit, update, pull, etc.).


author: stevestreeting
body: I'm working on a 2010 i5 MBP with a non-SSD drive and cannot reproduce this. Speed after pulling is no different to any other time here, average just under 2s. Repo size is \~400MB.

A few things that might affect this:

1. Disk space free. OS X becomes considerably less efficient when you're below about 15GB or 10%, because its dynamic defragmentation cannot function as effectively when you're below this.
2. Subrepositories. Do you have any in this repo?
3. Python version. Have you replaced the system Python version with a different one? SourceTree precompiles all the Mercurial scripts for Python 2.7, the default on Lion and Mountain Lion. The Mac App Store version cannot save compiled code, so if you've set a different global Python version you should switch to using a system-installed version of Mercurial which can have its Python precompiled and saved.

comments: author: Bi11
body: My repo is very simple and only about 100 logs, 3MB in total.

I just opened Source Tree, first open log view only 2s, after pull+update, it takes 14s.

1 Disk free space more than 5G.

2 No subrepos

3 No system file change.

The only bottleneck is my CPU. The 10 more python processes started after pull+update are nesscary? That takes a lot time with full CPU usage.


author: stevestreeting
body: FYI, 5GB is under the recommended free space for OS X. 15GB / 10% is the recommended minimim for optimal performance. I've seen several of 1st gen MBAs have issues when they're low on free space.

Building the SourceTree views takes a few different hg calls, especially the log view. I wouldn't have thought it was 10, but I guess that's possible. On my 2010 MBP I only ever see 1 or 2 in Activity Monitor, my guess is that due to the performance issues caused by low disk space they're clogging up.

The fact that it happens just after Pull and at no other time also suggests disk issues. The refresh tasks after Pull are completely identical to the tasks when first opening the repo, since it has to build the same visual state. I think it's particularly slow for you after Pull because that's changed files on disk, which has caused the OS X disk management to kick in, and it's slow because it doesn't have enough free space to work efficiently.


author: Bi11
body: I've tested another small repo with only pull one change set with one file changes.

In terminal, hg pull -u finished immediatly after pulling from remote server.

I striped the change set and tested again.

In source tree, refresh after pull, takes 5s; refresh after update, takes 5s; refresh after pull+update, takes 10s.

I think the log refresh takes a long time on my MacBook Air, and after pull+update, it takes 2x time.


author: stevestreeting
body: SourceTree issues a bunch of extra hg commands after the pull's completed in order to refresh all the UI elements, so just comparing with the pull -u isn't representative. That said, I've just tested again here with a reasonably sized pull (161 commits, \~80MB repository) on a 2010 MBP, i5 with non-SSD drive, here's the result:

<http://screencast.com/t/byhPm4HF7D>

The pull completes at 32s and the refresh completes just before 35s, it takes 2.5s here which is about the same time as it always does. I used the log view as a test since that's the most expensive view to be on when the refresh occurs.

I would refer you back to my original list of potential reasons for a slower experience on your machine. My test machine is hardly a powerhouse so there must be something else going on here. Are you running Python 2.6 perhaps (Snow Leopard) and using the Mac App Store version (my point 3 originally)?


author: Bi11
body: I would like to use QuickTime to do a screen recording, but the recording takes 100% cpu, that makes Source Tree deadly slow. So I used my iPhone to do the record.

<http://www.screencast.com/t/kccGtzRVR>

The refresh takes more than 5s after update.

Btw, it's a bit faster when I made another 5G free space (now 10G free in total). But it is only a bit faster.

I'll take another screen record on a more powerful Mac tomorrow.