proto/equal: reduce equal scalar value allocation
Instead of lifting values to interface and then do equality test,
compare scalar values with defined types to reduce allocation
from interface.
Change-Id: Ieb777fbd1a48c83d896d0ebe6ad605433f44c16c
Reviewed-on: https://go-review.googlesource.com/c/protobuf/+/253100
Reviewed-by: Joe Tsai <thebrokentoaster@gmail.com>
Trust: Damien Neil <dneil@google.com>
Trust: Joe Tsai <thebrokentoaster@gmail.com>
diff --git a/proto/equal.go b/proto/equal.go
index 10902bd..4dba2b9 100644
--- a/proto/equal.go
+++ b/proto/equal.go
@@ -111,18 +111,31 @@
// equalValue compares two singular values.
func equalValue(fd pref.FieldDescriptor, x, y pref.Value) bool {
- switch {
- case fd.Message() != nil:
- return equalMessage(x.Message(), y.Message())
- case fd.Kind() == pref.BytesKind:
- return bytes.Equal(x.Bytes(), y.Bytes())
- case fd.Kind() == pref.FloatKind, fd.Kind() == pref.DoubleKind:
+ switch fd.Kind() {
+ case pref.BoolKind:
+ return x.Bool() == y.Bool()
+ case pref.EnumKind:
+ return x.Enum() == y.Enum()
+ case pref.Int32Kind, pref.Sint32Kind,
+ pref.Int64Kind, pref.Sint64Kind,
+ pref.Sfixed32Kind, pref.Sfixed64Kind:
+ return x.Int() == y.Int()
+ case pref.Uint32Kind, pref.Uint64Kind,
+ pref.Fixed32Kind, pref.Fixed64Kind:
+ return x.Uint() == y.Uint()
+ case pref.FloatKind, pref.DoubleKind:
fx := x.Float()
fy := y.Float()
if math.IsNaN(fx) || math.IsNaN(fy) {
return math.IsNaN(fx) && math.IsNaN(fy)
}
return fx == fy
+ case pref.StringKind:
+ return x.String() == y.String()
+ case pref.BytesKind:
+ return bytes.Equal(x.Bytes(), y.Bytes())
+ case pref.MessageKind, pref.GroupKind:
+ return equalMessage(x.Message(), y.Message())
default:
return x.Interface() == y.Interface()
}
diff --git a/proto/equal_test.go b/proto/equal_test.go
index 8d85397..2def30f 100644
--- a/proto/equal_test.go
+++ b/proto/equal_test.go
@@ -41,18 +41,15 @@
x: new(testpb.TestAllTypes),
y: new(testpb.TestAllTypes),
eq: true,
- },
- {
+ }, {
x: (*testpb.TestAllTypes)(nil),
y: (*testpb.TestAllExtensions)(nil),
eq: false,
- },
- {
+ }, {
x: (*testpb.TestAllTypes)(nil),
y: new(testpb.TestAllExtensions),
eq: false,
- },
- {
+ }, {
x: new(testpb.TestAllTypes),
y: new(testpb.TestAllExtensions),
eq: false,
@@ -113,6 +110,78 @@
}, {
x: &testpb.TestAllTypes{OptionalNestedEnum: testpb.TestAllTypes_FOO.Enum()},
y: &testpb.TestAllTypes{OptionalNestedEnum: testpb.TestAllTypes_BAR.Enum()},
+ }, {
+ x: &testpb.TestAllTypes{OptionalInt32: proto.Int32(2)},
+ y: &testpb.TestAllTypes{OptionalInt32: proto.Int32(2)},
+ eq: true,
+ }, {
+ x: &testpb.TestAllTypes{OptionalInt64: proto.Int64(2)},
+ y: &testpb.TestAllTypes{OptionalInt64: proto.Int64(2)},
+ eq: true,
+ }, {
+ x: &testpb.TestAllTypes{OptionalUint32: proto.Uint32(2)},
+ y: &testpb.TestAllTypes{OptionalUint32: proto.Uint32(2)},
+ eq: true,
+ }, {
+ x: &testpb.TestAllTypes{OptionalUint64: proto.Uint64(2)},
+ y: &testpb.TestAllTypes{OptionalUint64: proto.Uint64(2)},
+ eq: true,
+ }, {
+ x: &testpb.TestAllTypes{OptionalSint32: proto.Int32(2)},
+ y: &testpb.TestAllTypes{OptionalSint32: proto.Int32(2)},
+ eq: true,
+ }, {
+ x: &testpb.TestAllTypes{OptionalSint64: proto.Int64(2)},
+ y: &testpb.TestAllTypes{OptionalSint64: proto.Int64(2)},
+ eq: true,
+ }, {
+ x: &testpb.TestAllTypes{OptionalFixed32: proto.Uint32(2)},
+ y: &testpb.TestAllTypes{OptionalFixed32: proto.Uint32(2)},
+ eq: true,
+ }, {
+ x: &testpb.TestAllTypes{OptionalFixed64: proto.Uint64(2)},
+ y: &testpb.TestAllTypes{OptionalFixed64: proto.Uint64(2)},
+ eq: true,
+ }, {
+ x: &testpb.TestAllTypes{OptionalSfixed32: proto.Int32(2)},
+ y: &testpb.TestAllTypes{OptionalSfixed32: proto.Int32(2)},
+ eq: true,
+ }, {
+ x: &testpb.TestAllTypes{OptionalSfixed64: proto.Int64(2)},
+ y: &testpb.TestAllTypes{OptionalSfixed64: proto.Int64(2)},
+ eq: true,
+ }, {
+ x: &testpb.TestAllTypes{OptionalFloat: proto.Float32(2)},
+ y: &testpb.TestAllTypes{OptionalFloat: proto.Float32(2)},
+ eq: true,
+ }, {
+ x: &testpb.TestAllTypes{OptionalDouble: proto.Float64(2)},
+ y: &testpb.TestAllTypes{OptionalDouble: proto.Float64(2)},
+ eq: true,
+ }, {
+ x: &testpb.TestAllTypes{OptionalFloat: proto.Float32(float32(math.NaN()))},
+ y: &testpb.TestAllTypes{OptionalFloat: proto.Float32(float32(math.NaN()))},
+ eq: true,
+ }, {
+ x: &testpb.TestAllTypes{OptionalDouble: proto.Float64(float64(math.NaN()))},
+ y: &testpb.TestAllTypes{OptionalDouble: proto.Float64(float64(math.NaN()))},
+ eq: true,
+ }, {
+ x: &testpb.TestAllTypes{OptionalBool: proto.Bool(true)},
+ y: &testpb.TestAllTypes{OptionalBool: proto.Bool(true)},
+ eq: true,
+ }, {
+ x: &testpb.TestAllTypes{OptionalString: proto.String("abc")},
+ y: &testpb.TestAllTypes{OptionalString: proto.String("abc")},
+ eq: true,
+ }, {
+ x: &testpb.TestAllTypes{OptionalBytes: []byte("abc")},
+ y: &testpb.TestAllTypes{OptionalBytes: []byte("abc")},
+ eq: true,
+ }, {
+ x: &testpb.TestAllTypes{OptionalNestedEnum: testpb.TestAllTypes_FOO.Enum()},
+ y: &testpb.TestAllTypes{OptionalNestedEnum: testpb.TestAllTypes_FOO.Enum()},
+ eq: true,
},
// Proto2 presence.