Skip to content

Commit bcf1f91

Browse files
committed
Use .EqualFold() to parse urn prefixed UUIDs
Prior to this commit we used a comparison with the result of ToLower() to test for a "urn:uuid" prefix in both UUID strings and byte slices. This commit replaces the ToLower and string comparison with both strings.EqualFold() and bytes.EqualFold(). This reduces the CPU time across the board for UUIDs that start with "urn:uuid" and eliminates some allocations when parsing bytes. The benchmark output was generated by adding "urn:uuid" to the test input. goos: linux goarch: amd64 pkg: github.com/google/uuid cpu: Intel(R) Core(TM) i7-10510U CPU @ 1.80GHz │ /tmp/output1 │ /tmp/output2 │ │ sec/op │ sec/op vs base │ Parse-8 35.87n ± ∞ ¹ 33.75n ± ∞ ¹ ~ (p=1.000 n=1) ² ParseBytes-8 65.10n ± ∞ ¹ 35.56n ± ∞ ¹ ~ (p=1.000 n=1) ² ParseBytesUnsafe-8 35.31n ± ∞ ¹ 34.70n ± ∞ ¹ ~ (p=1.000 n=1) ² ParseBytesCopy-8 78.01n ± ∞ ¹ 61.21n ± ∞ ¹ ~ (p=1.000 n=1) ² ParseBadLength-8 3.499n ± ∞ ¹ 3.084n ± ∞ ¹ ~ (p=1.000 n=1) ² ParseLen32Truncated-8 3.335n ± ∞ ¹ 3.334n ± ∞ ¹ ~ (p=1.000 n=1) ² ParseLen36Corrupted-8 63.02n ± ∞ ¹ 58.26n ± ∞ ¹ ~ (p=1.000 n=1) ² geomean 24.11n 20.51n -14.92% ¹ need >= 6 samples for confidence interval at level 0.95 ² need >= 4 samples to detect a difference at alpha level 0.05 │ /tmp/output1 │ /tmp/output2 │ │ B/op │ B/op vs base │ Parse-8 0.000 ± ∞ ¹ 0.000 ± ∞ ¹ ~ (p=1.000 n=1) ² ParseBytes-8 16.00 ± ∞ ¹ 0.00 ± ∞ ¹ ~ (p=1.000 n=1) ³ ParseBytesUnsafe-8 0.000 ± ∞ ¹ 0.000 ± ∞ ¹ ~ (p=1.000 n=1) ² ParseBytesCopy-8 48.00 ± ∞ ¹ 48.00 ± ∞ ¹ ~ (p=1.000 n=1) ² ParseBadLength-8 0.000 ± ∞ ¹ 0.000 ± ∞ ¹ ~ (p=1.000 n=1) ² ParseLen32Truncated-8 0.000 ± ∞ ¹ 0.000 ± ∞ ¹ ~ (p=1.000 n=1) ² ParseLen36Corrupted-8 16.00 ± ∞ ¹ 16.00 ± ∞ ¹ ~ (p=1.000 n=1) ² geomean ⁴ ? ⁴ ⁵ ¹ need >= 6 samples for confidence interval at level 0.95 ² all samples are equal ³ need >= 4 samples to detect a difference at alpha level 0.05 ⁴ summaries must be >0 to compute geomean ⁵ ratios must be >0 to compute geomean │ /tmp/output1 │ /tmp/output2 │ │ allocs/op │ allocs/op vs base │ Parse-8 0.000 ± ∞ ¹ 0.000 ± ∞ ¹ ~ (p=1.000 n=1) ² ParseBytes-8 1.000 ± ∞ ¹ 0.000 ± ∞ ¹ ~ (p=1.000 n=1) ³ ParseBytesUnsafe-8 0.000 ± ∞ ¹ 0.000 ± ∞ ¹ ~ (p=1.000 n=1) ² ParseBytesCopy-8 1.000 ± ∞ ¹ 1.000 ± ∞ ¹ ~ (p=1.000 n=1) ² ParseBadLength-8 0.000 ± ∞ ¹ 0.000 ± ∞ ¹ ~ (p=1.000 n=1) ² ParseLen32Truncated-8 0.000 ± ∞ ¹ 0.000 ± ∞ ¹ ~ (p=1.000 n=1) ² ParseLen36Corrupted-8 1.000 ± ∞ ¹ 1.000 ± ∞ ¹ ~ (p=1.000 n=1) ² geomean ⁴ ? ⁴ ⁵ ¹ need >= 6 samples for confidence interval at level 0.95 ² all samples are equal ³ need >= 4 samples to detect a difference at alpha level 0.05 ⁴ summaries must be >0 to compute geomean ⁵ ratios must be >0 to compute geomean
1 parent 44b5fee commit bcf1f91

File tree

1 file changed

+6
-4
lines changed

1 file changed

+6
-4
lines changed

uuid.go

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -69,7 +69,7 @@ func Parse(s string) (UUID, error) {
6969

7070
// urn:uuid:xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx
7171
case 36 + 9:
72-
if strings.ToLower(s[:9]) != "urn:uuid:" {
72+
if !strings.EqualFold(s[:9], "urn:uuid:") {
7373
return uuid, fmt.Errorf("invalid urn prefix: %q", s[:9])
7474
}
7575
s = s[9:]
@@ -101,7 +101,8 @@ func Parse(s string) (UUID, error) {
101101
9, 11,
102102
14, 16,
103103
19, 21,
104-
24, 26, 28, 30, 32, 34} {
104+
24, 26, 28, 30, 32, 34,
105+
} {
105106
v, ok := xtob(s[x], s[x+1])
106107
if !ok {
107108
return uuid, errors.New("invalid UUID format")
@@ -117,7 +118,7 @@ func ParseBytes(b []byte) (UUID, error) {
117118
switch len(b) {
118119
case 36: // xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx
119120
case 36 + 9: // urn:uuid:xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx
120-
if !bytes.Equal(bytes.ToLower(b[:9]), []byte("urn:uuid:")) {
121+
if !bytes.EqualFold(b[:9], []byte("urn:uuid:")) {
121122
return uuid, fmt.Errorf("invalid urn prefix: %q", b[:9])
122123
}
123124
b = b[9:]
@@ -145,7 +146,8 @@ func ParseBytes(b []byte) (UUID, error) {
145146
9, 11,
146147
14, 16,
147148
19, 21,
148-
24, 26, 28, 30, 32, 34} {
149+
24, 26, 28, 30, 32, 34,
150+
} {
149151
v, ok := xtob(b[x], b[x+1])
150152
if !ok {
151153
return uuid, errors.New("invalid UUID format")

0 commit comments

Comments
 (0)