-
-
Save Vladimir-Z/1a1755ce91cb0e7636b5 to your computer and use it in GitHub Desktop.
simplified example of the template optimization in D language
This file contains 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
// a simplified example of the template optimization | |
// сhanged according to recommendation: http://forum.dlang.org/thread/afzdsheqremujxttizdp@forum.dlang.org#post-foystbsgikxuwcmzwutz:40forum.dlang.org | |
// and http://forum.dlang.org/thread/afzdsheqremujxttizdp@forum.dlang.org#post-le602a:242dr5:241:40digitalmars.com | |
import std.stdio; | |
import std.c.stdlib; | |
import std.datetime; | |
enum tableSize = 5_000_000; | |
struct Row //of table | |
{ | |
enum numberField = 2; | |
enum numberOptions = 2 ^^ numberField; | |
uint [numberField] Fields; | |
} | |
Row generateRow() | |
{ | |
Row row; | |
row.Fields[0] = rand() % 10; | |
row.Fields[1] = (rand() % 1)*(rand() % 10); | |
return row; | |
} | |
int processRow(in Row tableRow, ref bool[] isUseField) pure | |
nothrow | |
{ | |
int sum = 0; | |
foreach (immutable i, immutable value; tableRow.Fields) | |
{ | |
if (isUseField[i]) | |
sum += value ^^ 2 - i; | |
} | |
return sum; | |
} | |
int ProcessTable(in Row[] table, bool[] isUseField) | |
{ | |
int result = 0; | |
foreach (ref row; table) | |
{ | |
result += processRow(row, isUseField); | |
} | |
return result; | |
} | |
template TypeTuple(T...) { alias T TypeTuple; } | |
//alias TypeTuple(T...) = Types; | |
//template for compile-time foreach | |
template StaticRange(int stop) | |
{ | |
static if (stop <= 0) | |
alias TypeTuple!() StaticRange; | |
else | |
alias TypeTuple!(StaticRange!(stop-1), stop-1) StaticRange; | |
} | |
//pointer to a specialized function | |
alias int function (in Row) processRowPtr; | |
__gshared processRowPtr [Row.numberOptions] filters; | |
size_t getIndex (bool[] isUseField) | |
{ | |
size_t index = 0; | |
foreach(i, isUse; isUseField) | |
index |= isUse?(1<<i):0; | |
return index; | |
} | |
int processRowTemplate(size_t optionVariant)(in Row table) | |
{ | |
int sum = 0; | |
foreach(size_t i; StaticRange!(Row.numberField)) | |
{ | |
static if (optionVariant & 1<<i) | |
{ | |
sum += table.Fields[i] ^^ 2 - i; | |
} | |
} | |
return sum; | |
} | |
int optimizedProcessTable(in Row[] table, bool[] isUseField) | |
{ | |
int result = 0; | |
auto FilterIndex = getIndex(isUseField); | |
auto processRow = filters[FilterIndex]; | |
foreach (ref el; table) | |
{ | |
result += processRow(el); | |
} | |
return result; | |
} | |
void fillFilters() | |
{ | |
foreach(size_t i; StaticRange!(Row.numberOptions)) | |
filters[i] = &processRowTemplate!(i); | |
} | |
void main() | |
{ | |
// initialize random seed: | |
// srand (time(NULL)); | |
auto table = new Row[tableSize]; | |
foreach ( ref row; table) { | |
row = generateRow(); | |
} | |
bool isUseField[Row.numberOptions]; | |
isUseField[0] = rand()%1 + 1; // use or not Row.Field[0] | |
isUseField[1] = rand()%1 + 0; // use or not Row.Field[1] | |
int result; | |
StopWatch sw; | |
TickDuration last = TickDuration.from!"seconds"(0); | |
//Simple processing | |
sw.start(); | |
result = ProcessTable(table, isUseField); | |
sw.stop(); | |
writeln ("Process table result: ", result); | |
writeln ("Simple processing: ", sw.peek().msecs, " ms"); | |
last = sw.peek(); | |
//Processing with template | |
fillFilters(); //CTFE ? | |
sw.start(); | |
result = optimizedProcessTable(table, isUseField); | |
sw.stop(); | |
writeln ("Process table result: ", result); | |
writeln ("Template processing: ", sw.peek().msecs - last.msecs, " ms"); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment