Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Imporve performance when generating spec with external dependencies #1108

Merged
merged 3 commits into from May 18, 2022

Conversation

pytimer
Copy link
Contributor

@pytimer pytimer commented Jan 21, 2022

Describe the PR

Directly use go list command instead of depth, because depth use go standard library build.Import and call the build.Import too many times, it will spent too many times when the large dependencies.

Because swag only needs to know which files are dependent, and does not need to get the level of dependencies, all dependencies can be directly through go list command, and swag not need to go through deep loop again, but if use depth, swag still need to loop too many times, so i refactor the swag get ast files code.

Relation issue

Fixes: #1032

Additional context

Added the --parseGoList flag, the default value is true default. If someone does not want to enable it, it can be set to false when init, if it's set to false, swag still use depth for dependency parser.

@codecov
Copy link

codecov bot commented Jan 21, 2022

Codecov Report

Merging #1108 (842c7a2) into master (636f456) will increase coverage by 0.33%.
The diff coverage is 88.23%.

❗ Current head 842c7a2 differs from pull request most recent head ceb23ac. Consider uploading reports for the commit ceb23ac to get more accurate results

@@            Coverage Diff             @@
##           master    #1108      +/-   ##
==========================================
+ Coverage   95.03%   95.37%   +0.33%     
==========================================
  Files          10       11       +1     
  Lines        2557     2614      +57     
==========================================
+ Hits         2430     2493      +63     
+ Misses         69       66       -3     
+ Partials       58       55       -3     
Impacted Files Coverage Δ
parser.go 93.69% <83.33%> (+0.82%) ⬆️
golist.go 90.24% <90.24%> (ø)
gen/gen.go 93.30% <100.00%> (+0.03%) ⬆️
packages.go 86.74% <100.00%> (+1.26%) ⬆️
operation.go 96.64% <0.00%> (+0.29%) ⬆️

Continue to review full report at Codecov.

Legend - Click here to learn more
Δ = absolute <relative> (impact), ø = not affected, ? = missing data
Powered by Codecov. Last update 636f456...ceb23ac. Read the comment docs.

@ubogdan
Copy link
Contributor

ubogdan commented Jan 25, 2022

Unfortunately, I will have a busy week.

@easonlin404 can you please assist with a CR here?

@magandrez
Copy link

@ubogdan @easonlin404 Is there any way to contribute to this change? please, let know.

@ubogdan
Copy link
Contributor

ubogdan commented Feb 7, 2022

This implementation introduces a dependency over an external binary, the go binary, that comes with some new challenges :

  1. The output format may change over time.
  2. You may get slightly different output on different go versions.
  3. You may run the generator in an environment where the GO binary it's not in PATH.
  4. You may run the generator in an environment where the GO binary is not the same as your one to build your project.

I prefer to see this done programmatically by importing a go library that handlers go.mod and calling the specific methods.

The solution proposed by @pytimer may look like a quick fix at this time. Once the feature gets merged to master, the community will start using it, more issues will arrive, and code complexity will grow.

@pytimer
Copy link
Contributor Author

pytimer commented Feb 8, 2022

@ubogdan swag currently already depends on the go binary, now if the env has not go binary, swag init failed, because init first call go list to get pkg name, the code is getPkgName.
depth call build.Default, this code also call the go binary file, if no go binary, it will return ErrRootPkgNotResolved, this pr does not newly introduce the go binary.

However, the two points 2 and 4 above @ubogdan said do need to be pay attention to. I don't know much about the output of multiple versions of go list. I only tested it on versions of go 1.16 and 1.17.
I will try to understand the output format of go list in different versions. If anyone else is familiar with it, please point it out.

@ubogdan
Copy link
Contributor

ubogdan commented Feb 8, 2022

@ubogdan swag currently already depends on the go binary,
Please don't return this as an excuse.
I explained why I wouldn't say I like the idea, but didn't refuse the implementation.
It's more simple for me to Approve and Merge and after that, I can tag you in every issue where a community member is complaining something is wrong.

@ubogdan
Copy link
Contributor

ubogdan commented Feb 8, 2022

I expect to see at least one opinion from @easonlin404 or @sdghchj regarding this matter before going forward to do a real CR and approve it.

@g1eny0ung
Copy link

Any updates? After my local testing, this will greatly improve the generation speed.

@ubogdan
Copy link
Contributor

ubogdan commented Mar 7, 2022

I will consider this total silence as an aproval.
@pytimer I will go forward with a code review in the next few days, please confirm you are still interested to finish this PR.

@pytimer
Copy link
Contributor Author

pytimer commented Mar 7, 2022

Thanks.
I read some docs about not use binary execute command to do it recently, but unfortunately i don't find.

I try golang.org/x/tools/go/packages.Load, but it not works well.

Perhaps use go list now and find the better ways to optimize in later version, what's your recommend?

@ubogdan
Copy link
Contributor

ubogdan commented Mar 7, 2022

We will go with the current implementation. Please confirm you still intend to finish this PR so I can go with a CR.

@pytimer
Copy link
Contributor Author

pytimer commented Mar 7, 2022

We will go with the current implementation. Please confirm you still intend to finish this PR so I can go with a CR.

Yes,please tell me if need I do.

Copy link
Contributor

@ubogdan ubogdan left a comment

Choose a reason for hiding this comment

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

See comments ... Also include the usage example in the README.md

