Skip to content
This repository was archived by the owner on Mar 3, 2023. It is now read-only.

Move git refresh status task to long running task (Bug #9544)#14456

Closed
Xapphire13 wants to merge 18 commits intoatom:masterfrom
Xapphire13:gitRefreshTask
Closed

Move git refresh status task to long running task (Bug #9544)#14456
Xapphire13 wants to merge 18 commits intoatom:masterfrom
Xapphire13:gitRefreshTask

Conversation

@Xapphire13
Copy link
Contributor

@Xapphire13 Xapphire13 commented May 17, 2017

Description of the Change

This PR addresses #9544. The issue here is that upon gaining focus, Atom spins off a new task to update the repository status. Profiling Atom during this time shows that there is a lengthy (~ 2 seconds on my machine, longer on others') delay on the rendering thread due to the child_process.fork(). This PR changes it so that each repository has its own there is a single long running task that receives a message upon needing to update repo status. This moves the overhead of the child_process.fork() into a single hit per repo (I am experiencing zero noticeable delay upon focus now).

Alternate Designs

An alternate design would be to have a single task that handled messages for all repositories. I didn't go this route as I didn't want to change the method signatures in the areas I touched. If we did it at the workspace level, we would need to allow for passing in a reference to the task. And potentially add a few .destroy() methods to the layer that housed the task. I figure that it would be rare to have a number of repositories open at any given time that would cause negative effects due to the number of helper tasks alive.

I managed to implement the alternate design without making a change to the API

Why Should This Be In Core?

This fixes an issue within core itself.

Benefits

Usability of Atom is increased as you spend less time per day waiting on a blocked rendering thread.

Possible Drawbacks

If you have a high number of repos open on Atom, you will have a high number of child processes.

n/a

Applicable Issues

n/a

@winstliu
Copy link
Contributor

Awesome! Looks like there's quite a few lint and test failures though - could you please address those?

@Xapphire13
Copy link
Contributor Author

Yeah sorry about that. Forgot to run the lint script. Fixing now =]

@Xapphire13
Copy link
Contributor Author

Finally fixed the tests =]. Seems that window.requestIdleCallback() was causing the tests to fail. Not sure why though. The experience was useful as I found a few areas where tests weren't cleaning themselves up correctly, fixed that too. All tests are passing locally and in the CIs, with the exception of AppVeyor which seems to be having issues right now (same apm issue on other people's builds too)

@Xapphire13
Copy link
Contributor Author

Xapphire13 commented Jun 1, 2017

@50Wliu, what is the usual turnaround time for an Atom PR?

@winstliu
Copy link
Contributor

winstliu commented Jun 2, 2017

It depends. There's a lot of changes happening right now, so I can't give you an estimate. It is in the todo list however. (I know that's not the answer you were looking for, but it's the best I can give.)

@BinaryMuse
Copy link
Contributor

Thanks for the PR, and thanks for being patient as we worked through it!

There are a few concerns I have regarding this change as it stands. Items 1 and 2 are addressable, but 3 and 4 I'm not sure about for the short term. Definitely open to feedback especially from @smashwilson and @kuychaco.

  1. It doesn't look like we do any handling of the status handler instance if it crashes unexpectedly — we'd want to detect this and clear the appropriate state in the helper so the next call to refreshStatus properly restarts it.
  2. It also doesn't look like we do any handling in the task itself of any errors. I know this was all just copy/pasted from the old code, but I think wrapping at least the call to repo.release() in a try/finally would be a good idea.
  3. This creates a new long-running sidecar process for every Atom window. Probably not the biggest deal, but the GitHub package already does this for its own Git handling; a proper solution to the problem being addressed here (and, in general, for providing Git information to other parts of Atom) is to expose a service from the GitHub package that core and other packages can consume. Unfortunately this isn't trivial and probably not a viable short-term solution.
  4. The Task API uses ChildProcess#send for communication, which (as we discovered while working on the GitHub package) has a bug that causes a quadratic growth in time as the size of the input grows. Eventually the version of Node contained in Electron will provide a fix for this, but in the meantime we were still seeing a lot of UI jank and freezing during large repositories simply due to the size of the output when calling status. @kuychaco fixed this by using a sidecar Electron process/IPC instead of native Node IPC — again, exposing a service from the GitHub package, which already has this feature, makes the most sense to address this.

@Xapphire13
Copy link
Contributor Author

Thanks for the review! I have updated with changes addressing items 1 and 2. I'm unsure of how to move forward with items 3 and 4 however.

startHandler = ->
if not handlerInstance?
handlerInstance = new Task require.resolve('./repository-status-handler')
terminatedSub = handlerInstance.on "exit", status ->
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks like a minor typo here: (status) -> instead of status ->

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oops. Removed the param entirely as it's unused

@Xapphire13
Copy link
Contributor Author

Anything else I can add to the PR? I'm eager to work on this to address any concerns. It seems like the bug im addressing is getting a lot of attention from people this PR could help.

@Zireael07
Copy link

What's the holdup on merging this?

@BinaryMuse
Copy link
Contributor

I'm still concerned about the remaining issues I commented on above. Pinging @atom/core for additional 💭 s around this feature.

@Xapphire13
Copy link
Contributor Author

No worries, if it gets merged, I want it to be the right code for the job =]

@iolsen
Copy link
Contributor

iolsen commented Aug 11, 2017

My opinion, based on 3 and 4 in @BinaryMuse's comment, is that we should hold off merging this until the GitHub package exposes a service it can call. We've begun thinking about the right way to implement that.

@Xapphire13
Copy link
Contributor Author

Abandoning until #1089 is resolved. The new PR at that time will likely share little code with this.

@BinaryMuse
Copy link
Contributor

Alright, after considerable discussion with the rest of the team, I'm opting to reopen this PR, get it up to date with the new changes in #15415, and get it merged in. Apologies for the back and forth as we've explored the various ways to fix the underlying issue, and thanks again @Xapphire13 for the PR.

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

6 participants