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

go-fuzz-build: use go/packages #211

Merged
merged 5 commits into from
Mar 1, 2019
Merged

Conversation

josharian
Copy link
Collaborator

golang.org/x/tools/go/packages is a new package designed to aid in
locating, parsing, and typechecking Go packages.
This change updates go-fuzz-build to use it.
This effectively resulted in a rewrite of go-fuzz-build/main.go.

Some benefits are:

  • Improved performance. go-fuzz-build appears to be 2x faster on
    first build, and 4x faster on subsequent builds.
    This is due to several factors. One big one is the use of cached
    type information.
    And there are more performance improvements available;
    see the TODOs in the code.

  • More robust. Previously, the list of ignored packages had to be
    updated every time the standard library changed.
    Now the ignored packages are computed on the fly.

  • More user-friendly. You can now invoke go-fuzz-build without
    a package path; it assumes ".", and relative paths work seamlessly.

  • Closer to functionality in a module-enabled world.
    See the TODOs in the code.

  • Simpler and better documented.

Outstanding issue:

  • cgo code is not instrumented.
    See the discussion and linked Go toolchain issue in the code.

Implementation notes:

  • go-fuzz-defs has been split into two.
    The constants, which are shared across go-fuzz, go-fuzz-build,
    and instrumented code, have been left in place.
    The types, which were only needed by go-fuzz and go-fuzz-build,
    have been moved to a new internal package.
    This allowed us to break the go-fuzz-dep/go-fuzz-defs dependency
    and std-depends-on-non-std problems in a simpler way:
    We simply make another copy of go-fuzz-defs.
    See the comments in the code for details.

  • There is now a shared AST across the coverage and sonar passes.
    This works out OK, since the sonar pass used to request coverage first.
    Now we just have to be careful about the order in which we use and
    mutate the AST. This is well documented in the code.

@josharian
Copy link
Collaborator Author

This has not been tested on Windows yet. (I'm working on it, but my access to Windows machines is very limited. I'd love help testing on Windows, if anyone wants to chip in.) But I wanted to get this up to start the review, since it is a very large change.

golang.org/x/tools/go/packages is a new package designed to aid in
locating, parsing, and typechecking Go packages.
This change updates go-fuzz-build to use it.
This effectively resulted in a rewrite of go-fuzz-build/main.go.


Some benefits are:

* Improved performance. go-fuzz-build appears to be 2x faster on
  first build, and 4x faster on subsequent builds.
  This is due to several factors. One big one is the use of cached
  type information.
  And there are more performance improvements available;
  see the TODOs in the code.

* More robust. Previously, the list of ignored packages had to be
  updated every time the standard library changed.
  Now the ignored packages are computed on the fly.

* More user-friendly. You can now invoke go-fuzz-build without
  a package path; it assumes ".", and relative paths work seamlessly.

* Closer to functionality in a module-enabled world.
  See the TODOs in the code.

* Simpler and better documented.


Outstanding issue:

* cgo code is not instrumented.
  See the discussion and linked Go toolchain issue in the code.


Implementation notes:

* go-fuzz-defs has been split into two.
  The constants, which are shared across go-fuzz, go-fuzz-build,
  and instrumented code, have been left in place.
  The types, which were only needed by go-fuzz and go-fuzz-build,
  have been moved to a new internal package.
  This allowed us to break the go-fuzz-dep/go-fuzz-defs dependency
  and std-depends-on-non-std problems in a simpler way:
  We simply make another copy of go-fuzz-defs.
  See the comments in the code for details.

* There is now a shared AST across the coverage and sonar passes.
  This works out OK, since the sonar pass used to request coverage first.
  Now we just have to be careful about the order in which we use and
  mutate the AST. This is well documented in the code.
@josharian
Copy link
Collaborator Author

Basic Windows testing done; one bug found and fixed. I don't plan to do further Windows testing at this point, although further help and bug reports are of course welcome.

This makes go-fuzz a little easier to use;
one fewer flag to set.
This is what go-fuzz-corpus uses, and I have used elsewhere.
One fewer required flag to set when using go-fuzz.
@josharian
Copy link
Collaborator Author

I've added on a few bonus commits. :)

And now I'll stop messing with this until I have some review feedback.

@dvyukov
Copy link
Owner

dvyukov commented Mar 1, 2019

it assumes ".", and relative paths work seamlessly

my favorite feature

cgo code is not instrumented

this is not a regression, right?

the list of ignored packages had to be updated every time the standard library changed

this was annoying

// It's a non-trivial part of build time.
// Question: Do it here or in copyDir?

// TODO: consider using hard links for
Copy link
Owner

Choose a reason for hiding this comment

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

I think this can't work across mounts, and /tmp is frequently a different mount.

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Ack. Will remove that comment in a follow-up.

do := func(fn func()) {
wg.Add(1)
sem <- 0
fn()
Copy link
Owner

Choose a reason for hiding this comment

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

Wait, shouldn't this include go somewhere? ;)

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Ouch. :P That's what I get for refactoring while benchmarking.

I just re-benchmarked with higher N (with go!) and can't reproduce the speedup. I'll force push this branch to remove this commit, at least for now.

@dvyukov
Copy link
Owner

dvyukov commented Mar 1, 2019

I read the code and I don't have any particular comments.
It's now better, with less hardcode.
I also did some basic testing, it works. Build is indeed much faster now.
So I will merge it later today in case somebody else wants to take a look.
Thanks!

@josharian
Copy link
Collaborator Author

cgo code is not instrumented

this is not a regression, right?

Right. I just had high hopes that go/packages would help here.

Dmitry pointed out during code review
that hard links won't work across mounts,
and that /tmp is often a mount,
so it probably isn't worth the code to try
and then fall back.
@josharian
Copy link
Collaborator Author

Force push replaced my broken concurrent-I/O commit and replaced it with a hard links comment tweak. Thanks for the speedy review, Dmitry.

@dvyukov dvyukov merged commit 3246052 into dvyukov:master Mar 1, 2019
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.

2 participants