Created
September 24, 2021 02:00
-
-
Save FeepingCreature/ff4c052eb4df70774bbb3446df30dd9d to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
module bench; | |
import std; | |
import std.datetime.stopwatch : benchmark; | |
int test(alias skip)(ubyte[] trash) | |
{ | |
int lenSum; | |
while (!trash.empty) | |
{ | |
if (trash.front == '"') | |
{ | |
trash.popFront; | |
auto start = trash.length; | |
skip(trash); | |
lenSum += start - trash.length; | |
} | |
if (trash.empty) break; | |
trash.popFront; | |
} | |
return lenSum; | |
} | |
void skipToQuoteBasic(ref ubyte[] data) { | |
import core.bitop : bsf; | |
enum step = ` | |
while (!data.empty && data.front != '"' && %s) { | |
data.popFront; | |
}`; | |
if (data.length >= 16) { | |
// 16-align pointer | |
mixin(format!step(q{(cast(size_t) data.ptr) & 0xf})); | |
if (data.empty || data.front == '"') return; | |
align(16) | |
static struct AlignedVector | |
{ | |
ubyte[16] data; | |
} | |
while (data.length >= 16) { | |
auto vector = *cast(AlignedVector*) data.ptr; | |
static immutable AlignedVector match = AlignedVector(cast(ubyte[16]) [ | |
'"', '"', '"', '"', '"', '"', '"', '"', '"', '"', '"', '"', '"', '"', '"', '"']); | |
uint test; | |
foreach (i; 0 .. 16) | |
{ | |
test |= (vector.data[i] == match.data[i]) << i; | |
} | |
if (test == 0) { | |
// no characters match '"' | |
data = data.drop(16); | |
continue; | |
} | |
data = data.drop(bsf(test)); | |
return; | |
} | |
} | |
mixin(format!step(q{true})); | |
} | |
void skipToQuoteFullBasic(ref ubyte[] data) { | |
while (!data.empty && data.front != '"') { | |
data.popFront; | |
} | |
} | |
void skipToQuoteAsm(ref ubyte[] data) { | |
import core.bitop : bsf; | |
enum step = ` | |
while (!data.empty && data.front != '"' && %s) { | |
data.popFront; | |
}`; | |
if (data.length >= 16) { | |
// 16-align pointer | |
mixin(format!step(q{(cast(size_t) data.ptr) & 0xf})); | |
if (data.empty || data.front == '"') return; | |
align(16) | |
static struct AlignedVector | |
{ | |
ubyte[16] data; | |
} | |
while (data.length >= 16) { | |
auto vector = cast(AlignedVector*) data.ptr; | |
static immutable AlignedVector match = AlignedVector(cast(ubyte[16]) [ | |
'"', '"', '"', '"', '"', '"', '"', '"', '"', '"', '"', '"', '"', '"', '"', '"']); | |
uint test; | |
asm { | |
mov RAX, vector; | |
movaps XMM0, [RAX]; | |
movaps XMM1, [match]; | |
pcmpeqb XMM0, XMM1; | |
pmovmskb EAX, XMM0; | |
mov test, EAX; | |
} | |
if (test != 0) { | |
data = data.drop(bsf(test)); | |
return; | |
} | |
// no characters match '"' | |
data = data.drop(16); | |
continue; | |
} | |
} | |
mixin(format!step(q{true})); | |
} | |
void skipToQuoteUnalignedAsm(ref ubyte[] data) { | |
import core.bitop : bsf; | |
enum step = ` | |
while (!data.empty && data.front != '"' && %s) { | |
data.popFront; | |
}`; | |
while (data.length >= 16) { | |
align(16) | |
static struct AlignedVector | |
{ | |
ubyte[16] data; | |
} | |
auto vector = data.ptr; | |
static immutable AlignedVector match = AlignedVector(cast(ubyte[16]) [ | |
'"', '"', '"', '"', '"', '"', '"', '"', '"', '"', '"', '"', '"', '"', '"', '"']); | |
int test = 0; | |
asm { | |
mov RAX, vector; | |
movups XMM0, [RAX]; | |
movaps XMM1, [match]; | |
pcmpeqb XMM0, XMM1; | |
pmovmskb EAX, XMM0; | |
mov test, EAX; | |
} | |
if (test != 0) { | |
data = data.drop(bsf(test)); | |
return; | |
} | |
data = data.drop(16); | |
continue; | |
} | |
mixin(format!step(q{true})); | |
} | |
void main() { | |
ubyte[] trash = cast(ubyte[]) rndGen.take(32*1048576).array; | |
writefln!"Starting benchmark."; | |
int res1, res2, res3, res4; | |
auto r = benchmark!( | |
{ res1 = trash.test!skipToQuoteFullBasic; }, | |
{ res2 = trash.test!skipToQuoteBasic; }, | |
{ res3 = trash.test!skipToQuoteAsm; }, | |
{ res4 = trash.test!skipToQuoteUnalignedAsm; }, | |
)(16); | |
writefln!"[Full Basic ] %s in %s"(res1, r[0]); | |
writefln!"[Basic ] %s in %s"(res2, r[1]); | |
writefln!"[Asm ] %s in %s"(res3, r[2]); | |
writefln!"[UnalignedAsm] %s in %s"(res4, r[3]); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment