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

cmd/compile: optimize compile speed by checking public symbol #15569

Closed
fishedee opened this issue May 6, 2016 · 9 comments
Closed

cmd/compile: optimize compile speed by checking public symbol #15569

fishedee opened this issue May 6, 2016 · 9 comments

Comments

@fishedee
Copy link

fishedee commented May 6, 2016

cmd/compile: optimize compile speed by checking public symbol

Please answer these questions before submitting your issue. Thanks!

  1. What version of Go are you using (go version)?
➜  server git:(master) ✗ go version
go version go1.6.2 darwin/amd64
  1. What operating system and processor architecture are you using (go env)?
➜  server git:(master) ✗ go env
GOARCH="amd64"
GOBIN=""
GOEXE=""
GOHOSTARCH="amd64"
GOHOSTOS="darwin"
GOOS="darwin"
GOPATH="/Users/fish/Project/fishgo/"
GORACE=""
GOROOT="/usr/local/go"
GOTOOLDIR="/usr/local/go/pkg/tool/darwin_amd64"
GO15VENDOREXPERIMENT="1"
CC="clang"
GOGCCFLAGS="-fPIC -m64 -pthread -fno-caret-diagnostics -Qunused-arguments -fmessage-length=0 -fno-common"
CXX="clang++"
CGO_ENABLED="1"
  1. What did you do?
    If possible, provide a recipe for reproducing the error.
    A complete runnable program is good.
    A link on play.golang.org is best.
//$GOPATH/gotest/main.go
package main

import (
    "gotest/util"
)

func main() {
    util.Do()
}

I write a main.go

//$GOPATH/gotest/util/util.go
package util

import (
    "gotest/util2"
)

func Do() {
    a := util2.GetMM()
    a.Do()
}

I write a util/util.go

//$GOPATH/gotest/util2/util2.go
package util2

import (
    "fmt"
)

type MM interface {
    Do()
}

type mmInpement struct {
}

func (this *mmInpement) Do() {
    fmt.Println("uu4")
}

func GetMM() MM {
    return &mmInpement{}
}

I write a util2/util2.go

//$GOPATH/gotest/util2/util2.go
package util2

import (
    "fmt"
)

type MM interface {
    Do()
}

type mmInpement struct {
}

func (this *mmInpement) Do() {
    //i only change this code
    fmt.Println("dd")
}

func GetMM() MM {
    return &mmInpement{}
}

And Now, I just modify mmInpement code

➜  gotest git:(compile) go install -v gotest
gotest/util2
gotest/util
gotest

util2.go never modify it's public symbol and interface, it just modify implement,but all file which depend on util2.go will recompile

  1. What did you expect to see?
➜  gotest git:(compile) go install -v gotest
gotest/util2
gotest
  1. What did you see instead?
➜  gotest git:(compile) go install -v gotest
gotest/util2
gotest/util
gotest

I think the compiler should improve the compilation speed by checking whether the depend interface is changed.If the depend package is only changed implement, without changing the interface, then the package should not be re compiled.

We now have a relatively large project, when we modify the bottom module(just modify implement,no interface), all of the file depend on this module will be re compiled, resulting in a very very slow compile time

@minux
Copy link
Member

minux commented May 6, 2016 via email

@fishedee
Copy link
Author

fishedee commented May 6, 2016

When util2 compile ,it will generate a file name util2.symbol which contains all util2 public symbol

NextTime when util2 source change,generate a new util2.symbol

If the new util2.symbol is equal to old util2.symbol, never recompile util.go and never generate util.a

@fishedee
Copy link
Author

fishedee commented May 6, 2016

You can looing at util.go ,but no need to generate util.a

@kostya-sh
Copy link
Contributor

There are some changes that do not change public symbols and won't be visible without re-compilation.

A bit artificial example: https://play.golang.org/p/_OL9rbTUpM vs https://play.golang.org/p/Rbg4Z94bAA (public symbols stayed the same but value of Y is different). I am sure that this is not the only example.

@fishedee
Copy link
Author

fishedee commented May 6, 2016

@kostya-sh Because Y is a constants,so Y name and value will write to util.symbol,so if Y name or value change, public symbol is change too。
Could You give more example except constants

@minux
Copy link
Member

minux commented May 6, 2016 via email

@bradfitz
Copy link
Contributor

I agree with @minux. I don't think we're going to do anything here.

Others are working on many aspects of the compiler speed already.

@neelance
Copy link
Member

neelance commented Jun 2, 2016

Isn't it true that a package's output only depends on its source files and the export data of its dependencies? So if a dependency's source code changes, but the export data stays the same, then the output of the current package would also stay the same? Because the compiler still has the same input. It can't be that simple, but right now it sounds to me like a checksum across the export data could do the trick.

@minux I see your point with the inlined function. However, does the compiler do cross-package inlining at the compile step or at the linker step?

@ianlancetaylor
Copy link
Contributor

@neelance We try to avoid holding discussions on closed issues where nobody will see them. This is a good topic for the golang-dev mailing list. Thanks.

@golang golang locked and limited conversation to collaborators Jun 2, 2017
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
None yet
Development

No branches or pull requests

7 participants