mirror of
https://github.com/dlang/phobos.git
synced 2025-05-08 03:56:54 +03:00
567 lines
10 KiB
D
567 lines
10 KiB
D
|
|
// Copyright (C) 2001-2006 by Digital Mars
|
|
// All Rights Reserved
|
|
// Written by Walter Bright
|
|
// www.digitalmars.com
|
|
|
|
// GC tester program
|
|
|
|
import std.c.stdio;
|
|
import std.c.stdlib;
|
|
import std.c.string;
|
|
import std.string;
|
|
|
|
import gcstats;
|
|
import std.gc;
|
|
import gcx;
|
|
import std.random;
|
|
|
|
alias GC gc_t;
|
|
//alias GC* gc_t;
|
|
|
|
gc_t newGC()
|
|
{
|
|
version (all)
|
|
{ void* p;
|
|
ClassInfo ci = GC.classinfo;
|
|
|
|
p = std.c.stdlib.malloc(ci.init.length);
|
|
(cast(byte*)p)[0 .. ci.init.length] = ci.init[];
|
|
return cast(GC)p;
|
|
}
|
|
else
|
|
{
|
|
return cast(gc_t)std.c.stdlib.calloc(1, GC.sizeof);
|
|
}
|
|
}
|
|
|
|
void deleteGC(gc_t gc)
|
|
{
|
|
gc.Dtor();
|
|
std.c.stdlib.free(cast(void*)gc);
|
|
}
|
|
|
|
void printStats(gc_t gc)
|
|
{
|
|
GCStats stats;
|
|
|
|
//gc.getStats(stats);
|
|
printf("poolsize = x%x, usedsize = x%x, freelistsize = x%x, freeblocks = %d, pageblocks = %d\n",
|
|
stats.poolsize, stats.usedsize, stats.freelistsize, stats.freeblocks, stats.pageblocks);
|
|
}
|
|
|
|
uint PERMUTE(uint key)
|
|
{
|
|
return key + 1;
|
|
}
|
|
|
|
void fill(void *p, uint key, uint size)
|
|
{
|
|
uint i;
|
|
byte *q = cast(byte *)p;
|
|
|
|
for (i = 0; i < size; i++)
|
|
{
|
|
key = PERMUTE(key);
|
|
q[i] = cast(byte)key;
|
|
}
|
|
}
|
|
|
|
void verify(void *p, uint key, uint size)
|
|
{
|
|
uint i;
|
|
byte *q = cast(byte *)p;
|
|
|
|
for (i = 0; i < size; i++)
|
|
{
|
|
key = PERMUTE(key);
|
|
assert(q[i] == cast(byte)key);
|
|
}
|
|
}
|
|
|
|
long desregs()
|
|
{
|
|
return strlen("foo");
|
|
}
|
|
|
|
/* ---------------------------- */
|
|
|
|
void smoke()
|
|
{
|
|
gc_t gc;
|
|
|
|
printf("--------------------------smoke()\n");
|
|
|
|
gc = newGC();
|
|
deleteGC(gc);
|
|
printf("smoke.1\n");
|
|
|
|
gc = newGC();
|
|
gc.initialize();
|
|
deleteGC(gc);
|
|
printf("smoke.2\n");
|
|
|
|
gc = newGC();
|
|
gc.initialize();
|
|
char *p = cast(char *)gc.malloc(10);
|
|
assert(p);
|
|
strcpy(p, "Hello!");
|
|
// char *p2 = gc.strdup(p);
|
|
// printf("p2 = %x, '%s'\n", p2, p2);
|
|
// int result = strcmp(p, p2);
|
|
// assert(result == 0);
|
|
// gc.strdup(p);
|
|
|
|
printf("p = %x\n", p);
|
|
p = null;
|
|
gc.fullCollect();
|
|
printStats(gc);
|
|
|
|
deleteGC(gc);
|
|
}
|
|
|
|
/* ---------------------------- */
|
|
|
|
void finalizer(void *p, bool dummy)
|
|
{
|
|
}
|
|
|
|
void smoke2()
|
|
{
|
|
gc_t gc;
|
|
int *p;
|
|
int i;
|
|
|
|
const int SMOKE2_SIZE = 100;
|
|
int *foo[SMOKE2_SIZE];
|
|
|
|
printf("--------------------------smoke2()\n");
|
|
|
|
gc = newGC();
|
|
gc.initialize();
|
|
|
|
for (i = 0; i < SMOKE2_SIZE; i++)
|
|
{
|
|
p = cast(int *)gc.calloc(i + 1, 500);
|
|
p[0] = i * 3;
|
|
foo[i] = p;
|
|
gc.setFinalizer(cast(void *)p, &finalizer);
|
|
}
|
|
|
|
for (i = 0; i < SMOKE2_SIZE; i += 2)
|
|
{
|
|
p = foo[i];
|
|
if (p[0] != i * 3)
|
|
{
|
|
printf("p = %x, i = %d, p[0] = %d\n", p, i, p[0]);
|
|
//c.stdio.fflush(stdout);
|
|
}
|
|
assert(p[0] == i * 3);
|
|
gc.free(p);
|
|
}
|
|
|
|
p = null;
|
|
foo[] = null;
|
|
|
|
gc.fullCollect();
|
|
printStats(gc);
|
|
|
|
deleteGC(gc);
|
|
}
|
|
|
|
/* ---------------------------- */
|
|
|
|
void smoke3()
|
|
{
|
|
gc_t gc;
|
|
int *p;
|
|
int i;
|
|
|
|
printf("--------------------------smoke3()\n");
|
|
|
|
gc = newGC();
|
|
gc.initialize();
|
|
|
|
// for (i = 0; i < 1000000; i++)
|
|
for (i = 0; i < 1000; i++)
|
|
{
|
|
uint size = std.random.rand() % 2048;
|
|
p = cast(int *)gc.malloc(size);
|
|
memset(p, i, size);
|
|
|
|
size = std.random.rand() % 2048;
|
|
p = cast(int *)gc.realloc(p, size);
|
|
memset(p, i + 1, size);
|
|
}
|
|
|
|
p = null;
|
|
desregs();
|
|
gc.fullCollect();
|
|
printStats(gc);
|
|
|
|
deleteGC(gc);
|
|
}
|
|
|
|
/* ---------------------------- */
|
|
|
|
void smoke4()
|
|
{
|
|
gc_t gc;
|
|
int *p;
|
|
int i;
|
|
|
|
printf("--------------------------smoke4()\n");
|
|
|
|
gc = newGC();
|
|
gc.initialize();
|
|
|
|
for (i = 0; i < 80000; i++)
|
|
{
|
|
uint size = i;
|
|
p = cast(int *)gc.malloc(size);
|
|
memset(p, i, size);
|
|
|
|
size = std.random.rand() % 2048;
|
|
gc.check(p);
|
|
p = cast(int *)gc.realloc(p, size);
|
|
memset(p, i + 1, size);
|
|
}
|
|
|
|
p = null;
|
|
desregs();
|
|
gc.fullCollect();
|
|
printStats(gc);
|
|
|
|
deleteGC(gc);
|
|
}
|
|
|
|
/* ---------------------------- */
|
|
|
|
void smoke5(gc_t gc)
|
|
{
|
|
byte *p;
|
|
int i;
|
|
int j;
|
|
const int SMOKE5_SIZE = 1000;
|
|
byte *array[SMOKE5_SIZE];
|
|
uint offset[SMOKE5_SIZE];
|
|
|
|
printf("--------------------------smoke5()\n");
|
|
//printf("gc = %p\n", gc);
|
|
//printf("gc = %p, gcx = %p, self = %x\n", gc, gc.gcx, gc.gcx.self);
|
|
|
|
for (j = 0; j < 20; j++)
|
|
{
|
|
for (i = 0; i < 2000 /*4000*/; i++)
|
|
{
|
|
uint size = (std.random.rand() % 2048) + 1;
|
|
uint index = std.random.rand() % SMOKE5_SIZE;
|
|
|
|
//printf("index = %d, size = %d\n", index, size);
|
|
p = array[index] - offset[index];
|
|
p = cast(byte *)gc.realloc(p, size);
|
|
if (array[index])
|
|
{ uint s;
|
|
|
|
//printf("\tverify = %d\n", p[0]);
|
|
s = offset[index];
|
|
if (size < s)
|
|
s = size;
|
|
verify(p, index, s);
|
|
}
|
|
array[index] = p;
|
|
fill(p, index, size);
|
|
offset[index] = std.random.rand() % size;
|
|
array[index] += offset[index];
|
|
|
|
//printf("p[0] = %d\n", p[0]);
|
|
}
|
|
gc.fullCollect();
|
|
}
|
|
|
|
p = null;
|
|
array[] = null;
|
|
gc.fullCollect();
|
|
printStats(gc);
|
|
}
|
|
|
|
/* ---------------------------- */
|
|
|
|
void test1()
|
|
{
|
|
printf("test1()\n");
|
|
char[] a=new char[0];
|
|
uint c = 200000;
|
|
while (c--)
|
|
a ~= 'x';
|
|
//printf("a = '%.*s'\n", a);
|
|
printf("test1() done\n");
|
|
}
|
|
|
|
/* ---------------------------- */
|
|
|
|
void test2()
|
|
{
|
|
char[] str;
|
|
|
|
for (int i = 0; i < 10_000; i++)
|
|
str = str ~ "ABCDEFGHIJKLMNOPQRST";
|
|
}
|
|
|
|
/* ---------------------------- */
|
|
|
|
/* The Great Computer Language Shootout
|
|
http://shootout.alioth.debian.org/
|
|
|
|
http://www.bagley.org/~doug/shootout/
|
|
|
|
converted to D by Dave Fladebo
|
|
compile: dmd -O -inline -release hash.d
|
|
*/
|
|
|
|
|
|
void test3()
|
|
{
|
|
int n = 1000;
|
|
|
|
char[32] str;
|
|
int[char[]] X;
|
|
|
|
for(int i = 1; i <= n; i++) {
|
|
int len = sprintf(str.ptr,"%x",i);
|
|
X[str[0..len].dup] = i;
|
|
}
|
|
|
|
int c;
|
|
for(int i = n; i > 0; i--) {
|
|
int len = sprintf(str.ptr,"%d",i);
|
|
if(str[0..len] in X) c++;
|
|
}
|
|
|
|
printf("%d\n", c);
|
|
}
|
|
|
|
/* ---------------------------- */
|
|
|
|
void test4()
|
|
{
|
|
const int iters = 1_000_000;
|
|
C[] c = new C[iters];
|
|
int i;
|
|
for(i = 0; i < iters; i++)
|
|
{
|
|
c[i] = new C;
|
|
delete c[i];
|
|
}
|
|
printf("%d\n", i);
|
|
}
|
|
|
|
class C
|
|
{
|
|
int i, j, k;
|
|
real l, m, n;
|
|
}
|
|
|
|
/* ---------------------------- */
|
|
|
|
/* The Computer Language Shootout Benchmarks
|
|
http://shootout.alioth.debian.org/
|
|
|
|
contributed by Dave Fladebo
|
|
compile: dmd -O -inline -release binarytrees.d
|
|
*/
|
|
|
|
|
|
int test5()
|
|
{
|
|
TreeNode* stretchTree, longLivedTree, tempTree;
|
|
int depth, minDepth, maxDepth, stretchDepth, N = 1;
|
|
|
|
minDepth = 4;
|
|
maxDepth = (minDepth + 2) > N ? minDepth + 2 : N;
|
|
stretchDepth = maxDepth + 1;
|
|
|
|
stretchTree = TreeNode.BottomUpTree(0, stretchDepth);
|
|
printf("stretch tree of depth %d\t check: %d\n", stretchDepth, stretchTree.ItemCheck);
|
|
//TreeNode.DeleteTree(stretchTree);
|
|
|
|
longLivedTree = TreeNode.BottomUpTree(0, maxDepth);
|
|
|
|
for(depth = minDepth; depth <= maxDepth; depth += 2)
|
|
{
|
|
int check, iterations = 1 << (maxDepth - depth + minDepth);
|
|
|
|
for(int i = 0; i < iterations; i++)
|
|
{
|
|
tempTree = TreeNode.BottomUpTree(i, depth);
|
|
check += tempTree.ItemCheck;
|
|
//TreeNode.DeleteTree(tempTree);
|
|
|
|
tempTree = TreeNode.BottomUpTree(-i, depth);
|
|
check += tempTree.ItemCheck;
|
|
//TreeNode.DeleteTree(tempTree);
|
|
}
|
|
|
|
//printf(iterations * 2,"\t trees of depth ",depth,"\t check: ",check);
|
|
}
|
|
|
|
//writefln("long lived tree of depth ",maxDepth,"\t check: ",longLivedTree.ItemCheck);
|
|
|
|
return 0;
|
|
}
|
|
|
|
struct TreeNode
|
|
{
|
|
public:
|
|
static TreeNode* BottomUpTree(int item, int depth)
|
|
{
|
|
if(depth > 0)
|
|
return TreeNode(item
|
|
,BottomUpTree(2 * item - 1, depth - 1)
|
|
,BottomUpTree(2 * item, depth - 1));
|
|
return TreeNode(item);
|
|
}
|
|
|
|
int ItemCheck()
|
|
{
|
|
if(left)
|
|
return item + left.ItemCheck() - right.ItemCheck();
|
|
return item;
|
|
}
|
|
|
|
static void DeleteTree(TreeNode* tree)
|
|
{
|
|
if(tree.left)
|
|
{
|
|
DeleteTree(tree.left);
|
|
DeleteTree(tree.right);
|
|
}
|
|
|
|
delete tree;
|
|
}
|
|
|
|
private:
|
|
TreeNode* left, right;
|
|
int item;
|
|
|
|
static TreeNode* opCall(int item, TreeNode* left = null, TreeNode* right = null)
|
|
{
|
|
TreeNode* t = new TreeNode;
|
|
t.left = left;
|
|
t.right = right;
|
|
t.item = item;
|
|
return t;
|
|
}
|
|
|
|
//new(uint sz)
|
|
//{
|
|
// return std.c.stdlib.malloc(sz);
|
|
//}
|
|
|
|
//delete(void* p)
|
|
//{
|
|
// free(p);
|
|
//}
|
|
}
|
|
|
|
/* ---------------------------- */
|
|
|
|
void test6()
|
|
{
|
|
printf("test6\n");
|
|
|
|
gc_t gc;
|
|
|
|
gc = newGC();
|
|
gc.initialize();
|
|
|
|
auto p = gc.malloc(4096);
|
|
assert(gc.capacity(p) == 4096);
|
|
memset(p, 3, 4096);
|
|
|
|
auto q = gc.realloc(p, 4096*4);
|
|
assert(q == p);
|
|
assert(gc.capacity(p) == 4096*4);
|
|
memset(p, 4, 4096*4);
|
|
|
|
q = gc.realloc(p, 4096*2);
|
|
assert(q == p);
|
|
assert(gc.capacity(p) == 4096*2);
|
|
memset(p, 5, 4096*2);
|
|
|
|
q = gc.realloc(p, 4096*2 + 1000);
|
|
assert(q == p);
|
|
assert(gc.capacity(p) == 4096*3);
|
|
memset(p, 6, 4096*2 + 1000);
|
|
|
|
q = gc.realloc(p, 4096*4);
|
|
assert(q == p);
|
|
assert(gc.capacity(p) == 4096*4);
|
|
memset(p, 7, 4096*4);
|
|
|
|
q = gc.realloc(p, 0);
|
|
assert(q == null);
|
|
assert(gc.capacity(p) == 0);
|
|
|
|
gc.fullCollect();
|
|
deleteGC(gc);
|
|
}
|
|
|
|
/* ---------------------------- */
|
|
|
|
void test7()
|
|
{
|
|
printf("test7\n");
|
|
|
|
gc_t gc;
|
|
|
|
gc = newGC();
|
|
gc.initialize();
|
|
|
|
auto p = gc.malloc(4096);
|
|
assert(gc.capacity(p) == 4096);
|
|
memset(p, 3, 4096);
|
|
|
|
auto q = gc.extend(p, 4096, 4096*2);
|
|
assert(q == 4096*2 || q == 4096*3);
|
|
|
|
auto s = gc.malloc(4096);
|
|
q = gc.extend(p, 4096, 4096);
|
|
assert(q == 0);
|
|
|
|
gc.fullCollect();
|
|
deleteGC(gc);
|
|
}
|
|
|
|
/* ---------------------------- */
|
|
|
|
int main(char[][] args)
|
|
{
|
|
test1();
|
|
test2();
|
|
test3();
|
|
test4();
|
|
test5();
|
|
test6();
|
|
test7();
|
|
|
|
gc_t gc;
|
|
|
|
printf("GC test start\n");
|
|
|
|
gc = newGC();
|
|
printf("gc = %p\n", gc);
|
|
gc.initialize();
|
|
|
|
smoke();
|
|
smoke2();
|
|
smoke3();
|
|
smoke4();
|
|
printf("gc = %p\n", gc);
|
|
smoke5(gc);
|
|
|
|
deleteGC(gc);
|
|
|
|
printf("GC test success\n");
|
|
return EXIT_SUCCESS;
|
|
}
|