gen/gen.go Outdated
@@ -151,6 +154,7 @@ func (g *Gen) Build(config *Config) error {
p.ParseVendor = config.ParseVendor
p.ParseDependency = config.ParseDependency
p.ParseInternal = config.ParseInternal
p.ParseGoList = config.ParseGoList

Copy link
Contributor

Choose a reason for hiding this comment

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

Please use the pattern above

	p := swag.New(swag.SetMarkdownFileDirectory(config.MarkdownFilesDir),
         ......
	     swag.ParseUsingGoList(config.ParseGoList),
        }

We will clean the other ones later.

golist.go Show resolved Hide resolved
golist.go Show resolved Hide resolved
golist.go Show resolved Hide resolved
golist.go Show resolved Hide resolved
golist.go Show resolved Hide resolved
golist.go Show resolved Hide resolved
golist.go Show resolved Hide resolved
parser.go Outdated Show resolved Hide resolved
@pytimer
Copy link
Contributor Author

pytimer commented Mar 9, 2022

@ubogdan Update the code, you can review it if you have time, thanks.

Should i squash all commits after review or now?

ubogdan
ubogdan previously approved these changes Mar 9, 2022
Copy link
Contributor

@ubogdan ubogdan left a comment

Choose a reason for hiding this comment

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

LGTM

@ubogdan
Copy link
Contributor

ubogdan commented Mar 9, 2022

@ubogdan Update the code, you can review it if you have time, thanks.

Should i squash all commits after review or now?

We are using "Squash and Merge" for all the contributions.

golist.go Outdated
// Skip cgo
if pkg.Name == "C" {
return nil
}
Copy link
Contributor

Choose a reason for hiding this comment

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

Please cover this by calling the function with a build.Package instance.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

ok, i will add some testing on this Saturday, i don't have the bandwidth these days, sorry.

@ubogdan
Copy link
Contributor

ubogdan commented Mar 9, 2022

Please improve code coverage so we can merge it.

Copy link

@akhmadKurniawan akhmadKurniawan left a comment

Choose a reason for hiding this comment

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

ok

@sdghchj
Copy link
Member

sdghchj commented Mar 22, 2022

I expect to see at least one opinion from @easonlin404 or @sdghchj regarding this matter before going forward to do a real CR and approve it.

As far as I see, go list will find out all its dependent packages, I am not sure whether it's more efficient in a huge project or not.

@pytimer pytimer force-pushed the golist branch 4 times, most recently from 56a4e31 to 9fe3da7 Compare March 30, 2022 06:54
@magandrez
Copy link

Any ETA to land this? @ubogdan

@ubogdan
Copy link
Contributor

ubogdan commented Apr 8, 2022

@magandrez, I'm waiting for @pytimer to improve code coverage so we can merge it.

@g1eny0ung
Copy link

g1eny0ung commented Apr 24, 2022

@ubogdan I wonder if it is possible to draft a new release after merging this PR? I've been looking forward to this improvement for a long time. Very grateful to everyone for this. ❤️

@pytimer
Copy link
Contributor Author

pytimer commented Apr 25, 2022

@ubogdan How can i rerun github Actions and codecov?

@ubogdan
Copy link
Contributor

ubogdan commented Apr 26, 2022

Good job. Please resolve conflicts.

@pytimer
Copy link
Contributor Author

pytimer commented Apr 27, 2022

@ubogdan solve conflicts, please review it, thanks.

@ubogdan
Copy link
Contributor

ubogdan commented Apr 27, 2022

Looks like code coverage is still failing :(

@pytimer
Copy link
Contributor Author

pytimer commented Apr 27, 2022

Maybe i merge master branch code, add test code in the latest commit.

@pytimer
Copy link
Contributor Author

pytimer commented May 8, 2022

Please rerun test codecov, thanks.

@pytimer
Copy link
Contributor Author

pytimer commented May 9, 2022

@ubogdan Can you tell me how to fix codecov/patch, i don't understand where the problem, thanks.

@ubogdan
Copy link
Contributor

ubogdan commented May 10, 2022

Maybe you need to write unit tests this parts of the code: https://github.com/swaggo/swag/pull/1108/checks?check_run_id=6346809522? if possible...

@ivanpk
Copy link

ivanpk commented May 16, 2022

Do we have any ETA regarding the required changes? What can others do to help get this in?

time ../../pytimer/swag/cmd/swag/swag init -d {directory names removed} --parseDependency --parseDepth 1 --output api/generated_docs

8.26s user 6.70s system 359% cpu 4.160 total

time swag init -d {directory names removed} --parseDependency --parseDepth 1 --output api/generated_docs

318.74s user 736.87s system 928% cpu 1:53.65 total

The performance difference is vast

Copy link
Contributor

@ubogdan ubogdan left a comment

Choose a reason for hiding this comment

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

LGTM

@ubogdan
Copy link
Contributor

ubogdan commented May 18, 2022

y ETA regarding the required changes

We will try to include this in the next release. I was hoping we would get better code coverage.

@ubogdan ubogdan merged commit 5f6b402 into swaggo:master May 18, 2022
@g1eny0ung
Copy link

g1eny0ung commented Jun 16, 2022

@ubogdan Can we release a new version? It's been a long time since this PR was merged. 😢

@ubogdan
Copy link
Contributor

ubogdan commented Jun 16, 2022

released in v1.8.3

@g1eny0ung
Copy link

released in v1.8.3

Many thanks!

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.

Slow performance when generating spec with external dependencies
7 participants