Skip to content

Commit 69cd91a

Browse files
committed
cmd/gc: don't copy []byte during string comparison
Currently we allocate a new string during []byte->string conversion in string comparison expressions. String allocation is unnecessary in this case, because comparison does memorize the strings for later use. This change uses slicebytetostringtmp to construct temp string directly from []byte buffer and passes it to runtime.eqstring. Change-Id: If00f1faaee2076baa6f6724d245d5b5e0f59b563 Reviewed-on: https://go-review.googlesource.com/3410 Reviewed-by: Russ Cox <rsc@golang.org>
1 parent 4737399 commit 69cd91a

File tree

3 files changed

+30
-0
lines changed

3 files changed

+30
-0
lines changed

src/cmd/gc/order.c

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1031,6 +1031,18 @@ orderexpr(Node **np, Order *order)
10311031
}
10321032
break;
10331033

1034+
case OCMPSTR:
1035+
orderexpr(&n->left, order);
1036+
orderexpr(&n->right, order);
1037+
// Mark string(byteSlice) arguments to reuse byteSlice backing
1038+
// buffer during conversion. String comparison does not
1039+
// memorize the strings for later use, so it is safe.
1040+
if(n->left->op == OARRAYBYTESTR)
1041+
n->left->op = OARRAYBYTESTRTMP;
1042+
if(n->right->op == OARRAYBYTESTR)
1043+
n->right->op = OARRAYBYTESTRTMP;
1044+
break;
1045+
10341046
case OINDEXMAP:
10351047
// key must be addressable
10361048
orderexpr(&n->left, order);

src/runtime/string.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -76,6 +76,7 @@ func slicebytetostringtmp(b []byte) string {
7676
// First such case is a m[string(k)] lookup where
7777
// m is a string-keyed map and k is a []byte.
7878
// Second such case is "<"+string(b)+">" concatenation where b is []byte.
79+
// Third such case is string(b)=="foo" comparison where b is []byte.
7980

8081
if raceenabled && len(b) > 0 {
8182
racereadrangepc(unsafe.Pointer(&b[0]),

src/runtime/string_test.go

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -158,3 +158,20 @@ func TestGostringnocopy(t *testing.T) {
158158
t.Errorf("want %d, got %d", max+9, newmax)
159159
}
160160
}
161+
162+
func TestCompareTempString(t *testing.T) {
163+
s := "foo"
164+
b := []byte(s)
165+
n := testing.AllocsPerRun(1000, func() {
166+
if string(b) != s {
167+
t.Fatalf("strings are not equal: '%v' and '%v'", string(b), s)
168+
}
169+
if string(b) == s {
170+
} else {
171+
t.Fatalf("strings are not equal: '%v' and '%v'", string(b), s)
172+
}
173+
})
174+
if n != 0 {
175+
t.Fatalf("want 0 allocs, got %v", n)
176+
}
177+
}

0 commit comments

Comments
 (0)