Skip to content

Instantly share code, notes, and snippets.

@Vladimir-Z
Last active August 29, 2015 13:56
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save Vladimir-Z/1a1755ce91cb0e7636b5 to your computer and use it in GitHub Desktop.
Save Vladimir-Z/1a1755ce91cb0e7636b5 to your computer and use it in GitHub Desktop.
simplified example of the template optimization in D language
// 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