Commit 54e9406f authored by Dmitriy Vyukov's avatar Dmitriy Vyukov Committed by Russ Cox

runtime: add more specialized type algorithms

The change adds specialized type algorithms
for slices and types of size 8/16/32/64/128.
It significantly accelerates chan and map operations
for most builtin types as well as user structs.

benchmark                   old,ns/op   new,ns/op
BenchmarkChanUncontended          226          94
(on Intel Xeon E5620, 2.4GHz, Linux 64 bit)

R=golang-dev, rsc
CC=golang-dev
https://golang.org/cl/4815087
parent a09ba8b6
...@@ -40,7 +40,17 @@ enum ...@@ -40,7 +40,17 @@ enum
ASTRING, ASTRING,
AINTER, AINTER,
ANILINTER, ANILINTER,
AMEMWORD, ASLICE,
AMEM8,
AMEM16,
AMEM32,
AMEM64,
AMEM128,
ANOEQ8,
ANOEQ16,
ANOEQ32,
ANOEQ64,
ANOEQ128,
BADWIDTH = -1000000000, BADWIDTH = -1000000000,
}; };
......
...@@ -493,8 +493,16 @@ algtype(Type *t) ...@@ -493,8 +493,16 @@ algtype(Type *t)
if(issimple[t->etype] || isptr[t->etype] || if(issimple[t->etype] || isptr[t->etype] ||
t->etype == TCHAN || t->etype == TFUNC || t->etype == TMAP) { t->etype == TCHAN || t->etype == TFUNC || t->etype == TMAP) {
if(t->width == widthptr) if(t->width == 1)
a = AMEMWORD; a = AMEM8;
else if(t->width == 2)
a = AMEM16;
else if(t->width == 4)
a = AMEM32;
else if(t->width == 8)
a = AMEM64;
else if(t->width == 16)
a = AMEM128;
else else
a = AMEM; // just bytes (int, ptr, etc) a = AMEM; // just bytes (int, ptr, etc)
} else if(t->etype == TSTRING) } else if(t->etype == TSTRING)
...@@ -503,8 +511,22 @@ algtype(Type *t) ...@@ -503,8 +511,22 @@ algtype(Type *t)
a = ANILINTER; // nil interface a = ANILINTER; // nil interface
else if(t->etype == TINTER) else if(t->etype == TINTER)
a = AINTER; // interface a = AINTER; // interface
else if(isslice(t))
a = ASLICE; // slice
else {
if(t->width == 1)
a = ANOEQ8;
else if(t->width == 2)
a = ANOEQ16;
else if(t->width == 4)
a = ANOEQ32;
else if(t->width == 8)
a = ANOEQ64;
else if(t->width == 16)
a = ANOEQ128;
else else
a = ANOEQ; // just bytes, but no hash/eq a = ANOEQ; // just bytes, but no hash/eq
}
return a; return a;
} }
......
...@@ -398,21 +398,110 @@ memcopy(uint32 s, void *a, void *b) ...@@ -398,21 +398,110 @@ memcopy(uint32 s, void *a, void *b)
} }
static uint32 static uint32
memwordequal(uint32 s, void *a, void *b) memequal8(uint32 s, uint8 *a, uint8 *b)
{ {
USED(s); USED(s);
return *(uintptr*)(a) == *(uintptr*)(b); return *a == *b;
} }
static void static void
memwordcopy(uint32 s, void *a, void *b) memcopy8(uint32 s, uint8 *a, uint8 *b)
{ {
USED(s); USED(s);
if (b == nil) { if(b == nil) {
*(uintptr*)(a) = 0; *a = 0;
return;
}
*a = *b;
}
static uint32
memequal16(uint32 s, uint16 *a, uint16 *b)
{
USED(s);
return *a == *b;
}
static void
memcopy16(uint32 s, uint16 *a, uint16 *b)
{
USED(s);
if(b == nil) {
*a = 0;
return; return;
} }
*(uintptr*)(a) = *(uintptr*)(b); *a = *b;
}
static uint32
memequal32(uint32 s, uint32 *a, uint32 *b)
{
USED(s);
return *a == *b;
}
static void
memcopy32(uint32 s, uint32 *a, uint32 *b)
{
USED(s);
if(b == nil) {
*a = 0;
return;
}
*a = *b;
}
static uint32
memequal64(uint32 s, uint64 *a, uint64 *b)
{
USED(s);
return *a == *b;
}
static void
memcopy64(uint32 s, uint64 *a, uint64 *b)
{
USED(s);
if(b == nil) {
*a = 0;
return;
}
*a = *b;
}
static uint32
memequal128(uint32 s, uint64 *a, uint64 *b)
{
USED(s);
return a[0] == b[0] && a[1] == b[1];
}
static void
memcopy128(uint32 s, uint64 *a, uint64 *b)
{
USED(s);
if(b == nil) {
a[0] = 0;
a[1] = 0;
return;
}
a[0] = b[0];
a[1] = b[1];
}
static void
slicecopy(uint32 s, Slice *a, Slice *b)
{
USED(s);
if(b == nil) {
a->array = 0;
a->len = 0;
a->cap = 0;
return;
}
a->array = b->array;
a->len = b->len;
a->cap = b->cap;
} }
static uintptr static uintptr
...@@ -441,6 +530,19 @@ strprint(uint32 s, String *a) ...@@ -441,6 +530,19 @@ strprint(uint32 s, String *a)
runtime·printstring(*a); runtime·printstring(*a);
} }
static void
strcopy(uint32 s, String *a, String *b)
{
USED(s);
if(b == nil) {
a->str = 0;
a->len = 0;
return;
}
a->str = b->str;
a->len = b->len;
}
static uintptr static uintptr
interhash(uint32 s, Iface *a) interhash(uint32 s, Iface *a)
{ {
...@@ -462,6 +564,19 @@ interequal(uint32 s, Iface *a, Iface *b) ...@@ -462,6 +564,19 @@ interequal(uint32 s, Iface *a, Iface *b)
return runtime·ifaceeq_c(*a, *b); return runtime·ifaceeq_c(*a, *b);
} }
static void
intercopy(uint32 s, Iface *a, Iface *b)
{
USED(s);
if(b == nil) {
a->tab = 0;
a->data = 0;
return;
}
a->tab = b->tab;
a->data = b->data;
}
static uintptr static uintptr
nilinterhash(uint32 s, Eface *a) nilinterhash(uint32 s, Eface *a)
{ {
...@@ -483,6 +598,19 @@ nilinterequal(uint32 s, Eface *a, Eface *b) ...@@ -483,6 +598,19 @@ nilinterequal(uint32 s, Eface *a, Eface *b)
return runtime·efaceeq_c(*a, *b); return runtime·efaceeq_c(*a, *b);
} }
static void
nilintercopy(uint32 s, Eface *a, Eface *b)
{
USED(s);
if(b == nil) {
a->type = 0;
a->data = 0;
return;
}
a->type = b->type;
a->data = b->data;
}
uintptr uintptr
runtime·nohash(uint32 s, void *a) runtime·nohash(uint32 s, void *a)
{ {
...@@ -507,10 +635,20 @@ runtime·algarray[] = ...@@ -507,10 +635,20 @@ runtime·algarray[] =
{ {
[AMEM] { memhash, memequal, memprint, memcopy }, [AMEM] { memhash, memequal, memprint, memcopy },
[ANOEQ] { runtime·nohash, runtime·noequal, memprint, memcopy }, [ANOEQ] { runtime·nohash, runtime·noequal, memprint, memcopy },
[ASTRING] { strhash, strequal, strprint, memcopy }, [ASTRING] { strhash, strequal, strprint, strcopy },
[AINTER] { interhash, interequal, interprint, memcopy }, [AINTER] { interhash, interequal, interprint, intercopy },
[ANILINTER] { nilinterhash, nilinterequal, nilinterprint, memcopy }, [ANILINTER] { nilinterhash, nilinterequal, nilinterprint, nilintercopy },
[AMEMWORD] { memhash, memwordequal, memprint, memwordcopy }, [ASLICE] { runtime·nohash, runtime·noequal, memprint, slicecopy },
[AMEM8] { memhash, memequal8, memprint, memcopy8 },
[AMEM16] { memhash, memequal16, memprint, memcopy16 },
[AMEM32] { memhash, memequal32, memprint, memcopy32 },
[AMEM64] { memhash, memequal64, memprint, memcopy64 },
[AMEM128] { memhash, memequal128, memprint, memcopy128 },
[ANOEQ8] { runtime·nohash, runtime·noequal, memprint, memcopy8 },
[ANOEQ16] { runtime·nohash, runtime·noequal, memprint, memcopy16 },
[ANOEQ32] { runtime·nohash, runtime·noequal, memprint, memcopy32 },
[ANOEQ64] { runtime·nohash, runtime·noequal, memprint, memcopy64 },
[ANOEQ128] { runtime·nohash, runtime·noequal, memprint, memcopy128 },
}; };
int64 int64
......
...@@ -335,7 +335,17 @@ enum ...@@ -335,7 +335,17 @@ enum
ASTRING, ASTRING,
AINTER, AINTER,
ANILINTER, ANILINTER,
AMEMWORD, ASLICE,
AMEM8,
AMEM16,
AMEM32,
AMEM64,
AMEM128,
ANOEQ8,
ANOEQ16,
ANOEQ32,
ANOEQ64,
ANOEQ128,
Amax Amax
}; };
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment