mirror of
https://github.com/golang/go
synced 2024-11-02 13:42:29 +00:00
encoding/asn1: optimize asn1.Unmarshal
Used type-switch instead of switch by reflect.Type and added BenchmarkUnmarshal. name old time/op new time/op delta Marshal-8 28.1µs ± 2% 27.9µs ± 1% ~ (p=0.094 n=9+9) Unmarshal-8 6.45µs ± 1% 5.83µs ± 4% -9.59% (p=0.000 n=10+10) name old alloc/op new alloc/op delta Marshal-8 8.26kB ± 0% 8.26kB ± 0% ~ (all equal) Unmarshal-8 840B ± 0% 488B ± 0% -41.90% (p=0.000 n=10+10) name old allocs/op new allocs/op delta Marshal-8 363 ± 0% 363 ± 0% ~ (all equal) Unmarshal-8 50.0 ± 0% 43.0 ± 0% -14.00% (p=0.000 n=10+10) Change-Id: I6b53833c7a3e2524f025453311841d03c1256a45 GitHub-Pull-Request: golang/go#36341 Reviewed-on: https://go-review.googlesource.com/c/go/+/268557 Trust: Filippo Valsorda <filippo@golang.org> Trust: Roland Shoemaker <roland@golang.org> Run-TryBot: Filippo Valsorda <filippo@golang.org> TryBot-Result: Go Bot <gobot@golang.org> Reviewed-by: Roland Shoemaker <roland@golang.org>
This commit is contained in:
parent
d4957122ee
commit
d361691201
2 changed files with 45 additions and 33 deletions
|
@ -851,53 +851,37 @@ func parseField(v reflect.Value, bytes []byte, initOffset int, params fieldParam
|
|||
offset += t.length
|
||||
|
||||
// We deal with the structures defined in this package first.
|
||||
switch fieldType {
|
||||
case rawValueType:
|
||||
result := RawValue{t.class, t.tag, t.isCompound, innerBytes, bytes[initOffset:offset]}
|
||||
v.Set(reflect.ValueOf(result))
|
||||
switch v := v.Addr().Interface().(type) {
|
||||
case *RawValue:
|
||||
*v = RawValue{t.class, t.tag, t.isCompound, innerBytes, bytes[initOffset:offset]}
|
||||
return
|
||||
case objectIdentifierType:
|
||||
newSlice, err1 := parseObjectIdentifier(innerBytes)
|
||||
v.Set(reflect.MakeSlice(v.Type(), len(newSlice), len(newSlice)))
|
||||
if err1 == nil {
|
||||
reflect.Copy(v, reflect.ValueOf(newSlice))
|
||||
}
|
||||
err = err1
|
||||
case *ObjectIdentifier:
|
||||
*v, err = parseObjectIdentifier(innerBytes)
|
||||
return
|
||||
case bitStringType:
|
||||
bs, err1 := parseBitString(innerBytes)
|
||||
if err1 == nil {
|
||||
v.Set(reflect.ValueOf(bs))
|
||||
}
|
||||
err = err1
|
||||
case *BitString:
|
||||
*v, err = parseBitString(innerBytes)
|
||||
return
|
||||
case timeType:
|
||||
var time time.Time
|
||||
var err1 error
|
||||
case *time.Time:
|
||||
if universalTag == TagUTCTime {
|
||||
time, err1 = parseUTCTime(innerBytes)
|
||||
} else {
|
||||
time, err1 = parseGeneralizedTime(innerBytes)
|
||||
*v, err = parseUTCTime(innerBytes)
|
||||
return
|
||||
}
|
||||
if err1 == nil {
|
||||
v.Set(reflect.ValueOf(time))
|
||||
}
|
||||
err = err1
|
||||
*v, err = parseGeneralizedTime(innerBytes)
|
||||
return
|
||||
case enumeratedType:
|
||||
case *Enumerated:
|
||||
parsedInt, err1 := parseInt32(innerBytes)
|
||||
if err1 == nil {
|
||||
v.SetInt(int64(parsedInt))
|
||||
*v = Enumerated(parsedInt)
|
||||
}
|
||||
err = err1
|
||||
return
|
||||
case flagType:
|
||||
v.SetBool(true)
|
||||
case *Flag:
|
||||
*v = true
|
||||
return
|
||||
case bigIntType:
|
||||
case **big.Int:
|
||||
parsedInt, err1 := parseBigInt(innerBytes)
|
||||
if err1 == nil {
|
||||
v.Set(reflect.ValueOf(parsedInt))
|
||||
*v = parsedInt
|
||||
}
|
||||
err = err1
|
||||
return
|
||||
|
|
|
@ -376,3 +376,31 @@ func TestSetEncoderSETSliceSuffix(t *testing.T) {
|
|||
t.Errorf("Unexpected SET content. got: %s, want: %s", resultSet, expectedOrder)
|
||||
}
|
||||
}
|
||||
|
||||
func BenchmarkUnmarshal(b *testing.B) {
|
||||
b.ReportAllocs()
|
||||
|
||||
type testCase struct {
|
||||
in []byte
|
||||
out interface{}
|
||||
}
|
||||
var testData []testCase
|
||||
for _, test := range unmarshalTestData {
|
||||
pv := reflect.New(reflect.TypeOf(test.out).Elem())
|
||||
inCopy := make([]byte, len(test.in))
|
||||
copy(inCopy, test.in)
|
||||
outCopy := pv.Interface()
|
||||
|
||||
testData = append(testData, testCase{
|
||||
in: inCopy,
|
||||
out: outCopy,
|
||||
})
|
||||
}
|
||||
|
||||
b.ResetTimer()
|
||||
for i := 0; i < b.N; i++ {
|
||||
for _, testCase := range testData {
|
||||
_, _ = Unmarshal(testCase.in, testCase.out)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue