Skip to content

feat: Use async and batch stage commands#151

Closed
C-Hess wants to merge 12 commits intoprettier:masterfrom
C-Hess:async-experiment
Closed

feat: Use async and batch stage commands#151
C-Hess wants to merge 12 commits intoprettier:masterfrom
C-Hess:async-experiment

Conversation

@C-Hess
Copy link
Contributor

@C-Hess C-Hess commented Apr 22, 2022

pretty-quick(er? 🚀 )

Description

We noticed some performance issues with larger repository and environments at my workplace. In particular, we'd notice the most performance issues when pretty-quick runs on merge conflict commits, as it has to scan and prettify all files from the merge.

After forking pretty-quick and running a bunch of console.time() commands ( 😉 ), most of the performance impact seemed to come from the "git add" step (around 100ms~200ms). This amount of delay is reasonable for a small number of files, but for large commits it starts to add up to many seconds. It's a small, but noticeable delay that I believe goes goes against the spirit of the utility .

As a result, I changed most file system calls to their asynchronous equivalents, and more importantly changed staging each file into a single batched "stage" command/step after all of the files are "prettified". I'm seeing some subjective performance gains as a result of these changes, but haven't gotten the time yet to quantify it into numbers.

Let me know what, if any, of these changes you are interested in merging that might make this PR more manageable :)

This also Fixes #100

How Has This Been Tested?

We'll be piloting the forked version in our office of 50 developers or so. We only use git, and don't use some of the advanced flags for this plugin, so the breadth of end-to-end testing will be limited.

Things that should probably be done before merging

  • End to end test using Hg
  • Get some performance stats to quantify performance gains
  • Write tests for the batch staging functionality

@@ -1,15 +1,10 @@
const mockStream = () => ({
Copy link
Contributor Author

Choose a reason for hiding this comment

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

Pretty sure this isn't actually used anymore? I think execa is mocked in every test using jest.mock anyways

'✗ Code style issues found in the above file(s). Forgot to run Prettier?',
);
}
if (prettyQuickResult.errors.indexOf('STAGE_FAILED') !== -1) {
Copy link
Contributor Author

Choose a reason for hiding this comment

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

New error state due to the introduction of the "staging" step

});

prettyQuick('root');
await prettyQuick('/');
Copy link
Contributor Author

Choose a reason for hiding this comment

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

Okay. You'll see this in a lot of places :(

I develop on windows, and the issue is that the "find-up" module is pulling OS specific root directories in it's results (ex. it returns "C:\" instead of what you would expect from mock-fs: "/")

I changed most of the tests to pull from the root directory .git/ instance. The only test that is relatively unchanged is the test that specifically makes sure to grab the .git/ from the parent folder. I left that one in a failed state for now on my local, but I believe it will pass CI. In the future, the find-up module will probably need a good mock that utilizes the mock-fs

onExamineFile: verbose && onExamineFile,
});

if (filesToStage.length > 0) {
Copy link
Contributor Author

Choose a reason for hiding this comment

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

This is the new "staging" step that was added

export const stageFile = (directory, file) => {
runGit(directory, ['add', file]);
export const stageFiles = async (directory, files) => {
const maxArguments = 100;
Copy link
Contributor Author

Choose a reason for hiding this comment

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

Complete transparency: I didn't spend too much time looking into exaca, but I know that some OS/shells limit the number of arguments you can pass. I figured 100 is a reasonable batch size

@C-Hess
Copy link
Contributor Author

C-Hess commented Apr 22, 2022

Ah, it does look like this would break compatibility with node 10 and thus would be a breaking change. Let me know if I'm good to remove node 10.* from the test matrix 😮

@JounQin
Copy link
Member

JounQin commented Jan 17, 2024

@C-Hess Do you want to work on this again if after #182 been released?

@C-Hess
Copy link
Contributor Author

C-Hess commented Apr 15, 2024

@JounQin , Sorry it toke me so long to get back to this. I can certainly attempt this with the new changes

@JounQin
Copy link
Member

JounQin commented Jun 2, 2025

It seems I don't have the permission to push.

 pretty-quick on  async-experiment ❯ gp -u C-Hess async-experiment -f
枚举对象中: 26, 完成.
对象计数中: 100% (26/26), 完成.
使用 10 个线程进行压缩
压缩对象中: 100% (12/12), 完成.
写入对象中: 100% (12/12), 2.92 KiB | 2.92 MiB/s, 完成.
总共 12(差异 9),复用 0(差异 0),包复用 0(来自  0 个包)
remote: Resolving deltas: 100% (9/9), completed with 9 local objects.
To https://github.com/C-Hess/pretty-quick.git
 ! [remote rejected] async-experiment -> async-experiment (permission denied)
错误:无法推送一些引用到 'https://github.com/C-Hess/pretty-quick.git'

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

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Use async approach

3 participants