mirror of
https://github.com/protocolbuffers/protobuf-go.git
synced 2025-04-16 08:42:29 +00:00
reflect/prototype: lower minimum support to Go1.9
The minimum supported version is currently Go1.10 since we use strings.Builder for a fairly significant optimization when constructing all of the descriptor full names. The strings.Builder implementation is not particularly complicated, so just fork it into our code. The golang/protobuf and the golang/go projects share the same authors and copyright license. Change-Id: Ibb9519dbe756327a07369f10f80c15761002b5e7 Reviewed-on: https://go-review.googlesource.com/136735 Reviewed-by: Damien Neil <dneil@google.com>
This commit is contained in:
parent
a6c374a8f1
commit
ded92f8033
@ -7,6 +7,7 @@
|
|||||||
package main
|
package main
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"bytes"
|
||||||
"flag"
|
"flag"
|
||||||
"go/format"
|
"go/format"
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
@ -105,8 +106,8 @@ var listTypesTemplate = template.Must(template.New("").Funcs(template.FuncMap{
|
|||||||
|
|
||||||
func (p *{{$nameListMeta}}) lazyInit(parent protoreflect.Descriptor, ts []{{.}}) *{{$nameList}} {
|
func (p *{{$nameListMeta}}) lazyInit(parent protoreflect.Descriptor, ts []{{.}}) *{{$nameList}} {
|
||||||
p.once.Do(func() {
|
p.once.Do(func() {
|
||||||
nb := nameBuilderPool.Get().(*nameBuilder)
|
nb := getNameBuilder()
|
||||||
defer nameBuilderPool.Put(nb)
|
defer putNameBuilder(nb)
|
||||||
metas := make([]{{$nameMeta}}, len(ts))
|
metas := make([]{{$nameMeta}}, len(ts))
|
||||||
for i := range ts {
|
for i := range ts {
|
||||||
t := &ts[i]
|
t := &ts[i]
|
||||||
@ -185,11 +186,11 @@ var listTypesTemplate = template.Must(template.New("").Funcs(template.FuncMap{
|
|||||||
`))
|
`))
|
||||||
|
|
||||||
func mustExecute(t *template.Template, data interface{}) string {
|
func mustExecute(t *template.Template, data interface{}) string {
|
||||||
var sb strings.Builder
|
var b bytes.Buffer
|
||||||
if err := t.Execute(&sb, data); err != nil {
|
if err := t.Execute(&b, data); err != nil {
|
||||||
panic(err)
|
panic(err)
|
||||||
}
|
}
|
||||||
return sb.String()
|
return b.String()
|
||||||
}
|
}
|
||||||
|
|
||||||
func writeSource(file, src string) {
|
func writeSource(file, src string) {
|
||||||
|
19
reflect/prototype/name_pure.go
Normal file
19
reflect/prototype/name_pure.go
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
// Copyright 2018 The Go Authors. All rights reserved.
|
||||||
|
// Use of this source code is governed by a BSD-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
// +build purego
|
||||||
|
|
||||||
|
package prototype
|
||||||
|
|
||||||
|
import pref "google.golang.org/proto/reflect/protoreflect"
|
||||||
|
|
||||||
|
func getNameBuilder() *nameBuilder { return nil }
|
||||||
|
func putNameBuilder(*nameBuilder) {}
|
||||||
|
|
||||||
|
type nameBuilder struct{}
|
||||||
|
|
||||||
|
// Append is equivalent to protoreflect.FullName.Append.
|
||||||
|
func (*nameBuilder) Append(prefix pref.FullName, name pref.Name) pref.FullName {
|
||||||
|
return prefix.Append(name)
|
||||||
|
}
|
99
reflect/prototype/name_unsafe.go
Normal file
99
reflect/prototype/name_unsafe.go
Normal file
@ -0,0 +1,99 @@
|
|||||||
|
// Copyright 2018 The Go Authors. All rights reserved.
|
||||||
|
// Use of this source code is governed by a BSD-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
// +build !purego
|
||||||
|
|
||||||
|
package prototype
|
||||||
|
|
||||||
|
import (
|
||||||
|
"strings"
|
||||||
|
"sync"
|
||||||
|
"unsafe"
|
||||||
|
|
||||||
|
pref "google.golang.org/proto/reflect/protoreflect"
|
||||||
|
)
|
||||||
|
|
||||||
|
var nameBuilderPool = sync.Pool{
|
||||||
|
New: func() interface{} { return new(nameBuilder) },
|
||||||
|
}
|
||||||
|
|
||||||
|
func getNameBuilder() *nameBuilder {
|
||||||
|
return nameBuilderPool.Get().(*nameBuilder)
|
||||||
|
}
|
||||||
|
func putNameBuilder(b *nameBuilder) {
|
||||||
|
nameBuilderPool.Put(b)
|
||||||
|
}
|
||||||
|
|
||||||
|
type nameBuilder struct {
|
||||||
|
sb stringBuilder
|
||||||
|
}
|
||||||
|
|
||||||
|
// Append is equivalent to protoreflect.FullName.Append, but is optimized for
|
||||||
|
// large batches of operations where each name has a shared lifetime.
|
||||||
|
func (b *nameBuilder) Append(prefix pref.FullName, name pref.Name) pref.FullName {
|
||||||
|
const batchSize = 1 << 12
|
||||||
|
n := len(prefix) + len(".") + len(name)
|
||||||
|
if b.sb.Cap()-b.sb.Len() < n {
|
||||||
|
b.sb.Reset()
|
||||||
|
b.sb.Grow(batchSize)
|
||||||
|
}
|
||||||
|
if !strings.HasSuffix(b.sb.String(), string(prefix)) {
|
||||||
|
b.sb.WriteString(string(prefix))
|
||||||
|
}
|
||||||
|
b.sb.WriteByte('.')
|
||||||
|
b.sb.WriteString(string(name))
|
||||||
|
s := b.sb.String()
|
||||||
|
return pref.FullName(strings.TrimPrefix(s[len(s)-n:], "."))
|
||||||
|
}
|
||||||
|
|
||||||
|
// stringsBuilder is a simplified copy of the strings.Builder from Go1.12:
|
||||||
|
// * removed the shallow copy check
|
||||||
|
// * removed methods that we do not use (e.g. WriteRune)
|
||||||
|
//
|
||||||
|
// A forked version is used:
|
||||||
|
// * to enable Go1.9 support, but strings.Builder was added in Go1.10
|
||||||
|
// * for the Cap method, which was missing until Go1.12
|
||||||
|
//
|
||||||
|
// TODO: Remove this when Go1.12 is the minimally supported toolchain version.
|
||||||
|
type stringBuilder struct {
|
||||||
|
buf []byte
|
||||||
|
}
|
||||||
|
|
||||||
|
func (b *stringBuilder) String() string {
|
||||||
|
return *(*string)(unsafe.Pointer(&b.buf))
|
||||||
|
}
|
||||||
|
func (b *stringBuilder) Len() int {
|
||||||
|
return len(b.buf)
|
||||||
|
}
|
||||||
|
func (b *stringBuilder) Cap() int {
|
||||||
|
return cap(b.buf)
|
||||||
|
}
|
||||||
|
func (b *stringBuilder) Reset() {
|
||||||
|
b.buf = nil
|
||||||
|
}
|
||||||
|
func (b *stringBuilder) grow(n int) {
|
||||||
|
buf := make([]byte, len(b.buf), 2*cap(b.buf)+n)
|
||||||
|
copy(buf, b.buf)
|
||||||
|
b.buf = buf
|
||||||
|
}
|
||||||
|
func (b *stringBuilder) Grow(n int) {
|
||||||
|
if n < 0 {
|
||||||
|
panic("stringBuilder.Grow: negative count")
|
||||||
|
}
|
||||||
|
if cap(b.buf)-len(b.buf) < n {
|
||||||
|
b.grow(n)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
func (b *stringBuilder) Write(p []byte) (int, error) {
|
||||||
|
b.buf = append(b.buf, p...)
|
||||||
|
return len(p), nil
|
||||||
|
}
|
||||||
|
func (b *stringBuilder) WriteByte(c byte) error {
|
||||||
|
b.buf = append(b.buf, c)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
func (b *stringBuilder) WriteString(s string) (int, error) {
|
||||||
|
b.buf = append(b.buf, s...)
|
||||||
|
return len(s), nil
|
||||||
|
}
|
@ -24,8 +24,8 @@ type messages messagesMeta
|
|||||||
|
|
||||||
func (p *messagesMeta) lazyInit(parent protoreflect.Descriptor, ts []Message) *messages {
|
func (p *messagesMeta) lazyInit(parent protoreflect.Descriptor, ts []Message) *messages {
|
||||||
p.once.Do(func() {
|
p.once.Do(func() {
|
||||||
nb := nameBuilderPool.Get().(*nameBuilder)
|
nb := getNameBuilder()
|
||||||
defer nameBuilderPool.Put(nb)
|
defer putNameBuilder(nb)
|
||||||
metas := make([]messageMeta, len(ts))
|
metas := make([]messageMeta, len(ts))
|
||||||
for i := range ts {
|
for i := range ts {
|
||||||
t := &ts[i]
|
t := &ts[i]
|
||||||
@ -74,8 +74,8 @@ type fields fieldsMeta
|
|||||||
|
|
||||||
func (p *fieldsMeta) lazyInit(parent protoreflect.Descriptor, ts []Field) *fields {
|
func (p *fieldsMeta) lazyInit(parent protoreflect.Descriptor, ts []Field) *fields {
|
||||||
p.once.Do(func() {
|
p.once.Do(func() {
|
||||||
nb := nameBuilderPool.Get().(*nameBuilder)
|
nb := getNameBuilder()
|
||||||
defer nameBuilderPool.Put(nb)
|
defer putNameBuilder(nb)
|
||||||
metas := make([]fieldMeta, len(ts))
|
metas := make([]fieldMeta, len(ts))
|
||||||
for i := range ts {
|
for i := range ts {
|
||||||
t := &ts[i]
|
t := &ts[i]
|
||||||
@ -157,8 +157,8 @@ type oneofs oneofsMeta
|
|||||||
|
|
||||||
func (p *oneofsMeta) lazyInit(parent protoreflect.Descriptor, ts []Oneof) *oneofs {
|
func (p *oneofsMeta) lazyInit(parent protoreflect.Descriptor, ts []Oneof) *oneofs {
|
||||||
p.once.Do(func() {
|
p.once.Do(func() {
|
||||||
nb := nameBuilderPool.Get().(*nameBuilder)
|
nb := getNameBuilder()
|
||||||
defer nameBuilderPool.Put(nb)
|
defer putNameBuilder(nb)
|
||||||
metas := make([]oneofMeta, len(ts))
|
metas := make([]oneofMeta, len(ts))
|
||||||
for i := range ts {
|
for i := range ts {
|
||||||
t := &ts[i]
|
t := &ts[i]
|
||||||
@ -203,8 +203,8 @@ type extensions extensionsMeta
|
|||||||
|
|
||||||
func (p *extensionsMeta) lazyInit(parent protoreflect.Descriptor, ts []Extension) *extensions {
|
func (p *extensionsMeta) lazyInit(parent protoreflect.Descriptor, ts []Extension) *extensions {
|
||||||
p.once.Do(func() {
|
p.once.Do(func() {
|
||||||
nb := nameBuilderPool.Get().(*nameBuilder)
|
nb := getNameBuilder()
|
||||||
defer nameBuilderPool.Put(nb)
|
defer putNameBuilder(nb)
|
||||||
metas := make([]extensionMeta, len(ts))
|
metas := make([]extensionMeta, len(ts))
|
||||||
for i := range ts {
|
for i := range ts {
|
||||||
t := &ts[i]
|
t := &ts[i]
|
||||||
@ -249,8 +249,8 @@ type enums enumsMeta
|
|||||||
|
|
||||||
func (p *enumsMeta) lazyInit(parent protoreflect.Descriptor, ts []Enum) *enums {
|
func (p *enumsMeta) lazyInit(parent protoreflect.Descriptor, ts []Enum) *enums {
|
||||||
p.once.Do(func() {
|
p.once.Do(func() {
|
||||||
nb := nameBuilderPool.Get().(*nameBuilder)
|
nb := getNameBuilder()
|
||||||
defer nameBuilderPool.Put(nb)
|
defer putNameBuilder(nb)
|
||||||
metas := make([]enumMeta, len(ts))
|
metas := make([]enumMeta, len(ts))
|
||||||
for i := range ts {
|
for i := range ts {
|
||||||
t := &ts[i]
|
t := &ts[i]
|
||||||
@ -297,8 +297,8 @@ type enumValues enumValuesMeta
|
|||||||
|
|
||||||
func (p *enumValuesMeta) lazyInit(parent protoreflect.Descriptor, ts []EnumValue) *enumValues {
|
func (p *enumValuesMeta) lazyInit(parent protoreflect.Descriptor, ts []EnumValue) *enumValues {
|
||||||
p.once.Do(func() {
|
p.once.Do(func() {
|
||||||
nb := nameBuilderPool.Get().(*nameBuilder)
|
nb := getNameBuilder()
|
||||||
defer nameBuilderPool.Put(nb)
|
defer putNameBuilder(nb)
|
||||||
metas := make([]enumValueMeta, len(ts))
|
metas := make([]enumValueMeta, len(ts))
|
||||||
for i := range ts {
|
for i := range ts {
|
||||||
t := &ts[i]
|
t := &ts[i]
|
||||||
@ -361,8 +361,8 @@ type services servicesMeta
|
|||||||
|
|
||||||
func (p *servicesMeta) lazyInit(parent protoreflect.Descriptor, ts []Service) *services {
|
func (p *servicesMeta) lazyInit(parent protoreflect.Descriptor, ts []Service) *services {
|
||||||
p.once.Do(func() {
|
p.once.Do(func() {
|
||||||
nb := nameBuilderPool.Get().(*nameBuilder)
|
nb := getNameBuilder()
|
||||||
defer nameBuilderPool.Put(nb)
|
defer putNameBuilder(nb)
|
||||||
metas := make([]serviceMeta, len(ts))
|
metas := make([]serviceMeta, len(ts))
|
||||||
for i := range ts {
|
for i := range ts {
|
||||||
t := &ts[i]
|
t := &ts[i]
|
||||||
@ -407,8 +407,8 @@ type methods methodsMeta
|
|||||||
|
|
||||||
func (p *methodsMeta) lazyInit(parent protoreflect.Descriptor, ts []Method) *methods {
|
func (p *methodsMeta) lazyInit(parent protoreflect.Descriptor, ts []Method) *methods {
|
||||||
p.once.Do(func() {
|
p.once.Do(func() {
|
||||||
nb := nameBuilderPool.Get().(*nameBuilder)
|
nb := getNameBuilder()
|
||||||
defer nameBuilderPool.Put(nb)
|
defer putNameBuilder(nb)
|
||||||
metas := make([]methodMeta, len(ts))
|
metas := make([]methodMeta, len(ts))
|
||||||
for i := range ts {
|
for i := range ts {
|
||||||
t := &ts[i]
|
t := &ts[i]
|
||||||
|
@ -578,33 +578,3 @@ func resolveReference(parent pref.Descriptor, refName pref.FullName) pref.Descri
|
|||||||
}
|
}
|
||||||
return cur
|
return cur
|
||||||
}
|
}
|
||||||
|
|
||||||
var nameBuilderPool = sync.Pool{
|
|
||||||
New: func() interface{} { return new(nameBuilder) },
|
|
||||||
}
|
|
||||||
|
|
||||||
type nameBuilder struct {
|
|
||||||
sb strings.Builder
|
|
||||||
|
|
||||||
// TODO: See https://golang.org/issue/26269
|
|
||||||
rem int // conservative approximation for Cap-Len
|
|
||||||
}
|
|
||||||
|
|
||||||
// Append is equivalent to protoreflect.FullName.Append, but is optimized for
|
|
||||||
// large batches of operations where each name has a shared lifetime.
|
|
||||||
func (b *nameBuilder) Append(prefix pref.FullName, name pref.Name) pref.FullName {
|
|
||||||
const batchSize = 1 << 12
|
|
||||||
n := len(prefix) + len(".") + len(name)
|
|
||||||
if b.rem < n {
|
|
||||||
b.sb.Reset()
|
|
||||||
b.sb.Grow(batchSize)
|
|
||||||
b.rem = batchSize - n
|
|
||||||
}
|
|
||||||
if !strings.HasSuffix(b.sb.String(), string(prefix)) {
|
|
||||||
b.sb.WriteString(string(prefix))
|
|
||||||
}
|
|
||||||
b.sb.WriteByte('.')
|
|
||||||
b.sb.WriteString(string(name))
|
|
||||||
s := b.sb.String()
|
|
||||||
return pref.FullName(strings.TrimPrefix(s[len(s)-n:], "."))
|
|
||||||
}
|
|
||||||
|
@ -38,7 +38,7 @@ ln -s ../google $PROTOBUF_DIR/src/include/google
|
|||||||
|
|
||||||
# Download each Go toolchain version.
|
# Download each Go toolchain version.
|
||||||
GO_LATEST=go1.11
|
GO_LATEST=go1.11
|
||||||
GO_VERSIONS=(go1.10.3 $GO_LATEST)
|
GO_VERSIONS=(go1.9.7 go1.10.3 $GO_LATEST)
|
||||||
for GO_VERSION in ${GO_VERSIONS[@]}; do
|
for GO_VERSION in ${GO_VERSIONS[@]}; do
|
||||||
if [ ! -d $GO_VERSION ]; then
|
if [ ! -d $GO_VERSION ]; then
|
||||||
print "download $GO_VERSION"
|
print "download $GO_VERSION"
|
||||||
|
Loading…
x
Reference in New Issue
Block a user