M
Michael Cornelison
I believe I have found a serious performance
problem with heap management in C++ .Net.
I have an application does the following
thousands of times:
vint = new int[nn];
vchar = new char[nn];
The performance of these vector creations varies by
a factor of 40 or more. It is also sensitive to the
size and ratios in which the vectors are created.
Has anyone else had this problem?
I wrote a minimum console application to isolate
and validate the problem. Cycle this program 10 times
or more. The run time is about 0.3 seconds for the
first few iterations, then it increases to 16 seconds
per cycle and remains there.
This is NOT a problem with memory leak or memory
paging (the code is simple enough to rule this out).
I have also validated that no memory is leaking and
no paging occurs.
I speculate that if heap memory gets fragmented in
a certain way, then memory being released is not
properly consolidated, and allocation becomes slow.
I found no obvious way to send this bug report to
Microsoft. Any hints? Would they even want it?
/*******************************************
C++ test program for "new" (constructor).
Test C++ .Net heap memory management.
*******************************************/
#include <windows.h>
#include <conio.h>
#include <stdio.h>
#include <tchar.h>
int _tmain(int argc, char * argv[])
{
int Nv = 500000; // pointer count
int mdd = 200; // max int vector
int mcc = 200; // max. char vector
int Nii = 1; // int arrays to allocate
int Ncc = 50; // char arrays to allocate
void ** pvoid;
int * pint;
char * pchar;
int dd, cc, seed, bytes, ii, jj, check, errs;
double secs = 0.0;
char YN;
start:
printf("\n C++ memory management test \n");
printf("loading memory \n");
seed = 4444;
srand(seed);
bytes = 0;
secs = double(GetTickCount()); // start timer
pvoid = new void * [Nv]; // allocate pointers
bytes += 8 + Nv * 4;
for (ii = 0; ii < Nv; ) // index thru pointers
{
for (jj = ii; (jj < ii + Nii) && (jj < Nv); jj++)
{
dd = 2 + rand() % mdd;
pint = new int[dd]; // allocate ints
pvoid[jj] = (void *) pint; // set pointer
check = jj;
pint[0] = check; // add check data
pint[dd-1] = -check;
bytes += 8 + dd * 4;
}
ii = jj;
for (jj = ii; (jj < ii + Ncc) && (jj < Nv); jj++)
{
cc = 2 + rand() % mcc;
pchar = new char[cc]; // allocate chars
pvoid[jj] = (void *) pchar; // set pointer
check = jj % 128;
pchar[0] = check; // add check data
pchar[cc-1] = -check;
bytes += 8 + cc+2;
}
ii = jj;
}
secs = (double(GetTickCount()) - secs) / 1000.0;
printf("seconds: %.3f bytes: %d \n",secs,bytes);
printf("releasing memory \n");
srand(seed); // re-generate same randoms
errs = 0;
secs = double(GetTickCount());
for (ii = 0; ii < Nv; ) // index thru pointers
{
for (jj = ii; (jj < ii + Nii) && (jj < Nv); jj++)
{
dd = 2 + rand() % mdd;
pint = (int *) pvoid[jj]; // get ints
check = jj; // validate
if (pint[0] != check) errs++;
if (pint[dd-1] != -check) errs++;
delete [] pint; // delete
}
ii = jj;
for (jj = ii; (jj < ii + Ncc) && (jj < Nv); jj++)
{
cc = 2 + rand() % mcc;
pchar = (char *) pvoid[jj]; // get chars
check = jj % 128; // validate
if (pchar[0] != check) errs++;
if (pchar[cc-1] != -check) errs++;
delete [] pchar; // delete
}
ii = jj;
}
delete [] pvoid; // delete array of pointers
secs = (double(GetTickCount()) - secs) / 1000.0;
printf("seconds: %.3f \n",secs);
printf("errors: %d \n\n",errs);
printf("enter Y to test again ");
YN = getche();
if ((YN == 'Y') || (YN == 'y')) goto start;
return 0;
}
problem with heap management in C++ .Net.
I have an application does the following
thousands of times:
vint = new int[nn];
vchar = new char[nn];
The performance of these vector creations varies by
a factor of 40 or more. It is also sensitive to the
size and ratios in which the vectors are created.
Has anyone else had this problem?
I wrote a minimum console application to isolate
and validate the problem. Cycle this program 10 times
or more. The run time is about 0.3 seconds for the
first few iterations, then it increases to 16 seconds
per cycle and remains there.
This is NOT a problem with memory leak or memory
paging (the code is simple enough to rule this out).
I have also validated that no memory is leaking and
no paging occurs.
I speculate that if heap memory gets fragmented in
a certain way, then memory being released is not
properly consolidated, and allocation becomes slow.
I found no obvious way to send this bug report to
Microsoft. Any hints? Would they even want it?
/*******************************************
C++ test program for "new" (constructor).
Test C++ .Net heap memory management.
*******************************************/
#include <windows.h>
#include <conio.h>
#include <stdio.h>
#include <tchar.h>
int _tmain(int argc, char * argv[])
{
int Nv = 500000; // pointer count
int mdd = 200; // max int vector
int mcc = 200; // max. char vector
int Nii = 1; // int arrays to allocate
int Ncc = 50; // char arrays to allocate
void ** pvoid;
int * pint;
char * pchar;
int dd, cc, seed, bytes, ii, jj, check, errs;
double secs = 0.0;
char YN;
start:
printf("\n C++ memory management test \n");
printf("loading memory \n");
seed = 4444;
srand(seed);
bytes = 0;
secs = double(GetTickCount()); // start timer
pvoid = new void * [Nv]; // allocate pointers
bytes += 8 + Nv * 4;
for (ii = 0; ii < Nv; ) // index thru pointers
{
for (jj = ii; (jj < ii + Nii) && (jj < Nv); jj++)
{
dd = 2 + rand() % mdd;
pint = new int[dd]; // allocate ints
pvoid[jj] = (void *) pint; // set pointer
check = jj;
pint[0] = check; // add check data
pint[dd-1] = -check;
bytes += 8 + dd * 4;
}
ii = jj;
for (jj = ii; (jj < ii + Ncc) && (jj < Nv); jj++)
{
cc = 2 + rand() % mcc;
pchar = new char[cc]; // allocate chars
pvoid[jj] = (void *) pchar; // set pointer
check = jj % 128;
pchar[0] = check; // add check data
pchar[cc-1] = -check;
bytes += 8 + cc+2;
}
ii = jj;
}
secs = (double(GetTickCount()) - secs) / 1000.0;
printf("seconds: %.3f bytes: %d \n",secs,bytes);
printf("releasing memory \n");
srand(seed); // re-generate same randoms
errs = 0;
secs = double(GetTickCount());
for (ii = 0; ii < Nv; ) // index thru pointers
{
for (jj = ii; (jj < ii + Nii) && (jj < Nv); jj++)
{
dd = 2 + rand() % mdd;
pint = (int *) pvoid[jj]; // get ints
check = jj; // validate
if (pint[0] != check) errs++;
if (pint[dd-1] != -check) errs++;
delete [] pint; // delete
}
ii = jj;
for (jj = ii; (jj < ii + Ncc) && (jj < Nv); jj++)
{
cc = 2 + rand() % mcc;
pchar = (char *) pvoid[jj]; // get chars
check = jj % 128; // validate
if (pchar[0] != check) errs++;
if (pchar[cc-1] != -check) errs++;
delete [] pchar; // delete
}
ii = jj;
}
delete [] pvoid; // delete array of pointers
secs = (double(GetTickCount()) - secs) / 1000.0;
printf("seconds: %.3f \n",secs);
printf("errors: %d \n\n",errs);
printf("enter Y to test again ");
YN = getche();
if ((YN == 'Y') || (YN == 'y')) goto start;
return 0;
}