GC performances
Craig Black
cblack at ara.com
Mon Nov 26 07:47:47 PST 2007
"Lutger" <lutger.blijdestijn at gmail.com> wrote in message
news:fiekma$otu$1 at digitalmars.com...
> bearophile wrote:
>> Lutger Wrote:
> ...
>>> Likely not the intent of the benchmark, but an array based
>>> implementation could be faster here.
>>
>> It seems slower.
>>
>> Bye,
>> bearophile
>
> I've hacked up an array based implementation without recursion and
> allocating whole trees at once. Although it produces the same results,
> it's probably flawed somewhere or the profiling is wrong I think. Anyway
> it runs much faster, perhaps you care to take a look. I'm not so good at
> these things:
>
>
> import std.stdio, std.conv;
> import std.math;
>
> int left(int i) { return i * 2; }
>
> int right(int i) { return ++i * 2; }
>
> int parent(int i) { return i / 2; }
>
> struct Tree
> {
> static Tree bottumUpTree(int item, int depth)
> {
> Tree result;
> result.depth = depth;
> if (depth > 0)
> {
> auto len = pow(depth, cast(real)1);
> result.children.length = cast(uint)len;
>
> }
> else
> result.children.length = 1;
> result.children[0] = item;
> for (int i = 1; i < result.children.length; i+=2)
> {
> result.children[i] = (result.children[parent(i)] * 2) - 1;
> result.children[i + 1] = result.children[parent(i)] * 2;
> }
> return result;
> }
>
> int depth;
>
> int check()
> {
> int result = children[0];
> auto copy = children.dup;
>
> for (int i = children.length - ((depth * 2) -1); i <
> children.length; i+=2)
> {
> auto p = parent(i);
> copy[p] += children[i] - children[i+1];
> }
>
> for (int i = children.length - ((depth * 2) - 2); i > 0; i-=2)
> {
> auto p = parent(i);
> copy[p] += children[i-1] - children[i];
> }
>
> result+= copy[1] - copy[2];
>
> return result;
> }
> void deleteTree() { delete children; }
> int[] children;
>
> private int item;
> }
>
>
> void main(string[] args) {
> const minDepth = 4;
> int n = (args.length > 1) ? toInt(args[1]) : 2;
> int maxDepth = (minDepth + 2) > n ? minDepth + 2 : n;
>
> auto t = Tree.bottumUpTree(0, maxDepth + 1);
> writefln("stretch tree of depth ", maxDepth + 1, "\t check: ",
> t.check());
> t.deleteTree();
>
> auto longLivedTree = Tree.bottumUpTree(0, maxDepth);
>
> for (int depth = minDepth; depth <= maxDepth; depth += 2)
> {
> int check;
> int iterations = 1 << (maxDepth - depth + minDepth);
>
>
> for (int i = 1; i <= iterations; i++)
> {
> auto t1 = Tree.bottumUpTree(i, depth);
> check += t1.check();
> t1.deleteTree();
> auto t2 = Tree.bottumUpTree(-i, depth);
> check += t2.check();
> t2.deleteTree();
> }
>
> writefln(iterations * 2, "\t trees of depth ", depth, "\t check:
> ", check);
> }
>
> writefln("long lived tree of depth ", maxDepth, "\t check: ",
> longLivedTree.check);
> longLivedTree.deleteTree();
> }
Here's an array-based C++ implementation from the shootout. It performs the
best but was disqualified because it allocates everything in one big chunk
and then uses placement new to allocate each node.
/* The Computer Language Shootout
* http://shootout.alioth.debian.org/
* Contributed by Paul Kitchin
*/
#include <iostream>
#include <sstream>
class Tree
{
struct Node
{
Node(int value, std::size_t depth, std::size_t index, Node * nodes,
std::size_t max)
:
value(value)
{
if (index * 2 + 2 < max)
{
new (nodes + index * 2 + 1) Node(2 * value - 1, depth - 1,
index * 2 + 1, nodes, max);
new (nodes + index * 2 + 2) Node(2 * value, depth - 1, index
* 2 + 2, nodes, max);
}
}
int check(std::size_t index, Node * nodes, std::size_t max) const
{
if (index * 2 + 2 < max)
{
return nodes[index * 2 + 1].check(index * 2 + 1, nodes, max)
+ value - nodes[index * 2 + 2].check(index * 2 + 2, nodes, max);
}
return value;
}
int value;
};
public:
Tree(int value, std::size_t depth)
:
size((2 << depth) - 1),
nodes(static_cast< Node * >(operator new(size * sizeof(Node))))
{
new (nodes) Node(value, depth, 0, nodes, size);
}
~Tree()
{
operator delete(nodes);
}
int check() const
{
return nodes->check(0, nodes, size);
}
private:
std::size_t size;
Node * nodes;
};
int main(int argc, char * * argv)
{
std::size_t user_depth = 10;
if (argc == 2)
{
std::istringstream convertor(argv[1]);
if (!(convertor >> user_depth) || !convertor.eof())
{
std::cerr << "Usage: " << argv[0] << " [n]\n";
std::cerr << "\tn must be an integer\n";
return 1;
}
}
std::size_t minimum_depth = 4;
std::size_t maximum_depth = std::max(minimum_depth + 2, user_depth);
{
Tree tree(0, maximum_depth + 1);
std::cout << "stretch tree of depth " << (maximum_depth + 1) << "\t
check: " << tree.check() << '\n';
}
Tree long_lived_tree(0, maximum_depth);
for (std::size_t depth = minimum_depth; depth <= maximum_depth; depth +=
2)
{
int iterations = 1 << (maximum_depth - depth + minimum_depth);
int check = 0;
for (int iteration = 1; iteration <= iterations; ++iteration)
{
Tree first(iteration, depth);
Tree second(-iteration, depth);
check += first.check() + second.check();
}
std::cout << (2 * iterations) << "\t trees of depth " << depth << "\t
check: " << check << '\n';
}
std::cout << "long lived tree of depth " << maximum_depth << "\t check: "
<< long_lived_tree.check() << '\n';
}
More information about the Digitalmars-d
mailing list