mirror of
https://github.com/octoleo/syncthing.git
synced 2024-12-23 03:18:59 +00:00
9682bbfbda
These functions were very naive and slow. We haven't done much about them because they pretty much don't matter at all for Syncthing performance. They are however called very often in the discovery server and these optimizations have a huge effect on the CPU load on the public discovery servers. The code isn't exactly obvious, but we have good test coverage on all these functions. benchmark old ns/op new ns/op delta BenchmarkLuhnify-8 12458 1045 -91.61% BenchmarkUnluhnify-8 12598 1074 -91.47% BenchmarkChunkify-8 10792 104 -99.04% benchmark old allocs new allocs delta BenchmarkLuhnify-8 18 1 -94.44% BenchmarkUnluhnify-8 18 1 -94.44% BenchmarkChunkify-8 44 2 -95.45% benchmark old bytes new bytes delta BenchmarkLuhnify-8 1278 64 -94.99% BenchmarkUnluhnify-8 1278 64 -94.99% BenchmarkChunkify-8 42552 128 -99.70% GitHub-Pull-Request: https://github.com/syncthing/syncthing/pull/4346
191 lines
5.0 KiB
Go
191 lines
5.0 KiB
Go
// Copyright (C) 2014 The Protocol Authors.
|
|
|
|
//go:generate go run ../../script/protofmt.go deviceid_test.proto
|
|
//go:generate protoc -I ../../vendor/ -I ../../vendor/github.com/gogo/protobuf/protobuf -I . --gogofast_out=. deviceid_test.proto
|
|
|
|
package protocol
|
|
|
|
import "testing"
|
|
|
|
var formatted = "P56IOI7-MZJNU2Y-IQGDREY-DM2MGTI-MGL3BXN-PQ6W5BM-TBBZ4TJ-XZWICQ2"
|
|
var formatCases = []string{
|
|
"P56IOI-7MZJNU-2IQGDR-EYDM2M-GTMGL3-BXNPQ6-W5BTBB-Z4TJXZ-WICQ",
|
|
"P56IOI-7MZJNU2Y-IQGDR-EYDM2M-GTI-MGL3-BXNPQ6-W5BM-TBB-Z4TJXZ-WICQ2",
|
|
"P56IOI7 MZJNU2I QGDREYD M2MGTMGL 3BXNPQ6W 5BTB BZ4T JXZWICQ",
|
|
"P56IOI7 MZJNU2Y IQGDREY DM2MGTI MGL3BXN PQ6W5BM TBBZ4TJ XZWICQ2",
|
|
"P56IOI7MZJNU2IQGDREYDM2MGTMGL3BXNPQ6W5BTBBZ4TJXZWICQ",
|
|
"p56ioi7mzjnu2iqgdreydm2mgtmgl3bxnpq6w5btbbz4tjxzwicq",
|
|
"P56IOI7MZJNU2YIQGDREYDM2MGTIMGL3BXNPQ6W5BMTBBZ4TJXZWICQ2",
|
|
"P561017MZJNU2YIQGDREYDM2MGTIMGL3BXNPQ6W5BMT88Z4TJXZWICQ2",
|
|
"p56ioi7mzjnu2yiqgdreydm2mgtimgl3bxnpq6w5bmtbbz4tjxzwicq2",
|
|
"p561017mzjnu2yiqgdreydm2mgtimgl3bxnpq6w5bmt88z4tjxzwicq2",
|
|
}
|
|
|
|
func TestFormatDeviceID(t *testing.T) {
|
|
for i, tc := range formatCases {
|
|
var id DeviceID
|
|
err := id.UnmarshalText([]byte(tc))
|
|
if err != nil {
|
|
t.Errorf("#%d UnmarshalText(%q); %v", i, tc, err)
|
|
} else if f := id.String(); f != formatted {
|
|
t.Errorf("#%d FormatDeviceID(%q)\n\t%q !=\n\t%q", i, tc, f, formatted)
|
|
}
|
|
}
|
|
}
|
|
|
|
var validateCases = []struct {
|
|
s string
|
|
ok bool
|
|
}{
|
|
{"", true}, // Empty device ID, all zeroes
|
|
{"a", false},
|
|
{"P56IOI7-MZJNU2Y-IQGDREY-DM2MGTI-MGL3BXN-PQ6W5BM-TBBZ4TJ-XZWICQ2", true},
|
|
{"P56IOI7-MZJNU2-IQGDREY-DM2MGT-MGL3BXN-PQ6W5B-TBBZ4TJ-XZWICQ", true},
|
|
{"P56IOI7 MZJNU2I QGDREYD M2MGTMGL 3BXNPQ6W 5BTB BZ4T JXZWICQ", true},
|
|
{"P56IOI7MZJNU2IQGDREYDM2MGTMGL3BXNPQ6W5BTBBZ4TJXZWICQ", true},
|
|
{"P56IOI7MZJNU2IQGDREYDM2MGTMGL3BXNPQ6W5BTBBZ4TJXZWICQCCCC", false},
|
|
{"p56ioi7mzjnu2iqgdreydm2mgtmgl3bxnpq6w5btbbz4tjxzwicq", true},
|
|
{"p56ioi7mzjnu2iqgdreydm2mgtmgl3bxnpq6w5btbbz4tjxzwicqCCCC", false},
|
|
}
|
|
|
|
func TestValidateDeviceID(t *testing.T) {
|
|
for _, tc := range validateCases {
|
|
var id DeviceID
|
|
err := id.UnmarshalText([]byte(tc.s))
|
|
if (err == nil && !tc.ok) || (err != nil && tc.ok) {
|
|
t.Errorf("ValidateDeviceID(%q); %v != %v", tc.s, err, tc.ok)
|
|
}
|
|
}
|
|
}
|
|
|
|
func TestMarshallingDeviceID(t *testing.T) {
|
|
n0 := DeviceID{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 10, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32}
|
|
n1 := DeviceID{}
|
|
n2 := DeviceID{}
|
|
|
|
bs, _ := n0.MarshalText()
|
|
n1.UnmarshalText(bs)
|
|
bs, _ = n1.MarshalText()
|
|
n2.UnmarshalText(bs)
|
|
|
|
if n2.String() != n0.String() {
|
|
t.Errorf("String marshalling error; %q != %q", n2.String(), n0.String())
|
|
}
|
|
if !n2.Equals(n0) {
|
|
t.Error("Equals error")
|
|
}
|
|
if n2.Compare(n0) != 0 {
|
|
t.Error("Compare error")
|
|
}
|
|
}
|
|
|
|
func TestShortIDString(t *testing.T) {
|
|
id, _ := DeviceIDFromString(formatted)
|
|
|
|
sid := id.Short().String()
|
|
if len(sid) != 7 {
|
|
t.Errorf("Wrong length for short ID: got %d, want 7", len(sid))
|
|
}
|
|
|
|
want := formatted[:len(sid)]
|
|
if sid != want {
|
|
t.Errorf("Wrong short ID: got %q, want %q", sid, want)
|
|
}
|
|
}
|
|
|
|
func TestDeviceIDFromBytes(t *testing.T) {
|
|
id0, _ := DeviceIDFromString(formatted)
|
|
id1 := DeviceIDFromBytes(id0[:])
|
|
if id1.String() != formatted {
|
|
t.Errorf("Wrong device ID, got %q, want %q", id1, formatted)
|
|
}
|
|
}
|
|
|
|
func TestNewDeviceIDMarshalling(t *testing.T) {
|
|
// The new DeviceID.Unmarshal / DeviceID.MarshalTo serialization should
|
|
// be message compatible with how we used to serialize DeviceIDs.
|
|
|
|
// Create a message with a device ID in old style bytes format
|
|
|
|
id0, _ := DeviceIDFromString(formatted)
|
|
msg0 := TestOldDeviceID{id0[:]}
|
|
|
|
// Marshal it
|
|
|
|
bs, err := msg0.Marshal()
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
|
|
// Unmarshal using the new DeviceID.Unmarshal
|
|
|
|
var msg1 TestNewDeviceID
|
|
if err := msg1.Unmarshal(bs); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
|
|
// Verify it's the same
|
|
|
|
if msg1.Test != id0 {
|
|
t.Error("Mismatch in old -> new direction")
|
|
}
|
|
|
|
// Marshal using the new DeviceID.MarshalTo
|
|
|
|
bs, err = msg1.Marshal()
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
|
|
// Create an old style message and attempt unmarshal
|
|
|
|
var msg2 TestOldDeviceID
|
|
if err := msg2.Unmarshal(bs); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
|
|
// Verify it's the same
|
|
|
|
if DeviceIDFromBytes(msg2.Test) != id0 {
|
|
t.Error("Mismatch in old -> new direction")
|
|
}
|
|
}
|
|
|
|
var resStr string
|
|
|
|
func BenchmarkLuhnify(b *testing.B) {
|
|
str := "ABCDEFGHIJABCDEFGHIJABCDEFGHIJABCDEFGHIJABCDEFGHIJAB"
|
|
var err error
|
|
for i := 0; i < b.N; i++ {
|
|
resStr, err = luhnify(str)
|
|
if err != nil {
|
|
b.Fatal(err)
|
|
}
|
|
}
|
|
}
|
|
|
|
func BenchmarkUnluhnify(b *testing.B) {
|
|
str, _ := luhnify("ABCDEFGHIJABCDEFGHIJABCDEFGHIJABCDEFGHIJABCDEFGHIJAB")
|
|
var err error
|
|
for i := 0; i < b.N; i++ {
|
|
resStr, err = unluhnify(str)
|
|
if err != nil {
|
|
b.Fatal(err)
|
|
}
|
|
}
|
|
}
|
|
|
|
func BenchmarkChunkify(b *testing.B) {
|
|
str := "ABCDEFGHIJABCDEFGHIJABCDEFGHIJABCDEFGHIJABCDEFGHIJAB"
|
|
for i := 0; i < b.N; i++ {
|
|
resStr = chunkify(str)
|
|
}
|
|
}
|
|
|
|
func BenchmarkUnchunkify(b *testing.B) {
|
|
str := chunkify("ABCDEFGHIJABCDEFGHIJABCDEFGHIJABCDEFGHIJABCDEFGHIJAB")
|
|
for i := 0; i < b.N; i++ {
|
|
resStr = unchunkify(str)
|
|
}
|
|
}
|