Join GitHub today
GitHub is home to over 20 million developers working together to host and review code, manage projects, and build software together.
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
Already on GitHub? Sign in to your account
Cache projectile-project-root for performance #1149
Conversation
alexmurray
referenced this pull request
Jul 22, 2017
Open
projectile-project-root is called often and is slow #1003
|
I'd like to give this a try because I've been hit by perf in the past. |
| + (progn | ||
| + (setq projectile-cached-buffer-file-name buffer-file-name) | ||
| + (setq projectile-cached-project-root | ||
| + (or (let* ((dir default-directory) |
| @@ -911,10 +937,13 @@ This variable is reset automatically when Projectile detects that | ||
| the `buffer-file-name' has changed. It can also be reset manually | ||
| by calling `projectile-reset-cached-project-name'.") | ||
| -(defvar-local projectile-cached-buffer-file-name nil |
alexmurray
Jul 23, 2017
Contributor
I just moved it up earlier in the file so it is declared before we now first reference it.
| - (if projectile-require-project-root | ||
| - (error "You're not in a project") | ||
| - default-directory)))) | ||
| + (or (cl-subst nil 'none |
bbatsov
Jul 22, 2017
Owner
I don't understand what exactly is this supposed to do. Seems like some unnecessary complication of the code.
alexmurray
Jul 23, 2017
Contributor
To handle the case where there is no project root (and (projectile-project-root) returns nil) we can't just store nil as the cached value - as then we would end up reevaluating it every time and never using the cache. So instead we store the symbol 'none there instead - however we don't want to return 'none from the function since this invalidates the expected contract (return nil if not in a project) so we use cl-subst to replace any 'none value with nil.
bbatsov
Jul 23, 2017
Owner
Can't you simply use 'none as the default value for the buffer-local-variable?
alexmurray
Jul 24, 2017
•
Contributor
But then we will never evaluate it - the code is:
(or (and (equal projectile-cached-buffer-file-name buffer-file-name)
projectile-cached-project-root)
...)
So a non-nil value means the buffer-local cached value will be used - so it needs to be nil initially, then it gets evaluated once, and either set to a path or 'none and then it can be used as a cached value without reevaluation in the future.
fommil
Jul 24, 2017
Contributor
Isn't it easier if nil just cache misses? So what, projectile is slightly slower on directories that are not source managed or have a manual .projectile :-/
There is an elisp package for caching btw, if you'd like to reuse it.
alexmurray
Jul 24, 2017
•
Contributor
I disagree - I often use emacs on directories which are not part of a project and having EVERYTHING slow down (say when using spaceline-all-the-icons which calls (projectile-project-root) on every redisplay) is very annoying. Why go to the effort of caching in a project and not also add support for caching outside of a project?
Also it is more expensive to determine when we are outside of a project than inside a project since we can't short-circuit out of the checks - we have to exhaust every possible project test each time - so it is MORE of a win performance wise to cache in this case (ie when no project) than in the case of being in a project.
Which elisp package are you referring to?
bbatsov
Jul 24, 2017
Owner
Just explain in a comment what this code is doing for future reference and I'll merge it. No need for more 3rd party deps.
alexmurray
Jul 24, 2017
Contributor
How about c473d17 ? Do you want me to squash these all into a single commit?
alexmurray
added some commits
Jul 23, 2017
bbatsov
merged commit 7951b17
into
bbatsov:master
Jul 24, 2017
1 check passed
|
Thanks! |
| - "The last known value of `buffer-file-name' for the current | ||
| -buffer. This is used to detect a change in `buffer-file-name', | ||
| -which triggers a reset of `projectile-cached-project-name'.") | ||
| +(defun projectile-reset-cached-project-root () |
|
I wonder if it still makes sense to cache |
|
that lib: https://github.com/skeeto/emacs-memoize |
|
(in hindsight, I agree it makes sense to cache non-projects. I have worked in environments with network drives and ... short of having an extensive exclusion list for projectile... a cache for buffers in those folders would have surely helped) |
JeanMax
commented
Aug 9, 2017
|
Hey! This merge broke (projectile-all-project-files) for me. I could reproduce the behaviour with 'emacs -q' and 2 random projects, but it seems that it doesn't affect everybody. |
alexmurray commentedJul 19, 2017
Cache the result of (projectile-project-root) as a buffer local variable to
increase performance - this is implemented the same as was done
for (projectile-project-name) in PR 1906.
Should help resolve issue #1003