all: remove protoreflect.Message.Len
Len looks like it should be O(1), but the need to check for
non-zero-length repeated fields makes it at minimum O(n) where n is
the number of repeated fields. In practice, it's O(n) where n is the
number of fields altogether.
The Len function is not especially useful, easily duplicated with Range
and a counter, and can be surprisingly inefficient. Drop it.
Change-Id: I24b27433217e131e842bd18dd58475bcdf62ef97
Reviewed-on: https://go-review.googlesource.com/c/protobuf/+/183678
Reviewed-by: Joe Tsai <thebrokentoaster@gmail.com>
diff --git a/proto/encode.go b/proto/encode.go
index 87a0394..5139cce 100644
--- a/proto/encode.go
+++ b/proto/encode.go
@@ -145,7 +145,7 @@
m.Range(f)
return
}
- fds := make([]protoreflect.FieldDescriptor, 0, m.Len())
+ var fds []protoreflect.FieldDescriptor
m.Range(func(fd protoreflect.FieldDescriptor, _ protoreflect.Value) bool {
fds = append(fds, fd)
return true
diff --git a/proto/equal.go b/proto/equal.go
index 6f64434..1aca670 100644
--- a/proto/equal.go
+++ b/proto/equal.go
@@ -35,11 +35,10 @@
return false
}
- if mx.Len() != my.Len() {
- return false
- }
+ nx := 0
equal := true
mx.Range(func(fd pref.FieldDescriptor, vx pref.Value) bool {
+ nx++
vy := my.Get(fd)
equal = my.Has(fd) && equalField(fd, vx, vy)
return equal
@@ -47,6 +46,14 @@
if !equal {
return false
}
+ ny := 0
+ my.Range(func(fd pref.FieldDescriptor, vx pref.Value) bool {
+ ny++
+ return true
+ })
+ if nx != ny {
+ return false
+ }
return equalUnknown(mx.GetUnknown(), my.GetUnknown())
}
diff --git a/proto/reset_test.go b/proto/reset_test.go
index 9447df6..b9ad5b7 100644
--- a/proto/reset_test.go
+++ b/proto/reset_test.go
@@ -49,9 +49,6 @@
t.Errorf("m.OneofField = %p, want nil", m.OneofField)
}
- if got := m.ProtoReflect().Len(); got != 0 {
- t.Errorf("m.ProtoReflect().Len() = %d, want 0", got)
- }
if got := m.ProtoReflect().GetUnknown(); got != nil {
t.Errorf("m.ProtoReflect().GetUnknown() = %d, want nil", got)
}