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

proposal: Go 2: compiler chosen constants - make(const, <min>, <max>) #36972

Closed
mattharrigan opened this issue Feb 2, 2020 · 9 comments
Closed
Labels
FrozenDueToAge LanguageChange Suggested changes to the Go language Proposal v2 An incompatible library change
Milestone

Comments

@mattharrigan
Copy link

I propose adding compiler chosen constants. The use case is for constants that do not impact program correctness but do impact program performance. Some specific examples where this may be useful:

  • I recently watched a Gophercon video which had two implementations for the same function, one using a linear search and another using a map. For "small" problems a linear search is often faster. The threshold which defines "small" can be hard to nail down, usually requiring quite a bit of manual benchmarking. Worse is that the number will likely change in future go releases or on different platforms. Explicitly telling the compiler that it can choose that threshold enables to compiler to do the hard work.
  • The size of a buffer is another item that may be arbitrary from a program correctness perspective but very important from a performance perspective.
  • The number of worker goroutines.
  • The initial size and growth rates of data structures

I propose adding the capability to explicitly let the compiler choose the value of a constant. The programmer promises to ensure the program is correct regardless of the value. The compiler promises to choose the best value it can from a performance perspective. A trivial implementation could simply choose the midpoint. A much more complex implementation could estimate the cost of various values, perform actual benchmarking, or even produce code that determines the optimal value at runtime. The implementation could mature over time and the user would only notice improved performance.

One possible syntax is make(const, <min>, <max>). For the first example above, it could be const linearSearchThreshold = make(const, 0, 100). I think that would be readily understood and consistent with go, but there are certainly variations possible.

I believe this proposal is consistent with the go philosophy. The proposed feature is quite simple for a user of the language. It doesn't add any new keywords and may only take a sentence in the spec to explain. It also hides a significant amount of complexity from the user, somewhat like the garbage collector or the scheduler. It builds upon one of go's more interesting language features, const. Finally I believe it is orthogonal to the other language features.

Thank you for your time and consideration.

@agnivade agnivade changed the title compiler chosen constants - make(const, <min>, <max>) proposal: compiler chosen constants - make(const, <min>, <max>) Feb 2, 2020
@gopherbot gopherbot added this to the Proposal milestone Feb 2, 2020
@chewxy
Copy link

chewxy commented Feb 2, 2020

I ran into a similar issue once upon a time - I was doing NLP work and depending on the context, the package I wrote could use a "small" set feature or a "large" set feature (leading to this).

The solution I ended up with was to use build tags to guard the library. It was not a very pretty solution. But I'm not sure if this proposal would work well.

The problem it seems, is that you need to provide alternatives, which would be hard to specify

@josharian
Copy link
Contributor

Related: #24204.

Another possible syntax is just plain make([]byte). That is currently rejected as requiring a length, so it would be backwards compatible.

Note that I can't imagine many cases in which the compiler/runtime could make good use of this freedom right now or in the foreseeable future. You'd need FGO/PGO (#28262) for this to be really useful.

@dpinela
Copy link
Contributor

dpinela commented Feb 2, 2020

The compiler promises to choose the best value it can from a performance perspective. A trivial implementation could simply choose the midpoint. A much more complex implementation could estimate the cost of various values, perform actual benchmarking, or even produce code that determines the optimal value at runtime. The implementation could mature over time and the user would only notice improved performance.

What you're suggesting is, I think, best accomplished by writing a problem-specific tool that does whatever benchmarks it needs and computes an optimal value for your constant. There is no reasonable way for the compiler to do either of these things for you; both require understanding of the implementation and the problem it is meant to solve, which only the programmer has.

@DeedleFake
Copy link

DeedleFake commented Feb 3, 2020

Not to bikeshed too much, especially given that other problems have already been mentioned here, but I don't think the syntax makes sense, for two primary reasons:

  • make() is a pseudo-function that performs operations at runtime. I don't think it makes sense to use as a compile-time directive.
  • const is a keyword. Given how it is currently handled by the parser, I don't think that it makes a lot of sense to use it as a psuedo-type, even in a fake make() call.

@ianlancetaylor ianlancetaylor changed the title proposal: compiler chosen constants - make(const, <min>, <max>) proposal: Go 2: compiler chosen constants - make(const, <min>, <max>) Feb 3, 2020
@ianlancetaylor ianlancetaylor added v2 An incompatible library change LanguageChange Suggested changes to the Go language labels Feb 3, 2020
@mattharrigan
Copy link
Author

@dpinela go already has a very nice standard benchmark. The go tool chain could guess a value for the constant, run the benchmark, guess another value, run the benchmark, and repeat in a descent search algorithm. None of that is really problem specific. It only requires a standard benchmark, which you should have already if you really care about performance this much.

@mattharrigan
Copy link
Author

the syntax is admittedly a crude first stab at it. i think is should be very clear that it is compiler chosen, which make([]byte) is not to me at least. i think it should be limited to constants over a given range to limit the overall search space and complexity

@mattharrigan
Copy link
Author

@DeedleFake

make() is a pseudo-function that performs operations at runtime. I don't think it makes sense to use as a compile-time directive.

It may not be a compile time directive. It could be, or the compiler could decide to compute it at runtime with a function chosen by the compiler. Those are implementation details.

@ianlancetaylor
Copy link
Member

It's hard to understand how to use this without telling the compiler a specific implementation to test, or perhaps two different implementations to choose between. A syntax like make(const, min, max) doesn't tell the compiler on what basis it should choose the constant.

This is related to compiler optimizations that use profiling feedback to choose expected values of constants. But those optimizations do not require language changes. In general this seems like a mechanism that should live outside the language proper. The language can't easily provide the knobs that the compiler would need to use. There needs to be a system outside the compiler. For that we don't need a language change.

@mattharrigan
Copy link
Author

Good points. Thank you for your time and consideration.

@golang golang locked and limited conversation to collaborators Feb 22, 2021
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
FrozenDueToAge LanguageChange Suggested changes to the Go language Proposal v2 An incompatible library change
Projects
None yet
Development

No branches or pull requests

7 participants