Large memory allocations
Kagamin
spam at here.lot
Sun Nov 16 03:55:47 PST 2008
lol, quot damage!
Janderson Wrote:
> bearophile wrote:
> > While allocating lot of memory for a little memory-hungry program, I have found results that I don't understand. So I have written the following test programs. Maybe someone can give me some information on the matter.
> > I am using a default install of a 32 bit Win XP with 2 GB RAM (so for example I can't allocate 3 GB of RAM). (I presume answers to my questions are Windows-related).
> >
> > From C (MinGW 4.2.1) this is about the largest memory block I can allocate (even it swaps and requires 7+ seconds to run), 1_920_000_000 bytes:
> >
> > #include "stdio.h"
> > #include "stdlib.h"
> > #define N 480000000
> > int main() {
> > unsigned int* a = (unsigned int*)malloc(N * sizeof(unsigned int));
> > unsigned int i;
> > if (a != NULL)
> > for (i = 0; i < N; ++i)
> > a[i] = i;
> > else
> > printf("null!");
> > return 0;
> > }
> >
> >
> > But from D this is about the largest memory block I can allocate with std.c.stdlib.malloc, 1_644_000_000 bytes, do you know why the difference?
> >
> > //import std.gc: malloc;
> > import std.c.stdlib: malloc;
> > void main() {
> > const uint N = 411_000_000;
> > uint* a = cast(uint*)malloc(N * uint.sizeof);
> > if (a !is null)
> > for (uint i; i < N; ++i)
> > a[i] = i;
> > else
> > printf("null!");
> > }
> >
> > (If I use std.gc.malloc the situation is different yet, and generally worse).
> >
> > -----------------------
> >
> > So I have tried to use a sequence of smaller memory blocks, this is the C code (every block is about 1 MB):
> >
> > #include "stdio.h"
> > #include "stdlib.h"
> >
> > #define N 250000
> >
> > int main(int argc, char** argv) {
> > unsigned int i, j;
> > unsigned int m = argc == 2 ? atoi(argv[1]) : 100;
> >
> > for (j = 0; j < m; ++j) {
> > unsigned int* a = (unsigned int*)malloc(N * sizeof(unsigned int));
> >
> > if (a != NULL) {
> > for (i = 0; i < N; ++i)
> > a[i] = i;
> > } else {
> > printf("null! %d\n", j);
> > break;
> > }
> > }
> >
> > return 0;
> > }
> >
> >
> > And the D code:
> >
> > //import std.gc: malloc;
> > import std.c.stdlib: malloc;
> > import std.conv: toUint;
> >
> > void main(string[] args) {
> > const uint N = 250_000;
> > uint m = toUint(args[1]);
> >
> > for (uint j; j < m; ++j) {
> > uint* a = cast(uint*)malloc(N * uint.sizeof);
> >
> > if (a !is null) {
> > for (uint i; i < N; ++i)
> > a[i] = i;
> > } else {
> > printf("null! %d\n", j);
> > break;
> > }
> > }
> > }
> >
> > With such code I can allocate 1_708_000_000 bytes from D and up to 2_038_000_000 bytes from C (but near the last 100-200 MB of RAM the C code swaps a lot).
> > So can't I can't use all my RAM from my D code? And do you know why?
> >
> > Bye,
> > bearophile
>
>
> bearophile wrote:
> > While allocating lot of memory for a little memory-hungry program, I
> have found results that I don't understand. So I have written the
> following test programs. Maybe someone can give me some information on
> the matter.
> > I am using a default install of a 32 bit Win XP with 2 GB RAM (so for
> example I can't allocate 3 GB of RAM). (I presume answers to my
> questions are Windows-related).
> >
> > From C (MinGW 4.2.1) this is about the largest memory block I can
> allocate (even it swaps and requires 7+ seconds to run), 1_920_000_000
> bytes:
> >
> > #include "stdio.h"
> > #include "stdlib.h"
> > #define N 480000000
> > int main() {
> > unsigned int* a = (unsigned int*)malloc(N * sizeof(unsigned int));
> > unsigned int i;
> > if (a != NULL)
> > for (i = 0; i < N; ++i)
> > a[i] = i;
> > else
> > printf("null!");
> > return 0;
> > }
> >
> >
> > But from D this is about the largest memory block I can allocate with
> std.c.stdlib.malloc, 1_644_000_000 bytes, do you know why the difference?
> >
> > //import std.gc: malloc;
> > import std.c.stdlib: malloc;
> > void main() {
> > const uint N = 411_000_000;
> > uint* a = cast(uint*)malloc(N * uint.sizeof);
> > if (a !is null)
> > for (uint i; i < N; ++i)
> > a[i] = i;
> > else
> > printf("null!");
> > }
> >
> > (If I use std.gc.malloc the situation is different yet, and generally
> worse).
> >
> > -----------------------
> >
> > So I have tried to use a sequence of smaller memory blocks, this is
> the C code (every block is about 1 MB):
> >
> > #include "stdio.h"
> > #include "stdlib.h"
> >
> > #define N 250000
> >
> > int main(int argc, char** argv) {
> > unsigned int i, j;
> > unsigned int m = argc == 2 ? atoi(argv[1]) : 100;
> >
> > for (j = 0; j < m; ++j) {
> > unsigned int* a = (unsigned int*)malloc(N * sizeof(unsigned
> int));
> >
> > if (a != NULL) {
> > for (i = 0; i < N; ++i)
> > a[i] = i;
> > } else {
> > printf("null! %d\n", j);
> > break;
> > }
> > }
> >
> > return 0;
> > }
> >
> >
> > And the D code:
> >
> > //import std.gc: malloc;
> > import std.c.stdlib: malloc;
> > import std.conv: toUint;
> >
> > void main(string[] args) {
> > const uint N = 250_000;
> > uint m = toUint(args[1]);
> >
> > for (uint j; j < m; ++j) {
> > uint* a = cast(uint*)malloc(N * uint.sizeof);
> >
> > if (a !is null) {
> > for (uint i; i < N; ++i)
> > a[i] = i;
> > } else {
> > printf("null! %d\n", j);
> > break;
> > }
> > }
> > }
> >
> > With such code I can allocate 1_708_000_000 bytes from D and up to
> 2_038_000_000 bytes from C (but near the last 100-200 MB of RAM the C
> code swaps a lot).
> > So can't I can't use all my RAM from my D code? And do you know why?
> >
> > Bye,
> > bearophile
>
> Different allocation schemes have different strengths and weaknesses.
> Some are fast, some fragment less, some have less overhead, some allow
> larger sized blocks. Often these things arn't mutual so there are
> always tradoffs. For example, to improve speed an allocator may
> allocate into particular buckets which might restrict the maximum size
> of one allocation.
>
> I wonder how Ned-Malloc or Hord perform with your tests?
>
> -Joel
More information about the Digitalmars-d-learn
mailing list