organize-imports-cli icon indicating copy to clipboard operation
organize-imports-cli copied to clipboard

Suggestions on performance improving

Open afterwind-io opened this issue 4 years ago • 9 comments

TL;DR: A little bit changes to the options of the Project constructor will greatly reduce the time consuming during the initializing of the new instance.

const project = new Project({
  tsConfigFilePath,
  manipulationSettings,

  // **The real problem here**
  // Should set to false and add files needed manually
  addFilesFromTsConfig: false,

  // Can reduce a chunk of time if added alone without other options
  skipFileDependencyResolution: true,

  // Not important, but a better-have theoreticallly
  compilerOptions: { isolatedModules: true },
});

In most daily cases, imports organizing only deal with files on a one-to-one basis. There is no need to know the whole detail of the project(s), nor the dependency relations of every single file. The only thing wo do need is the pure AST.

Currently, the default options of the Project constructor, which defined by ts-morph, is quite opposite to our ideal scenario:

https://github.com/dsherret/ts-morph/blob/e769b7871982ca874684e20355d58f1153efdcda/packages/ts-morph/src/Project.ts#L11-L34

FYI, we use organize-imports-cli in a middle size project, managed by lerna, with dozens of inline packages. That means, when commited files scatter acrose several packages, each package will produce an instance of Project, and each instance costs 3 seconds on average, because ts-morph is trying to load all the files during initializing, though most of them are totally irrelevant.

I have tried modify the code locally, and passed all the tests, except the excluded test, which is caused by addFilesFromTsConfig. So if you are willing to alter the options, there will be some more effort needed to deal with file resolving when included files defined in the tsconfig.json are really all needed. But for almost all daily cases, it will just works fine.

afterwind-io avatar May 26 '20 07:05 afterwind-io

I'm not sure how compiler options and dependency resolution affect organizing imports. It looks like they shouldn't really affect it, but still I'm somehow sure there are tricky edge cases I'm not aware of.

What if we add an explicit --skip-tsconfig flag? With it tsconfig.json won't be resolved and default settings will be used. Thoughts?

thorn0 avatar May 26 '20 09:05 thorn0

I just tested the following code and it works fine for me.

// cli.js:L45
/**
 * @type {Record<string, {
 *   files: 'all' | SourceFile[]
 *   project: import('ts-morph').Project,
 *   detectNewLineKind: boolean,
 * }>}
 */
const projects = {};

const defaultProject = new Project();
defaultProject.addSourceFilesAtPaths(filePaths);
projects.defaultProject = {
  project: defaultProject,
  files: defaultProject.getSourceFiles(),
};

// The whole `for` loop is commented out, for test purpose only
// for (const filePath of filePaths) {
//   const tsConfigFilePath = tsconfig.findSync(path.dirname(filePath));

I agree with the --skip-tsconfig idea, but I think the flag name itself might be a little confusing. IMO the --list-different is quite straight forward, but --skip-tsconfig is relatively harder to understand without further explanation.

Though I don't have a clear idea neither, how about --isolated-modules or --isolated-files, which refers to the compiler option --isolatedModules from Typescript. Or maybe anything else conveys "Treat every input as individual file only". The choice is yours.

afterwind-io avatar May 26 '20 13:05 afterwind-io

--isolated-modules sounds great.

thorn0 avatar May 26 '20 13:05 thorn0

Any updates?

jantimon avatar Oct 21 '20 14:10 jantimon

@afterwind-io @thorn0 The suggested options can be added to https://github.com/thorn0/organize-imports-cli/blob/master/cli.js#L74 & https://github.com/thorn0/organize-imports-cli/blob/master/cli.js#L103-L105. Is this correct? Happy to open a PR to have this shipped.

glennreyes avatar Nov 05 '20 16:11 glennreyes

@glennreyes

It has been quite a while and if I recall correctly...

https://github.com/thorn0/organize-imports-cli/blob/master/cli.js#L74

Yes.

https://github.com/thorn0/organize-imports-cli/blob/master/cli.js#L103-L105

Not sure. Seems yes. Haven't tried manipulating this before.

afterwind-io avatar Nov 06 '20 07:11 afterwind-io

It's the opposite. The first link leads to a code path where tsconfig is used. We want to skip it when the new flag is specified. Please go ahead with the PR @glennreyes.

thorn0 avatar Nov 06 '20 08:11 thorn0

it's much faster for my project after disabling the line below, are there any consequences?

this line took 5-6 seconds

      const project = new Project({ tsConfigFilePath, manipulationSettings });
if (tsConfigFilePath && !projectEntry && false) {

format a file before: 9.5s after: 2.24s

image

nhducit avatar Aug 24 '21 11:08 nhducit

Would love to have this feature added

jlissner avatar Apr 18 '23 19:04 jlissner