digitalmars.D.learn - Memory allocation faile on string concat
- Xie (17/17) Nov 10 2010 Can't run a simple program. What's wrong, GC?
- Jonathan M Davis (10/32) Nov 10 2010 You just tried to create an array with 100_000_000 elements, and arrays ...
- Steven Schveighoffer (20/36) Nov 10 2010 The results on my machine with 1G of memory is that it consumes 2G of
- Steven Schveighoffer (10/49) Nov 10 2010 Waaaait a second, a is not a wstring, it's an *array* of wstrings. That...
- Xie (17/17) Nov 10 2010 Sorry, it a mistypo (i began from wchar[], later changed to wstring)
- Steven Schveighoffer (16/33) Nov 10 2010 OK, this actually makes sense to me.
- Xie (4/7) Nov 10 2010 I'm think - it's truth but not at all.
- Steven Schveighoffer (5/12) Nov 11 2010 Yes, this is what the bug report is about -- the memory is not collected...
- Steven Schveighoffer (18/33) Dec 23 2010 OK, so I have actually implemented a fix for bug 3929. Essentially, the...
- sybrandy (6/23) Nov 10 2010 In addition to what everybody else is suggesting you look at, you may
- Steven Schveighoffer (5/32) Nov 10 2010 Just tried it, Appender is actually slower. This *is* a problem, it
- Steven Schveighoffer (8/11) Nov 10 2010 More data, Appender taking an array of elements is significantly slower ...
Can't run a simple program. What's wrong, GC? import std.stdio; import std.date; void f0() { wstring a[]; foreach(i; 0 .. 100_000_000) { a ~= " "w; } } void main() { auto r = benchmark!(f0)(1); writeln(r, "ms"); } DMD 2.047
Nov 10 2010
On Wednesday, November 10, 2010 08:33:45 Xie wrote:Can't run a simple program. What's wrong, GC? import std.stdio; import std.date; void f0() { wstring a[]; foreach(i; 0 .. 100_000_000) { a ~= " "w; } } void main() { auto r = benchmark!(f0)(1); writeln(r, "ms"); } DMD 2.047You just tried to create an array with 100_000_000 elements, and arrays try and maintain extra capacity for extra appending, so you're actually trying to create one bigger than that. That's a _lot_ of memory, and it's _contiguous_ memory. You probably hit some sort of memory limit in there somewhere and would have the same problem if you tried to create an array that large in C or C++. That's an _enormous_ array. Maybe it's a 32-bit barrier which will go away once 64-bit dmd is complete, but it's not exactly normal to try and use an array wich 100 million elements in it. The computer does have limits you know. - Jonathan M Davis
Nov 10 2010
On Wed, 10 Nov 2010 11:33:45 -0500, Xie <xiemargl gmail.com> wrote:Can't run a simple program. What's wrong, GC? import std.stdio; import std.date; void f0() { wstring a[]; foreach(i; 0 .. 100_000_000) { a ~= " "w; } } void main() { auto r = benchmark!(f0)(1); writeln(r, "ms"); }The results on my machine with 1G of memory is that it consumes 2G of memory and the system starts thrashing. I changed the value to 10_000_000, and it runs in a couple seconds, I change it to 50_000_000 and it runs in 200 seconds. Something is definitely amiss here, because the following doesn't help (it still consumes 1.2GB of memory): void f0() { wstring a[]; a.reserve(100_000_000); foreach(i; 0 .. 100_000_000) { a ~= " "w; } } This should take the explosive nature of appending out of the equation, because a reallocation should never occur. I'll look into it. -Steve
Nov 10 2010
On Wed, 10 Nov 2010 13:33:11 -0500, Steven Schveighoffer <schveiguy yahoo.com> wrote:On Wed, 10 Nov 2010 11:33:45 -0500, Xie <xiemargl gmail.com> wrote:Waaaait a second, a is not a wstring, it's an *array* of wstrings. That's completely different. This all makes sense now. It's not 200MB, it's 800MB your code is asking for. This might be a bit much for a test, a 32-bit system only supports 4GB of address space, and usually 1GB is reserved, so you are trying to allocate about 1/3 of the memory you could possibly allocate. Is there any reason you expect this to perform well? -SteveCan't run a simple program. What's wrong, GC? import std.stdio; import std.date; void f0() { wstring a[]; foreach(i; 0 .. 100_000_000) { a ~= " "w; } } void main() { auto r = benchmark!(f0)(1); writeln(r, "ms"); }The results on my machine with 1G of memory is that it consumes 2G of memory and the system starts thrashing. I changed the value to 10_000_000, and it runs in a couple seconds, I change it to 50_000_000 and it runs in 200 seconds. Something is definitely amiss here, because the following doesn't help (it still consumes 1.2GB of memory): void f0() { wstring a[]; a.reserve(100_000_000); foreach(i; 0 .. 100_000_000) { a ~= " "w; } } This should take the explosive nature of appending out of the equation, because a reallocation should never occur. I'll look into it.
Nov 10 2010
Sorry, it a mistypo (i began from wchar[], later changed to wstring) Real problem can be seen here import std.stdio; import std.date; void f0() { wstring a; foreach(i; 0 .. 100_000_000) { a ~= " "w; } } void main() { auto r = benchmark!(f0)(10); writeln(r, "ms"); }
Nov 10 2010
On Wed, 10 Nov 2010 14:38:02 -0500, Xie <Xiemargl gmail.com> wrote:Sorry, it a mistypo (i began from wchar[], later changed to wstring) Real problem can be seen here import std.stdio; import std.date; void f0() { wstring a; foreach(i; 0 .. 100_000_000) { a ~= " "w; } } void main() { auto r = benchmark!(f0)(10); writeln(r, "ms"); }OK, this actually makes sense to me. It's a manifestation of this issue: http://d.puremagic.com/issues/show_bug.cgi?id=3929 In essence, in order to aid performance, there is an 8-element cache of arrays that are being appended. At the moment, the append code relies on this cache keeping the array from being collected to remain sane. However, as I wrote in the last message on that bug report, I think I can fix it so the cache is not considered a pointer to the memory, and it should be collected. But I haven't done that yet. So what's happening in your code is the first 8 times executing that function, the memory is not collected. This results in you allocating actually 800 million wchars, or 1.6GB before anything can be collected. So in the meantime, jump on the CC for that bug, and I hope to get to it sometime in the near future (maybe by 2.051-2.052). -Steve
Nov 10 2010
OK, this actually makes sense to me.It's a manifestation of this issue: http://d.puremagic.com/issues/show_bug.cgi?id=3929I'm think - it's truth but not at all. Sorry, but i'm give incomplete data. My example run fine, when benchmark(1), (2), but not 10. This means, that memory not collected _between_ calls.
Nov 10 2010
On Wed, 10 Nov 2010 23:33:58 -0500, Xie <Xiemargl gmail.com> wrote:Yes, this is what the bug report is about -- the memory is not collected even though there are no references left, because the cache used to speed up appending still has a reference. -SteveOK, this actually makes sense to me.It's a manifestation of this issue: http://d.puremagic.com/issues/show_bug.cgi?id=3929I'm think - it's truth but not at all. Sorry, but i'm give incomplete data. My example run fine, when benchmark(1), (2), but not 10. This means, that memory not collected _between_ calls.
Nov 11 2010
On Thu, 11 Nov 2010 07:42:36 -0500, Steven Schveighoffer <schveiguy yahoo.com> wrote:On Wed, 10 Nov 2010 23:33:58 -0500, Xie <Xiemargl gmail.com> wrote:OK, so I have actually implemented a fix for bug 3929. Essentially, the cache will no longer hold hostage the data that was being appended. However, I have found that this *still* doesn't fix the problem. Even though the cache no longer holds the memory as allocated, the example does something that we can't really get around. When you allocate a very very large block of data (in this case 1/20 of your address space), it is inevitable with a conservative GC that this data never gets collected. Why? Because the stack is scanned conservatively, and the chances that some 4-bytes of data looks like it points to the space is very high. So in order to fix this, we would not only need precise heap scanning, but *also* precise stack scanning, and precise TLS/global data scanning. But I'm still going to check this in to fix the bug, because it does seem to help with smaller blocks. I'll post more on the main newsgroup on this issue. -SteveYes, this is what the bug report is about -- the memory is not collected even though there are no references left, because the cache used to speed up appending still has a reference.OK, this actually makes sense to me.It's a manifestation of this issue: http://d.puremagic.com/issues/show_bug.cgi?id=3929I'm think - it's truth but not at all. Sorry, but i'm give incomplete data. My example run fine, when benchmark(1), (2), but not 10. This means, that memory not collected _between_ calls.
Dec 23 2010
On 11/10/2010 11:33 AM, Xie wrote:Can't run a simple program. What's wrong, GC? import std.stdio; import std.date; void f0() { wstring a[]; foreach(i; 0 .. 100_000_000) { a ~= " "w; } } void main() { auto r = benchmark!(f0)(1); writeln(r, "ms"); } DMD 2.047In addition to what everybody else is suggesting you look at, you may want to look into using an appender (defined in std.array). Not sure if it will help with the memory usage, but it's supposed to be faster for appending data to an array. Casey
Nov 10 2010
On Wed, 10 Nov 2010 13:55:26 -0500, sybrandy <sybrandy gmail.com> wrote:On 11/10/2010 11:33 AM, Xie wrote:Just tried it, Appender is actually slower. This *is* a problem, it should be way faster than builtin array appending. I will look into it. -SteveCan't run a simple program. What's wrong, GC? import std.stdio; import std.date; void f0() { wstring a[]; foreach(i; 0 .. 100_000_000) { a ~= " "w; } } void main() { auto r = benchmark!(f0)(1); writeln(r, "ms"); } DMD 2.047In addition to what everybody else is suggesting you look at, you may want to look into using an appender (defined in std.array). Not sure if it will help with the memory usage, but it's supposed to be faster for appending data to an array.
Nov 10 2010
On Wed, 10 Nov 2010 14:06:40 -0500, Steven Schveighoffer <schveiguy yahoo.com> wrote:Just tried it, Appender is actually slower. This *is* a problem, it should be way faster than builtin array appending. I will look into it.More data, Appender taking an array of elements is significantly slower than taking a single element (by an order of magnitude). I'll try to figure out why. BTW, if you append individual wchars instead of a string of a single wchar, Appender does beat the pants off of builtin appends. -Steve
Nov 10 2010