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