Re: Maxime's micro allocation benchmark much faster ?
On 2015-03-31 at 22:56, Laeeth Isharc wrote: 1mm allocations 2.066: 0.844s 2.067: 0.19s That is great news, thanks! OT: it's a nasty financier's habit to write 1M and 1MM instead of 1k and 1M. :P
Re: Maxime's micro allocation benchmark much faster ?
On 2015-04-01 at 16:52, John Colvin wrote: On Wednesday, 1 April 2015 at 14:22:57 UTC, Laeeth Isharc wrote: On Wednesday, 1 April 2015 at 10:35:05 UTC, John Colvin wrote: On Wednesday, 1 April 2015 at 10:09:12 UTC, FG wrote: On 2015-03-31 at 22:56, Laeeth Isharc wrote: 1mm allocations 2.066: 0.844s 2.067: 0.19s That is great news, thanks! OT: it's a nasty financier's habit to write 1M and 1MM instead of 1k and 1M. :P Yeah, what's with that? I've never seen it before. One cannot entirely escape déformation professionnelle ;) [People mostly write 1,000 but 1mm although 1m is pedantically correct for 1,000). Better internalize the conventions if one doesn't want to avoid expensive mistakes under pressure. well yes, who doesn't always not want to never avoid mistakes? ;) Anyway, as I'm sure you know, the rest of the world assumes SI/metric, or binary in special cases (damn those JEDEC guys!): http://en.wikipedia.org/wiki/Template:Bit_and_byte_prefixes Yeah, there's that, but at least 1024 and 1000 are still in the same ballpark. Bankers are used to the convention and won't mistake M for a million (or you'd read it in every newspaper if they did), but it does create havoc when you see that convention being used outside of the financial context, or worse, being mixed with SI.
Re: The difference in string and char[], readf() and scanf()
On 2015-03-21 at 16:05, Ivan Kazmenko wrote: Generate a 10-character string [...] Try to copy it with D scanf and printf: - import std.stdio; void main () { char [10] a; scanf (%s, a.ptr); printf (%s\n, a.ptr); } - Only 32767 first characters of the string are actually copied. In what universe?! Which OS, compiler and architecture?
Re: The difference in string and char[], readf() and scanf()
On 2015-03-21 at 21:02, Dennis Ritchie wrote: In what universe?! Which OS, compiler and architecture? Windows 8.1 x64, dmd 2.066.1: That's strange. I cannot recreate the problem on Win7 x64 with dmd 2.066.1, neither when compiled for 32- nor 64-bit. I have saved the a's to a file and use input redirect to load it, while the program is as follows: import std.stdio; void main () { char [10] a; scanf (%s, a.ptr); printf (%s\n, a.ptr); } freopen(in.txt, r, din.file); No, that approach didn't change the result. I still get 1.
Re: The difference in string and char[], readf() and scanf()
On 2015-03-21 at 22:15, FG wrote: On 2015-03-21 at 21:02, Dennis Ritchie wrote: In what universe?! Which OS, compiler and architecture? Windows 8.1 x64, dmd 2.066.1: That's strange. I cannot recreate the problem on Win7 x64 with dmd 2.066.1, neither when compiled for 32- nor 64-bit. I have saved the a's to a file and use input redirect to load it, while the program is as follows: Oh, wait. I was wrong. I have the same problem. It didn't appear before because the file of A's that I used didn't have a \r\n EOL at the end. With those two bytes added it failed. It's the EOL at the end of the input word that's the problem. I tested four different inputs: aaa...aaa OK aaa...aaa\r\n FAIL aaa...aaa bbb OK aaa...aaa bbb\r\n OK
Re: C++ to D
On 2015-03-11 at 18:27, Dennis Ritchie wrote: The same without classes in Lisp: [...] And your point was...? I take it, poor c++ is a hint. Don't compare apples to oranges.
Re: C++ to D
On 2015-03-11 at 17:42, Dennis Ritchie wrote: On Wednesday, 11 March 2015 at 16:08:22 UTC, Kagamin wrote: A hash table? See http://dlang.org/hash-map.html That is, the input is a string and, depending on what word it contains, is called one of the three methods of the class that this line handles. And this happens in average constant time (for hash). An associative array where the key is a string and value is a function. Yeah, lookup in D's associative arrays is generally O(1). Here's the D version of your C++ code. A bit modified, to be more practical, i.e. you can register hooks yourself and not have them hard-coded into the class. import std.stdio, std.range; class A { alias Hook = void function(ref A, string); string m_buf; Hook[string] handlers; void foo(string s) { if (auto p = s in handlers) (*p)(this, s); m_buf ~= s ~ ; } void register(string name, Hook hook) { handlers[name] = hook; } } void foo1(ref A a, string s) { writeln(s); } void foo2(ref A a, string s) { writeln(s.retro); } void foo3(ref A a, string s) { writeln(s, , , a.m_buf); } void main() { A a = new A; a.register(first, foo1); a.register(second, foo2); a.register(third, foo3); a.foo(first); a.foo(second); a.foo(third); }
Re: string-int[] array
On 2015-03-08 at 20:26, Meta wrote: On Sunday, 8 March 2015 at 18:57:38 UTC, Kagamin wrote: http://dpaste.dzfl.pl/2c8d4a7d9ef0 like this. What in the world is that code doing? I'm having a hard time wrapping my head around this. It's a trick to reuse string internals to store an int. A string is a struct with two values (length, ptr). ivalue(i) is used to set ptr = i and length = 0. Except that with this solution you will confuse empty strings with ints. You could give such strings special treatment by replacing: this(string s){ svalue=s; } with: this(string s){ svalue=s; if (!s.length) svalue = cast(string)(cast(char*)0)[X..X]; } // where X is some magic int value to mark that we are dealing with an empty string, you'd still be confused if someone actually wanted to store the X value.
Re: how to write a string to a c pointer?
On 2015-03-06 at 00:25, ketmar wrote: unicode sux[1]. [1] http://file.bestmx.net/ee/articles/uni_vs_code.pdf Great article. Thanks, Кетмар ⚠ ∑ ♫ ⚽ ☀ ☕ ☺ ≡ ♛
Re: how to write a string to a c pointer?
On 2015-03-05 at 10:42, Kagamin wrote: string s; char[] b = cast(char[])asArray(); b[0..s.length] = s[]; It's a bit more complicated than that if you include cutting string for buffers with smaller capacity, doing so respecting UTF-8, and adding a '\0' sentinel, since you may want to use the string in C (if I assume correctly). The setString function does all that: import std.stdio, std.range, std.c.stdlib; class Buffer { private void *ptr; private int size; private int _cap; public this(int cap) { ptr = malloc(cap); this._cap = cap; } public ~this() { free(ptr); } public ubyte[] asArray() { ubyte[] ret = (cast(ubyte*)ptr)[0..cap]; return ret; } public void* getPtr() { return ptr; } public int cap() { return _cap; } } int setString(Buffer buffer, string s) { assert(buffer.cap 0); char[] b = cast(char[])buffer.asArray(); int len = min(s.length, buffer.cap - 1); int break_at; // The dchar is essential in walking over UTF-8 code points. // break_at will hold the last position at which the string can be cleanly cut foreach (int i, dchar v; s) { if (i == len) { break_at = i; break; } if (i len) break; break_at = i; } len = break_at; b[0..len] = s[0..len]; // add a sentinel if you want to use the string in C b[len] = '\0'; // you could at this point set buffer.size to len in order to use the string in D return len; } void main() { string s = ąćęłńóśźż; foreach (i; 1..24) { Buffer buffer = new Buffer(i); int len = setString(buffer, s); printf(bufsize %2d -- strlen %2d -- %s --\n, i, len, buffer.getPtr); } } Output of the program: bufsize 1 -- strlen 0 -- -- bufsize 2 -- strlen 0 -- -- bufsize 3 -- strlen 2 -- ą -- bufsize 4 -- strlen 2 -- ą -- bufsize 5 -- strlen 4 -- ąć -- bufsize 6 -- strlen 4 -- ąć -- bufsize 7 -- strlen 6 -- ąćę -- bufsize 8 -- strlen 6 -- ąćę -- bufsize 9 -- strlen 8 -- ąćęł -- bufsize 10 -- strlen 8 -- ąćęł -- bufsize 11 -- strlen 10 -- ąćęłń -- bufsize 12 -- strlen 10 -- ąćęłń -- bufsize 13 -- strlen 12 -- ąćęłńó -- bufsize 14 -- strlen 12 -- ąćęłńó -- bufsize 15 -- strlen 14 -- ąćęłńóś -- bufsize 16 -- strlen 14 -- ąćęłńóś -- bufsize 17 -- strlen 16 -- ąćęłńóśź -- bufsize 18 -- strlen 16 -- ąćęłńóśź -- bufsize 19 -- strlen 16 -- ąćęłńóśź -- bufsize 20 -- strlen 16 -- ąćęłńóśź -- bufsize 21 -- strlen 16 -- ąćęłńóśź -- bufsize 22 -- strlen 16 -- ąćęłńóśź -- bufsize 23 -- strlen 16 -- ąćęłńóśź --
Re: Mimicking C++'s indexing behavior in D associative arrays
// Assume bar is some associative array of type Foo[string] Foo* value = key in bar; if (!value) { bar[key] = Foo.init; value = bar[key]; } This seems sub-optimal, given that in involves three hashes (two lookups and one insertion). Is there a more efficient or cleaner way to do so? So basically: Foo v = bar.get(key, Foo.init) bar[key] = v; Get is like an ordinary index but it will return the given value if it does not exist in the AA. Of course you probably want to create a new UFCS function to wrap your check + default initialize if it doesn't exist. T grab(T, U)(T[U] aa, U key) if (is(T == struct)) { if (key !in aa) aa[key] = new T; return aa[key]; } You are searching for the key twice and the original example used pointers. There is a function called _aaGetX in the runtime that has exactly the required behaviour: // Get pointer to value in associative array indexed by key. // Add entry for key if it is not already there. void* _aaGetX(AA* aa, const TypeInfo keyti, in size_t valuesize, in void* pkey) however, using it in normal code could be considered a hack, because it belongs to the internal implementation of associative arrays. Anyway, while waiting for a better solution to present itself, we might as well have a look at this very dirty one. ;) extern(C) void* _aaGetX(void* aa, const TypeInfo keyti, in size_t valuesize, in void* pkey); V* aaGet(K, V)(V[K] arr, K key) { return cast(V*)_aaGetX(cast(void*)arr, typeid(K), V.sizeof, cast(void*)key); } unittest { int[int] arr = [1: 10, 2: 20, 3: 30]; int *val = arr.aaGet(3); // an existing value assert(*val == 30); val = arr.aaGet(4); // aa[4] will be created assert(*val == int.init); assert(arr[4] == int.init); }
Re: @nogc with assoc array
On 2015-02-16 at 18:58, Benjamin Thaut wrote: Am 16.02.2015 um 18:55 schrieb Jonathan Marler: Why is the 'in' operator nogc but the index operator is not? void main() @nogc { int[int] a; auto v = 0 in a; // OK auto w = a[0]; // Error: indexing an associative // array in @nogc function main may // cause GC allocation } Because the index operator throws a OutOfRange exception and throwing exceptions allocates, maybe? Range violation is an Error, but never mind that. The real question is: given all the work related to @nogc, wouldn't it be better for such common Errors to be preallocated and only have file and line updated when they are thrown? @nogc already, because they simply cast typeid(OutOfMemoryError).init or typeid(InvalidMemoryOperationError).init: extern (C) void onOutOfMemoryError(void* pretend_sideffect = null) @trusted pure nothrow @nogc extern (C) void onInvalidMemoryOperationError(void* pretend_sideffect = null) @trusted pure nothrow @nogc Could be made @nogc with one object of each kind preallocated: extern (C) void onAssertError( string file = __FILE__, size_t line = __LINE__ ) nothrow extern (C) void onRangeError( string file = __FILE__, size_t line = __LINE__ ) @safe pure nothrow extern (C) void onSwitchError( string file = __FILE__, size_t line = __LINE__ ) @safe pure nothrow
Re: @nogc with assoc array
On 2015-02-16 at 22:12, Jonathan Marler wrote: On Monday, 16 February 2015 at 19:12:45 UTC, FG wrote: Range violation is an Error, but never mind that. The real question is: given all the work related to @nogc, wouldn't it be better for such common Errors to be preallocated and only have file and line updated when they are thrown? @nogc already, because they simply cast typeid(OutOfMemoryError).init or typeid(InvalidMemoryOperationError).init: extern (C) void onOutOfMemoryError(void* pretend_sideffect = null) @trusted pure nothrow @nogc extern (C) void onInvalidMemoryOperationError(void* pretend_sideffect = null) @trusted pure nothrow @nogc Could be made @nogc with one object of each kind preallocated: extern (C) void onAssertError( string file = __FILE__, size_t line = __LINE__ ) nothrow extern (C) void onRangeError( string file = __FILE__, size_t line = __LINE__ ) @safe pure nothrow extern (C) void onSwitchError( string file = __FILE__, size_t line = __LINE__ ) @safe pure nothrow This could be a good idea for some types of exceptions. I believe OutOfMemory is already pre-allocated (it has to be since you can't allocate it once you are out of memory). The problem with your suggestion is that if you allow the exception to be updated with the line number/filename(it isn't immutable), then you have to store it in TLS memory. That may be an acceptable tradeoff, but you have to take that into consideration. Also if you have a chain of exceptions you wouldn't be able to include the same exception more then once in the chain. The problem D has with exceptions and GC memory is complex and will have different optimal solutions in different cases. In some cases, it would be better for D to support non-GC heap allocated exceptions. Maybe these types of exceptions could be derived from another class so the user code will know that the memory needs to be freed. There are also other ideas but my point is we should make a plan about what solutions we think would be good to implement and determine which ones we want to tackle first. Yes, they would be in TLS. I know exceptions in general are a complex problem, therefore I limited the comment only to errors, because forbidding the use of `aa[key]` in @nogc seemed odd (although I do think that `aa.get(key, default)` and `key in aa` are superior to `aa[key]`). I have seen a few examples of Exception chaining, but not Error chaining, and since Error trumps Exception, whatever else was raised was of less importance to me, so I didn't give much thought to that. And as for the extra non-GC exception class, maybe, I'm not sure, but it should nevertheless be a subclass of Exception to allow for a simple catch-all.
Re: @nogc with assoc array
On 2015-02-17 at 03:35, Jonathan Marler wrote: On Tuesday, 17 February 2015 at 00:00:54 UTC, FG wrote: Yes, they would be in TLS. I know exceptions in general are a complex problem, therefore I limited the comment only to errors, because forbidding the use of `aa[key]` in @nogc seemed odd (although I do think that `aa.get(key, default)` and `key in aa` are superior to `aa[key]`). I have seen a few examples of Exception chaining, but not Error chaining, and since Error trumps Exception, whatever else was raised was of less importance to me, so I didn't give much thought to that. I'm not sure what you mean by Errors? Are you talking about asserts? Asserts among them. I was talking about the two classes of Throwable: Error and Exception. Errors: AssertError, FinalizeError, HiddenFuncError, InvalidMemoryOperationError, InvalidPointerError, NotImplementedError, OutOfMemoryError, ParallelForeachError, RangeError, SwitchError, SysError, ThreadError. Exceptions: Base64Exception, CSVException, ConvException, CurlException, EncodingException, ErrnoException, FiberException, FileException, FormatException, GetOptException, JSONException, OverflowException, ...
Re: ranges reading garbage
On 2015-02-15 at 19:43, bearophile wrote: void foo(in float[] data, in float[] xs, in float[] ys) @safe { iota(0, data.length, ys.length) .map!(xBase = iota(xBase, xBase + ys.length - 1) .map!(y = [y, y+ys.length, y+ys.length+1, y+1]) .joiner) .joiner .writeln; } void main() { foo([1,2,3,4,5,6,7,8], [0.1,0.2], [10,20,30,40]); } Odd... Still something is wrong. It prints: [0, 4, 5, 1, 1, 5, 6, 2, 2, 6, 7, 3, 4, 8, 9, 5, 5, 5, 6, 6, 6, 6, 7, 7] instead of this: [0, 4, 5, 1, 1, 5, 6, 2, 2, 6, 7, 3, 4, 8, 9, 5, 5, 9, 10, 6, 6, 10, 11, 7]
Re: To write such an expressive code D
On 2015-02-11 at 01:56, bearophile wrote: Alternative solution closer to the F# code: import std.stdio, std.algorithm, std.typecons; int f(T)(T t) if (isTuple!T) { return t.predSwitch( tuple(0, 0, 0), 0, tuple(0, 1, 1), 0, tuple(1, 0, 1), 0, tuple(1, 1, 0), 0, /*else*/ 1); } void main() { foreach (immutable a; 0 .. 2) foreach (immutable b; 0 .. 2) foreach (immutable c; 0 .. 2) writefln(%d xor %d xor %d = %d, a, b, c, tuple(a, b, c).f); } Why bend over and try to make it F#? Screw the F# guy. He was cheating with a switch, so why can't we cheat? foreach(i;0..8)writefln(%d xor %d xor %d = %s,!!(i4),!!(i2),!!(i1),01101001[i]); Assimilate this! Oh wait, you needed a function. OK, here's a function (and just replace 01101001[i] with xxor(i4,i2,i1)): int xxor(int a, int b, int c) {return (abc)||(!a!bc)||(!ab!c)||(a!b!c);} If it makes him dislike D even more, great! Mission accomplished. :)
Re: parse string as char
Of course consuming it dchar by dchar also works: string s = `\tabŁŃ\r\nx`; assert(parseDchar(s) == '\t'); assert(parseDchar(s) == 'a'); assert(parseDchar(s) == 'b'); assert(parseDchar(s) == 'Ł'); assert(parseDchar(s) == 'Ń'); assert(parseDchar(s) == '\r'); assert(parseDchar(s) == '\n'); assert(parseDchar(s) == 'x'); assert(s.empty);
Re: parse string as char
On 2015-02-09 at 03:40, Timothee Cour via Digitalmars-d-learn wrote: Is there a simple way to parse a string as a char? eg: unittest{ assert(parseChar(`a`)=='a'); assert(parseChar(`\n`)=='\n'); //NOTE: I'm looking at `\n` not \n // should also work with other forms of characters, see http://dlang.org/lex.html } Note, std.conv.to http://std.conv.to doesn't work (`\n`.to!char does not work) parseEscape does something similar to what you need: https://github.com/D-Programming-Language/phobos/blob/master/std/conv.d#L3415 Unfortunately it is private and handles only escapes, so here is a modified version: import std.range, std.stdio; dchar parseDchar(Source)(ref Source s) if (isInputRange!Source isSomeChar!(ElementType!Source)) { import std.utf, std.conv; if (s.front != '\\') { dchar c = decodeFront(s); return c; } s.popFront; if (s.empty) throw new Exception(Unterminated escape sequence); dchar getHexDigit()(ref Source s_ = s) // workaround { import std.ascii : isAlpha, isHexDigit; if (s_.empty) throw new Exception(Unterminated escape sequence); s_.popFront(); if (s_.empty) throw new Exception(Unterminated escape sequence); dchar c = s_.front; if (!isHexDigit(c)) throw new Exception(Hex digit is missing); return isAlpha(c) ? ((c ~0x20) - ('A' - 10)) : c - '0'; } dchar result; switch (s.front) { case '': result = '\'; break; case '\'': result = '\''; break; case '0': result = '\0'; break; case '?': result = '\?'; break; case '\\': result = '\\'; break; case 'a': result = '\a'; break; case 'b': result = '\b'; break; case 'f': result = '\f'; break; case 'n': result = '\n'; break; case 'r': result = '\r'; break; case 't': result = '\t'; break; case 'v': result = '\v'; break; case 'x': result = getHexDigit() 4; result |= getHexDigit(); break; case 'u': result = getHexDigit() 12; result |= getHexDigit() 8; result |= getHexDigit() 4; result |= getHexDigit(); break; case 'U': result = getHexDigit() 28; result |= getHexDigit() 24; result |= getHexDigit() 20; result |= getHexDigit() 16; result |= getHexDigit() 12; result |= getHexDigit() 8; result |= getHexDigit() 4; result |= getHexDigit(); break; default: throw new Exception(Unknown escape character ~ to!string(s.front)); } if (s.empty) throw new Exception(Unterminated escape sequence); s.popFront(); return result; } dstring parseString(Source)(Source s) if (isInputRange!Source isSomeChar!(ElementType!Source)) { import std.array; dchar[] result; auto app = appender(result); while (!s.empty) app.put(parseDchar(s)); return app.data; } unittest { assert(parseString(``) == d); assert(parseString(`abc`) == abcd); assert(parseString(`abc\\n\\n\\n`) == abc\\n\\n\\nd); assert(parseString(`ąćę\\nłńó`) == ąćę\\nłńód); assert(parseString(`abc\\\nx`) == abc\\\nxd); assert(parseString(`\tabc\r\nx`) == \tabc\r\nxd); assert(parseString(` \x20 `) ==d); }
Re: How to write similar code D?
On 2015-02-10 at 01:41, bearophile wrote: auto query = iota(2, 12) .map!(c = Tuple!(int,length, int,height, int,hypotenuse) (2 * c, c ^^ 2 - 1, c ^^ 2 + 1)) .map!(x = %3d%4d%4d.format(x.height, x.hypotenuse, x.length)); I took advantage of the fact that all elements were of the same type: auto query = iota(2, 2 + 10) .map!(c = [Length: 2 * c, Height: c * c - 1, Hypotenuse: c * c + 1]) .map!(x = format(%4d%4d%4d, x[Height], x[Hypotenuse], x[Length])); ... and was surprised that it worked straight away. :) But definitely this looks better and less complicated: auto query = iota(2, 12) .map!(c = tuple(c ^^ 2 - 1, c ^^ 2 + 1, 2 * c)); foreach (x; query) writefln(%4d%4d%4d, x[]); It's the foreach version, since `each` isn't officially out yet.
Re: strange work of GC
On 2015-02-08 at 06:36, Mike Parker wrote: On 2/8/2015 11:32 AM, FG wrote: On 2015-02-08 at 01:20, Mike Parker wrote: In your case, forget destructors and the destroy method. Just implement a common method on all of your objects that need cleanup (perhaps name it 'terminate') and call that. This gives you the deterministic destruction that you want (the same as calling destroy on each object) while avoiding the possibility that the GC can call your cleanup method. What is wrong with doing all that in a destructor? I don't know if it is just an implementation detail, but a destroyed object is either zero-filled or reinitialized to the default, so, if implemented correctly, it knows whether a cleanup is required (and I'm assuming that a model of simple single ownership is used, like in Qt). Therefore it should be safe to use destroy to finalize an object and even to put destroy in its destructor in order to perform a controlled cascade destruction of all the children that require immediate cleanup (ie. releasing expensive non-GC resources, closing connections, etc.). The main difference with C++ being that you would only force finalization, but then let the GC free the memory in its normal fashion. First, there are no guarantees about when or if a destructor is going to be called. The fact that the current GC calls the destructors of all live objects at application shutdown is an implementation detail. If you want deterministic destruction, you can not rely on destructors. I admit that I became accustomed to that implementation detail and would like it to stay. Second, if you are going to call destroy on every object to clean them up, then in principle that's fine. But now you have to be careful that no mistakes slip into the code base, e.g. forgetting to call destroy on an object that touches GC memory in its destructor. One could also forget to call terminate(). :) The advantage of ~this() is that it is standard, while terminate() is not. You call it that, someone else might call it finalize(), close() or whatever. I do see a benefit in using terminate() directly instead of the GC-fired destructor, because it's not constrained by having to steer clear of the InvalidMemoryOperationError, but it is overshadowed by inconvenience. So let's assume that terminate() is GC-friendly (ie. would work even when called from a destructor). By separating resource cleanup from object destruction, you get both deterministic cleanup and more freedom in choosing whether or not to clean up at all. I separate them only when the object needs it (flush a write, close a connection, release a big chunk of memory, etc.), by calling destroy and not waiting until the GC decides that it's time to deallocate memory for that object and performs the destruction by itself. For every other case of object I also do not care when and if it gets cleaned up. At app exit, I only call terminate on objects that absolutely need to do something before the process exits, like writing a final message to a log file [...] resource cleanup only happens when and if I say. Exactly, but if I put a call to terminate() in the destructor, then clean up will be automated in those cases when I don't care about cleaning up myself or *forget* to do it. That just isn't possible if all cleanup is in destructors. You either have to destroy *every* object yourself, or be vigilant about which objects you let the GC call destructors on. Why not? Are you saying that because of the lack of guarantees that a destructor will be called by the GC? And not *every* object -- it was stated that we don't care about all those objects that don't require special clean up.
Re: why GC not work?
On 2015-02-08 at 15:56, mzf wrote: On Saturday, 7 February 2015 at 06:08:39 UTC, ketmar wrote: On Sat, 07 Feb 2015 04:30:07 +, Safety0ff wrote: False pointers, current GC is not precise. not only that. constantly allocating big chunks of memory will inevitably lead to OOM due to current GC design. you can check it with manual freeing. there were some topics about it, and the solution is either use 64 bit OS ('cause the memory is here, but there is no address space to allocate it), or use `malloc()` and `free()` from libc. hi,i still have two questions: 1. how large is the big chunks ? 10MB? 50MB? ... where are topics about this? if I don't know the exact size, it is very likely a memory leak You wrote yourself, that you used win7 x86,dmd v2.066.0, that is x86 and not x86-64. In 32-bits even with blocks as small as 1 MB there is a chance that the garbage collector will think some data on stack is a pointer to that block because when cast to void* it could point right into that allocated block of memory. 2. auto buf = new byte[](1024*1024*100); now the gc can't free this buf. can i free it by manual? Yes. import core.memory; GC.free(buf.ptr); // and don't use buf afterwards
Re: why GC not work?
On 2015-02-08 at 19:15, safety0ff wrote: On Sunday, 8 February 2015 at 16:23:44 UTC, FG wrote: 2. auto buf = new byte[](1024*1024*100); now the gc can't free this buf. can i free it by manual? Yes. import core.memory; GC.free(buf.ptr); // and don't use buf afterwards That won't work, see: http://forum.dlang.org/thread/uankmwjejsitmlmrb...@forum.dlang.org Perhaps it was fixed in DMD 2.066.1, because this works for me just fine: import core.memory; void testGC() { auto b = new byte[](1024 * 1024 * 100); GC.free(b.ptr); } void main() { foreach (i; 1..100) testGC(); }
Re: strange work of GC
On 2015-02-07 at 12:02, Andrey Derzhavin wrote: If a destroy method is used together with GC inside of my app,it makes my app unstable. In this case I need to choose how to destroy my objects: 1) always manually by method destroy, but without GC; 2) or always automatically by GC, but without using the destroy method. In the first case I need to know how can I disable the automatic GC in my app? In the second case - how can I disable the destroy method calls inside of my app? Why do you want to use destroy? Put GC.collect() after the call to fn1 and GC cleanup will work just fine[1], I've checked. Are you talking about a different program now? [1] Assuming that you compile the program as 64-bit and not 32-bit.
Re: Using reduce with user types
On 2015-02-07 at 13:47, Kadir Erdem Demir wrote: auto sum = aArr.reduce!((a,b) = a.count + b.count); The line above gives C:\D\dmd2\windows\bin\..\..\src\phobos\std\algorithm.d(770): Error: cannot implicitly convert expression (__lambda3(result, front(_param_1))) of type int to A C:\D\dmd2\windows\bin\..\..\src\phobos\std\algorithm.d(791): Error: template instance app.main.reduce!((a, b) = a.count + b.count).reduce!(A, A[]) error instantiating source\app.d(363):instantiated from here: reduce!(A[]) // auto sum = aArr.reduce!((a,b) = a.count + b.count); // Wrong auto sum = reduce!((a, b) = a + b.count)(0, aArr); // Good See here: http://dlang.org/phobos/std_algorithm.html#.reduce
Re: strange work of GC
On 2015-02-08 at 01:20, Mike Parker wrote: In your case, forget destructors and the destroy method. Just implement a common method on all of your objects that need cleanup (perhaps name it 'terminate') and call that. This gives you the deterministic destruction that you want (the same as calling destroy on each object) while avoiding the possibility that the GC can call your cleanup method. What is wrong with doing all that in a destructor? I don't know if it is just an implementation detail, but a destroyed object is either zero-filled or reinitialized to the default, so, if implemented correctly, it knows whether a cleanup is required (and I'm assuming that a model of simple single ownership is used, like in Qt). Therefore it should be safe to use destroy to finalize an object and even to put destroy in its destructor in order to perform a controlled cascade destruction of all the children that require immediate cleanup (ie. releasing expensive non-GC resources, closing connections, etc.). The main difference with C++ being that you would only force finalization, but then let the GC free the memory in its normal fashion.
Re: Trying to make a TCP server, client connects and disconnects immediately
On 2015-02-06 at 05:17, Gan wrote: Oh sweet. Though if one message length is off by even 1 byte, then all future messages get corrupted? Yes, but you can easily detect that by adding a magic number and packet checksum to the header.
Re: Issue with template function
On 2015-02-06 at 18:09, Charles wrote: readString(toBytes!char(['t','e','s','t']),0,4).writeln; readString(toBytes!string(test),0,4).writeln;// This is line 39 That second line makes no sense (you didn't provide an array of strings). Why toBytes!string(test) and not toBytes!char(test) or rather: toBytes!(immutable char)(test) ?
Re: how can I get a reference of array?
On 2015-02-05 at 09:58, bearophile wrote: zhmt: Will arr.ptr change in the future? As the array add more members , it need more memroy, then remalloc may be called, the pointer maybe change, then the stored pointer will be invalid. Will this happen? Yes, it can happen. Therefore, don't use arr.ptr directly, but always access it via arr or a.arr. class A { public int[] * arr; } int[] arr; A a = new A; a.arr = arr; ... // lots of adding to arr ... // and yet still, a.arr == arr Even when the array in the memory gets reallocated by adding to arr, causing arr.length and arr.ptr to be updated, the arr struct itself will remain in the same spot, so pointers to it, including a.arr, are valid. (Unless arr goes out of scope before a, in which case you would be in deep trouble.)
Re: Do you have a better way to remove element from a array?
On 2015-02-05 at 17:25, bearophile wrote: It has to be a void function (or perhaps bettter it can return true/false if it has removed the item, so it becomes @nogc and nothrow). And it has to remove the first item equal to the given one. You can then add a second function that removes at a given index (like removeAt). I was never a fan of STL's erase-remove idiom, although the decoupling of algorithms and containers is in general a great idea. However, in D algorithms can be smarter, because they operate on ranges instead of iterators. I don't see why remove has to follow the C++ example. Therefore I have to ask: Is there any reason why `remove` doesn't take the range by reference and `popBack` as many elements as were removed?
Re: Want to read a whole file as utf-8
On 2015-02-03 at 19:53, Foo wrote: How can I do that without any GC allocation? Nothing in std.file seems to be marked with @nogc I'm asking since it seems very complicated to do that with C++, maybe D is a better choice, then we would probably move our whole project from C++ to D. Looks like std.stdio isn't marked with @nogc all the way either. So for now the temporary solution would be to use std.c.stdio. Get the file size, malloc a buffer large enough for it[1], use std.c.stdio.read to fill it, assign it to a char[] slice and std.utf.decode to consume the text... Oh wait, decode isn't @nogc either. FFS, what now? [1] I assume the file is small, otherwise there would be an extra step involved where after nearing the end of the buffer you move the rest of the data to the front, read new data after it, and continue decoding.
Re: Want to read a whole file as utf-8
On 2015-02-03 at 20:50, Tobias Pankrath wrote: Use std.utf.validate instead of decode. It will only allocate one exception if necessary. Looks to me like it uses decode internally... But Foo, do you have to use @nogc? It still looks like it's work in progress, and lack of it doesn't mean that the GC is actually involved in the function. It will probably take several months for the obvious nogc parts of the std lib to get annotated, and much longer to get rid of unnecessary use of the GC. So maybe the solution for now is to verify the source code of the function in question with ones own set of eyeballs and decide if it's good enough for use, ie. doesn't leak too much?
Re: Want to read a whole file as utf-8
On 2015-02-04 at 00:07, Foo wrote: How would I use decoding for that? Isn't there a way to read the file as utf8 or event better, as unicode? Well, apparently the utf-8-aware foreach loop still works just fine. This program shows the file size and the number of unicode glyps, or whatever they are called: import core.stdc.stdio; int main() @nogc { const int bufSize = 64000; char[bufSize] buffer; size_t bytesRead, count; FILE* f = core.stdc.stdio.fopen(test.d, r); if (!f) return 1; bytesRead = fread(cast(void*)buffer, 1, bufSize, f); if (bytesRead bufSize - 1) { printf(File is too big); return 1; } if (!bytesRead) return 2; foreach (dchar d; buffer[0..bytesRead]) count++; printf(read %d bytes, %d unicode characters\n, bytesRead, count); fclose(f); return 0; } Outputs for example this: read 838 bytes, 829 unicode characters (It would be more complicated if it had to process bigger files.)
Re: Want to read a whole file as utf-8
On 2015-02-04 at 01:56, Namespace wrote: FILE* f = fopen(filename.ptr, rb); fseek(f, 0, SEEK_END); immutable size_t fsize = ftell(f); fseek(f, 0, SEEK_SET); That's quite a smart way to get the size of the file. I started with std.file.getSize (which obviously isn't marked as @nogc) and ended up with the monstrosity below (which I have only compiled on Windows), so I decided not to mention it in my previous post. Wouldn't be the point anyway, since I have only shown an example with a single-fill fixed buffer. But here it is, rendered useless by your code: long getFileSize(const char* cName) @nogc { version(Windows) { import core.sys.windows.windows; WIN32_FILE_ATTRIBUTE_DATA fad; if (!GetFileAttributesExA(cName, GET_FILEEX_INFO_LEVELS.GetFileExInfoStandard, fad)) return -1; ULARGE_INTEGER li; li.LowPart = fad.nFileSizeLow; li.HighPart = fad.nFileSizeHigh; return li.QuadPart; } else version(Posix) { import core.sys.posix.sys.stat; stat_t statbuf = void; if (stat(cName, statbuf)) return -1; return statbuf.st_size; } }
Re: Conway's game of life
On 2015-02-02 at 12:23, FG wrote: Cell(0,3) is not a neighbour bit fits the (diff1 == 1 || diff2 == 1) criterion. s/bit/but/
Re: Conway's game of life
Bloody Thunderbird has sent a reply to the OP and not to the NG. On 2015-02-02 at 11:45, gedaiu wrote: I don't think that the line of code is wrong. If use the function will check for neighbours only on diagonals. Having || allows the search on the vertical and horizontal axis and diagonals. In short: Yes, alone would check only diagonals, but I forgot to tell you to also change the ==. (diff1 == 1 || diff2 == 1) -- bad, accepts whole neighbouring rows and columns (diff1 == 1 diff2 == 1) -- bad, accepts only neighbouring diagonals (diff1 = 1 diff2 = 1) -- correct, I think :) This unittest should show the difference: unittest { CellList world = [ Cell(0,0), Cell(0,1), Cell(0,2), Cell(0,3) ]; assertEqual(Cell(1,1).neighbours(world), 3); } Cell(0,3) is not a neighbour bit fits the (diff1 == 1 || diff2 == 1) criterion.
Re: cast a C char array - offset ?
On 2015-02-02 at 13:16, irtcupc wrote: The manual section about interfacing from c states that type[] is inter-compatible from C to D, however, I face this strange case: - C declaration: char identifier[64]; - D declaration: char[64] identifier; - the result is only correct if i slice by (- pointer size): char[64] fromC(char[64] * thing) { const offs = size_t.sizeof; return thing[-offs.sizeof .. $-offs]; } Is this correct ? So you have to shift the whole array right by 4 or 8 bytes? Strange. Looks like an alignment issue. Is identifier part of a bigger structure?
Re: cast a C char array - offset ?
On 2015-02-02 at 14:40, irtcupc wrote: On Monday, 2 February 2015 at 13:34:28 UTC, ketmar wrote: struct _Disasm { align(1): the difference is that `align` before struct tells how structure should be packed (i.e. when you have `_Disasm[2] arr`). and `align` *inside* struct tells compiler how struct *members* should be packed. Thx, problem fixed, it works now. Yeah, without the align(1) inside the struct, the members of the struct were not crammed, so VirtualAddr started in byte x+8 instead of x+4 (on a 32-bit machine), and that was the source of the extra 4-byte shift you encountered.
Re: Can't understand how to compare DateTime with opCmp
On 2015-02-01 at 16:04, Suliman wrote: opCmp(in DateTime rhs); what is rhs? RHS is probably short of right hand side, ie. the argument on the right side of the operator in a binary operator expression. In `a b` it would be b. I am trying to do something like this: if( DateTime.opCmp(dtindb, outoftime)); But it's seems that I wrong understand how to use this function... No. That would be `if (dtindb.opCmp(outoftime))`, but it's simpler to write `if (dtindb outoftime)`
Re: Conway's game of life
On 2015-02-01 at 22:00, gedaiu wrote: I implemented Conway's game of life in D. I think you are playing a different game here. /// Count cell neighbours long neighbours(Cell myCell, CellList list) { long cnt; foreach(cell; list) { auto diff1 = abs(myCell.x - cell.x); auto diff2 = abs(myCell.y - cell.y); if(diff1 == 1 || diff2 == 1) cnt++; // Why || instead of ??? } return cnt; }
Re: std.algorithm sort() and reverse() confusion
On 2015-01-30 at 17:07, Paul wrote: writeln(Sorted, reversed: , reverse(myVals)); Gives me... Error: template std.stdio.writeln cannot deduce function from argument types !()(string, void) As it should, because reverse returns nothing, void. But you may wonder what the design choice behind that was that reverse doesn't return the range itself while sort does (a SortedRange, specifically).
Re: std.algorithm sort() and reverse() confusion
On 2015-01-30 at 18:42, FG wrote: But you may wonder what the design choice behind that was that reverse doesn't return the range itself while sort does (a SortedRange, specifically). Although, after thinking about it, it makes sense. sort is used mostly to enforce that something is sorted in case it isn't already, so chaining it with other functions is reasonable, while in case of reverse you don't normally call it very often, it's cheaper to wrap the range in a retro range and iterate backwards when required, without touching the original.
Re: Thread.sleep( dur!(msecs)( 50 ) ); // sleep for 50 milliseconds
On 2015-01-30 at 12:08, Vladimir Panteleev wrote: On Friday, 30 January 2015 at 11:04:47 UTC, FG wrote: Bug or correct behaviour? Bug: https://issues.dlang.org/show_bug.cgi?id=1238 https://github.com/D-Programming-Language/dmd/pull/3743 The fix is pretty much a one-liner. Probably 2.067 will already include it, right?
Re: Thread.sleep( dur!(msecs)( 50 ) ); // sleep for 50 milliseconds
Error: module app struct std.regex.Thread(DataIndex) is private Did you import core.thread?
Re: Thread.sleep( dur!(msecs)( 50 ) ); // sleep for 50 milliseconds
On 2015-01-30 at 11:55, FG wrote: Error: module app struct std.regex.Thread(DataIndex) is private Did you import core.thread? This is silly. Thread is internal to std.regex, yet when importing both std.regex and core.thread, you still get an error: src.d(10): Error: core.thread.Thread at ..\thread.d(514) conflicts with std.regex.Thread(Dat aIndex) at ..\src\phobos\std\regex.d(4588) The way around is of course the use of a fully qualified name: core.thread.Thread.sleep( dur!(msecs)( 50 ) ); but there really should be no need for this, since std.regex.Thread is private. Bug or correct behaviour?
Re: What is @return?
@property auto info() @safe @nothrow @pure @return const { return this; } It is mesmerizing... (@ _ @)
Re: I left my program open for 9 hours and it used up 700mb of ram, could someone review it?
On 2015-01-27 at 23:39, Gan wrote: I commented out some stuff and it appears my massive memory consumption comes from my tile.redraw function: ... Would you know why this is using hundreds of mb of rams? Looks OK, so probably it is not the cause by itself. I would add a piece of code to SpaceBackground.draw that for every few calls to this function would print out tiles.length and stack.length to the console. Just to make sure that those arrays don't grow out of control, before accusing anything else.
Re: I left my program open for 9 hours and it used up 700mb of ram, could someone review it?
On 2015-01-28 at 03:04, Vladimir Panteleev wrote: What type is CircleShape? If it is a class, or otherwise contains pointers, then this is probably the source of your problem. class CircleShape : Shape is defined in dsfml.graphics.circleshape, so there's no going around this... - Building your program for x86_64 - 64 bits of address space will make fake pointer pinning very unlikely The binary included in the zip was 64-bit, so fake pointers shouldn't be that much of a problem. Oh, and I take back what I said about suspecting that SpaceBackground.stack grows infinitely. It probably doesn't. I don't have DSFML installed, and therefore couldn't recreate the behaviour.
Re: crash on args.getopt
On 2015-01-25 at 11:42, Tobias Pankrath wrote: On Sunday, 25 January 2015 at 10:21:34 UTC, Suliman wrote: But is it good practice to fail with exception during passing unknown parameters? Maybe std.getopt.config.passThrough should be as default? I really can't remember Apps that crush if pass to in unknown parameters. Almost all programs fail with an error message, if you pass unknown parameter. Just catch that exception. It's much better to fail up front than to create the illusion that everything is fine after the user has mistyped one of the parameters. Let's say foo a b copies from a to b, but foo --reverse a b does the opposite. Then, when someone types for example foo --revrse a b, and it is silently accepted, the program does exactly the opposite of what the user expects! A side note: GTK applications accept extra parameters used to initialize GTK, but it is not passThrough. What really happens is that the app calls gtk_init(argc, argv) (or Main.init(args) in case of GtkD) before it starts parsing arguments on its own. The call to gtk_init removes the options recognized by GTK from the list of program arguments, and this filtered array can be then processed in a normal way -- which means that whichever parameters are still left unrecognised, the program should fail with an error message.
Re: endsWith - for a string vs an array of strings
On 2015-01-10 at 21:58, bearophile wrote: Needles is not an array type, it's a type tuple, so withOneOfThese doesn't accept an array of strings. [...] So if you really want to pack the strings in some kind of unity, you can do this as workaround: [...] I would suggest create a function that does the same thing as endsWith(Range, Needles...) but instead of Needles expanded as a list of arguments it takes in a range of them. In fact I was surprised that there was no such function in std.algorithm present. Therefore I have written endsWithAny for this purpose a moment ago. Is it any good? Please correct if necessary. import std.array; import std.string; import std.stdio; import std.range; uint endsWithAny(alias pred = a == b, Range, Needles)(Range haystack, Needles needles) if (isBidirectionalRange!Range isInputRange!Needles is(typeof(.endsWith!pred(haystack, needles.front)) : bool)) { foreach (i, e; needles) if (endsWith!pred(haystack, e)) return i + 1; return 0; } void main(string[] args) { string[] test = [1, two, three!]; auto a = arghtwo.endsWithAny(test); writefln(%s, a); } unittest { string[] hs = [no-one, thee, there were three, two]; string[] tab = [one, two, three]; assert(endsWithAny(hs[0], tab) == 1); assert(endsWithAny(hs[1], tab) == 0); assert(endsWithAny(hs[2], tab) == 3); assert(endsWithAny(hs[3], tab) == 2); }
Re: Lexer in D
On 2013-03-11 16:11, Namespace wrote: I've also done some benchmarks. And I wonder why my appender is much faster if I enable memory reservation. Probably just because D's Appender has a better growth scheme than yours and you reallocate too often. Try to compare how often that happens. I'm also very interested to hear some improvements tips. Well, you may add a check whether alloc/realloc actually succeeded. :)
Re: How to initialize an immutable array
I suppose this: immutable long DIM = 1024L*1024L *128L; immutable(double)[] signal = new double[DIM+1]; static this() { for (long i=0L; i DIM+1; i++) { signal[i] = (i+DIM)%7 + (i+DIM+1)%5; } } void main() { ... }
Re: How to initialize an immutable array
On 2013-03-01 22:05, Sparsh Mittal wrote: On Friday, 1 March 2013 at 20:28:19 UTC, FG wrote: I suppose this: immutable long DIM = 1024L*1024L *128L; immutable(double)[] signal = new double[DIM+1]; static this() { for (long i=0L; i DIM+1; i++) { signal[i] = (i+DIM)%7 + (i+DIM+1)%5; } } void main() { ... } Thanks. This gives an error, which I don't know how to resolve: Error: cannot evaluate new double[](134217729LU) at compile time Can you please tell. Oh, sorry. Was typing without thinking. :) Here's a working sample (with long changed to uint): import std.stdio, std.datetime, std.parallelism, std.range; double my_abs(double n) { return n 0 ? n : -n; } immutable uint DIM = 1024 * 1024 * 128; immutable(double)[] signal; static this() { auto temp = new double[DIM+1]; for (uint i = 0; i DIM + 1; i++) temp[i] = (i + DIM) % 7 + (i + DIM + 1) % 5; signal = cast(immutable)temp; } void main() { double temp; double sample[2] = [4.1,7.2]; StopWatch sw; sw.start(); for (uint i = 0; i DIM; i++) { temp = my_abs(sample[0]-signal[i]) + my_abs(sample[1]-signal[i+1]); } sw.stop(); writeln( Total time: , (sw.peek().msecs/1000), [sec]); }
Re: A little of coordination for Rosettacode
On 2013-02-26 15:10, bearophile wrote: This third version is much simpler and it seems good enough for Rosettacode: http://codepad.org/YJjb1t91 Nice. Myself I'd add bits.reverse; after the N.iota.map..., because I'm more used to a truth table where the left-most operands iterate the slowest.
Re: A little of coordination for Rosettacode
On 2013-02-27 12:47, FG wrote: On 2013-02-26 15:10, bearophile wrote: This third version is much simpler and it seems good enough for Rosettacode: http://codepad.org/YJjb1t91 Nice. Myself I'd add bits.reverse; after the N.iota.map..., because I'm more used to a truth table where the left-most operands iterate the slowest. or, without reverse, but perhaps not very clear: N.iota.map!(j = !!(i (1 (N - j - 1.copy(bits[]);
Re: Issues with std.regex
On 2013-02-16 21:22, MrAppleseed wrote: auto reg = regex([ 0-9a-zA-Z.*=+-;()\\'\[\],{}^#/\\]); When I try to run the code above, I get: parser.d(64): Error: undefined escape sequence \[ parser.d(64): Error: undefined escape sequence \] When I remove the escaped characters (turning my regex into [ 0-9a-zA-Z.*=+-;()\\'[],{}^#/\\]), I get no issues compiling or linking. However, on first run, I get the following error (I cut the error short, full error is pasted http://pastebin.com/vjMhkx4N): std.regex.RegexException@/usr/include/dmd/phobos/std/regex.d(1942): wrong CodepointSet Pattern with error: `[ 0-9a-zA-Z.*=+-;()'[]` --HERE-- `,{}^#/\]` Perhaps try this: [ 0-9a-zA-Z.*=+-;()\\'\\[\\],{}^#/\\]
Re: Issues with std.regex
On 2013-02-16 22:36, MrAppleseed wrote: Perhaps try this: [ 0-9a-zA-Z.*=+-;()\\'\\[\\],{}^#/\\] I made the changes you suggested above, and although it compiled fine, on the first run I got a similar error: std.regex.RegexException@/usr/include/dmd/phobos/std/regex.d(1942): unexpected end of CodepointSet Pattern with error: `[ 0-9a-zA-Z.*=+-;()'\[\],{}^#/\]` --HERE-- `` Ah, right. Sorry for that. You'd need as much as 4 backslashes there. :) [ 0-9a-zA-Z.*=+-;()\\'\\[\\],{}^#/] Ain't pretty so it's better to go with raw strings, but apparently there are some problems with them right now, looking at the other posts here, right?
Re: Finding large difference b/w execution time of c++ and D codes for same problem
On 2013-02-13 14:26, Marco Leise wrote: template Julia(TReal) { struct ComplexStruct { float r; float i; ... Why aren't r and i of type TReal?
Re: Calculating mean and standard deviation with std.algorithm.reduce
On 2013-02-13 14:44, Joseph Rushton Wakeling wrote: The docs for std.algorithm give an illustration of its use to calculate mean and standard deviation in a single pass: [...] However, this formula for standard deviation is one that is well known for being subject to potentially fatal rounding error. Typical thing with examples - they try to be terse and show off a mechanism like reduce, without going into too much details and hence are unusable IRL. You can use reduce and put the division and subtraction into the reduce itself to prevent overflows. You also won't end up with jaw-dropping tuples, sorry. :) float[] a = [10_000.0f, 10_001.0f, 10_002.0f]; auto n = a.length; auto avg = reduce!((a, b) = a + b / n)(0.0f, a); auto var = reduce!((a, b) = a + pow(b - avg, 2) / n)(0.0f, a); auto sd = sqrt(var); writeln(avg, \t, sd); Output: 10001 0.816497
Re: Finding large difference b/w execution time of c++ and D codes for same problem
Good point about choosing the right type of floating point numbers. Conclusion: when there's enough space, always pick double over float. Tested with GDC in win64. floats: 16.0s / doubles: 14.1s / reals: 11.2s. I thought to myself: cool, I almost beat the 13.4s I got with C++, until I changed the C++ code to also use doubles and... got a massive speedup: 7.1s!
Re: Finding large difference b/w execution time of c++ and D codes for same problem
On 2013-02-13 16:26, Marco Leise wrote: I'd still bet a dollar that with an array of values floats would outperform doubles, when cache misses happen. (E.g. more or less random memory access.) I'll play it safe and only bet my opDollar. :)
Re: How to read fastly files ( I/O operation)
On 2013-02-13 18:39, monarch_dodra wrote: In any case, I am now parsing the 6Gig packed into 1.5Gig in about 53 seconds (down from 61). I also tried doing a dual-threaded approach (1 thread to unzip, 1 thread to parse), but again, the actual *parse* phase is so ridiculously fast, that it changes *nothing* to the final result. Great. Performance aside, we didn't talk much about how this data can be useful - should it only be read sequentially forward or both ways, would there be a need to place some markers or slice the sequence, etc. Our small test case was only about counting nucleotides, so reading order and possibility of further processing was irrelevant. Mr.Bio, what usage cases you'll be interested in, other than those counters?
Re: std.container.RedBlackTree versus C++ std::set
On 2013-02-14 01:09, Rob T wrote: You can check if disabling the GC just before the insert process improves the performance. You may see 3x performance improvement. Disabling is safe provided you re-enable, this can be done reliably with scope(exit) or something similar. How did you know? It was 3x in my case. :) Well, even more but the program had to wait 2 seconds at the end to collect. With LIMIT at 10M, g++: 5.0s, gdc: 27.0s and 8.7s with GC.disable. Internal memory handling by containers - yeah, can't wait to see that happen!
Re: Using objects that manage threads via std.concurrency
On 2013-02-12 12:14, monarch_dodra wrote: For one thing, MessageBox is private. Unnecessarily hidden, because, from what I can see from a fast look at the sources, there is no implicit requirement for there to be only one MessageBox per thread. Maybe we're getting somewhere and this will be changed. As for the re-implement of receive to work on a custom Tid, maybe it might be better to forget about the tid, and implement it on directly on the mailbox? Well, yes. It's more natural to work on mbox than some artificial struct. Now, as for the usefulness of having many mailboxes. I'd rather have one mailbox than go into a loop with receiveTimeout called for each Manager, but in your divideconquer example receive makes sense and keeps ordering.
Re: Finding large difference b/w execution time of c++ and D codes for same problem
On 2013-02-12 21:39, Sparsh Mittal wrote: I am finding C++ code is much faster than D code. I had a look, but first had to make juliaValue global, because g++ had optimized all the calculations away. :) Also changed DIM to 32 * 1024. 13.2s -- g++ -O3 16.0s -- g++ -O2 15.9s -- gdc -O3 15.9s -- gdc -O2 16.2s -- dmd -O -release -inline(v.2.060) Winblows and DMD 32-bit, the rest 64-bit, but still, dmd was quite fast. Interesting how gdc -O3 gave no extra boost vs. -O2.
Re: Using objects that manage threads via std.concurrency
On 2013-02-11 22:37, monarch_dodra wrote: Basically, I can't help but feel the thing has an hopelessly thread-global mailbox approach to the problem. This is all fine and dandy if there is only a single canal of communication between the master and the child/children. What thread-global? Every mbox is in thread-local storage. But what happens if you have 2 objects at once that want to communicate with their children? They have to share the global mailbox, making things very complex. Caller locks the callee mailbox for a moment to put a message. Doesn't lock any other thread, so you can have N/2 threads writing to other N/2 at the same time. In my program, I have simple objects: Managers, that spawn a child thread to do work. This works fine if I have a single Manager, but how do I manage having 2 Managers at once? It's generally a very bad idea to have more than 1 manager over one's head. :) What should a manager do if it calls receive, and notices the message wasn't meant for him? Don't know. Kill the messenger perhaps? :)
Re: Invisible console
On 2013-02-10 15:17, SaltySugar wrote: how to make console invisible? Seems to be a recurring question here. :) Search archives. You probably want: dmd.exe -L/SUBSYSTEM:WINDOWS app.d
Re: Looking for writing parallel foreach kind of statement for nested for-loops
On 2013-02-09 23:32, Sparsh Mittal wrote: I saw foreach and parallel commands on http://dlang.org/phobos/std_parallelism.html I have nested for-loops as follows: for(int i=1; i N; i++) { for(int j=1; j M; j++) { func(i,j); } } Here func(i,j) is such that there is no dependency or communication b/w different (i,j) tuple values. Thus, problem is very simple. Huh? for(int i=1; i N; i++)==foreach(i; iota(1, N)) so you can use: foreach(i; parallel(iota(1, N))) { ... }
Re: How to read fastly files ( I/O operation)
On 2013-02-07 08:26, monarch_dodra wrote: You have timed the same file SRR077487_1.filt.fastq at 67s? Yes, that file exactly. That said, I'm working on an SSD, so maybe I'm less IO bound than you are? Ah, now that you mention SSD, I moved the file onto one and it's even more clear that I am CPU-bound here on the Intel E6600 system. Compare: 7200rpm: MS 4m30s / FG 1m55s SSD: MS 4m14s / FG 1m44s Almost the same, but running the utility wc -l on the file renders: 7200rpm: 1m45s SSD: 0m33s In my case threads would be beneficial but only when using the SSD. Reading the file by chunk in D takes 33s on SSD and 1m44s on HDD. Slicing the file in half and reading from both threads would also be fine only on the SSD, because on a HDD I'd lose sequential disk reads jumping between threads (expecting lower performance). Therefore - threads: yes, but gotta use an SSD. :) Also, threads: yes, if there's gonna be more processing than just counting letters.
Re: How to read fastly files ( I/O operation)
On 2013-02-04 15:04, bioinfornatics wrote: I am looking to parse efficiently huge file but i think D lacking for this purpose. To parse 12 Go i need 11 minutes wheras fastxtoolkit (written in c++ ) need 2 min. Haven't compared to fastxtoolkit, but I have some code for you. I have processed the file SRR077487_1.filt.fastq from ftp://ftp.1000genomes.ebi.ac.uk/vol1/ftp/data/HG00096/sequence_read/ and expect this syntax (no multiline sequences or whitespace). File takes up almost 6 GB processing took 1m45s - twice as fast as the fastest D solution so far -- all compiled with gdc -O3. I bet your computer has better specs than mine. Program uses a buffer that should be twice the size of the largest sequence record (counting id, comment and quality data). A chunk of file is read, then records are scanned on the buffer until record start pointer passes the middle of the buffer -- then memcpy is used to move all the rest to the begining of the buffer and the remaining space at the end is filled with another chunk read from the file. Data contains both sequence letter and associated quality information. Sequence ID and comment are slices of the buffer, so they have valid info until you move to the next sequence (and the number increments). This is the code: http://dpaste.1azy.net/8424d4ac Tell me what timings you can get now.
Re: How to read fastly files ( I/O operation)
On 2013-02-06 21:43, monarch_dodra wrote: On Wednesday, 6 February 2013 at 19:19:52 UTC, FG wrote: I have processed the file SRR077487_1.filt.fastq from ftp://ftp.1000genomes.ebi.ac.uk/vol1/ftp/data/HG00096/sequence_read/ and expect this syntax (no multiline sequences or whitespace). File takes up almost 6 GB processing took 1m45s - twice as fast as the fastest D solution so far Do you mean my solution above? I tried your solution with dmd, with -release -O -inline, and both gave about the same result (69s yours, 67s mine). Yes. Maybe CPU is the bottleneck on my end. With DMD32 2.060 on win7-64 compiled with same flags I got: MD: 4m30 / FG: 1m55s - both using 100% of one core. Quite similar results with GDC64. You have timed the same file SRR077487_1.filt.fastq at 67s? I'm getting real interested on the subject. I'm going to try to write an actual library/framework for working with fastq files in a D environment. Those fastq are contagious. ;) This means I'll try to write robust and useable code, with both stability and performance in mind, as opposed to the proofs of concepts in so far. Yeah, but the big deal was that D is 5.5x slower than C++. You have mentioned something about using byLine. Well, I would have gladly used it instead of looking for line ends myself and pushing stuff with memcpy. But the thing is that while the fgets(char *buf, int bufSize, FILE *f) in fastx is fast in reading file by line, using file.readln(buf) is unpredictable. :) I mean that in DMD it's only a bit slower than file.rawRead(buf), but in GDC can be several times slower. For example just reading in a loop: import std.stdio; enum uint bufferSize = 4096 - 16; void main(string[] args) { char[] tmp, buf = new char[bufferSize]; size_t cnt; auto f = File(args[1], r); switch(args[2]) { case raw: do tmp = f.rawRead(buf); while (tmp.length); break; case readln: do cnt = f.readln(buf); while (cnt); break; default: writeln(Use parameters: filename raw|readln); } } Tested on a much smaller SRR077487.filt.fastq: DMD32 -release -O -inline: raw 94ms / readln 450ms GDC64 -O3: raw 94ms / readln 6.76s Tested on SRR077487_1.filt.fastq: DMD32 -release -O -inline: raw 1m44s / readln 1m55s GDC64 -O3: raw 1m48s / readln 14m16s Why such a big difference between the DMD and GDC (on Windows)? (or have I missed some switch in GDC?)
Re: How to read fastly files ( I/O operation)
On 2013-02-07 00:41, Lee Braiden wrote: I wasn't going to mention this as I thought the CPU usage might be trivial, but if both CPU and IO are factors, then it would probably be beneficial to have a separate IO thread/task. This wasn't an issue in my version of the program. It took 1m55s to process the file, but then again it takes 1m44s just to read it (as shown previously). Also, if you don't strictly need to parse the file in order, then you could divide and conquer it by breaking it into more sections/tasks. For example, if you're parsing records, you cold split the file in half, find the remaining parts of the record in the second half, move it to the first, and then process the two halves in two threads. If you've a nice function to do that split cleanly, and n cpus, then just call it some more. Now, this could make a big difference! If only parsing out of order is acceptable in this case.
Re: GtkD button size
On 2013-02-05 20:48, SaltySugar wrote: Can I use hbox.add(btn); instead of hbox.packStart (btn,false,false,5); What difference between them? Using add(btn) you would probably end up with a stretched button again. :) hbox.packStart(child, expand, fill, padding) It was explicitly said that expand = false, to prevent button resizing. Read more here: http://www.mono-project.com/GtkSharp:_Packing_with_Boxes It's Gtk# but may be of some help to you.
Re: How to read fastly files ( I/O operation)
On 2013-02-04 15:04, bioinfornatics wrote: I am looking to parse efficiently huge file but i think D lacking for this purpose. To parse 12 Go i need 11 minutes wheras fastxtoolkit (written in c++ ) need 2 min. My code is maybe not easy as is not easy to parse a fastq file and is more harder when using memory mapped file. Why are you using mmap? Don't you just go through the file sequentially? In that case it should be faster to read in chunks: foreach (ubyte[] buffer; file.byChunk(chunkSize)) { ... }
Re: Why are commands executing out of order?
On 2013-02-02 07:49, Josh wrote: But main's first writeln actually outputs after f.close(). Maybe because of output buffering and you need to add flush? The program uses ~1GB of RAM overall, even though main.results is ~50MB according to memSize. Wrong comparison. You should have compared to the output file's size. info.sizeof doesn't include the size of info.name. In my test results were 30 MB but the output file was 101 MB. Any attempts to call the GC do nothing, but I'm probably doing it wrong though. Is it possible that I have a memory leak somewhere that is causing this delay, or is this a DMD problem, or something else I haven't even thought of? It's a problem with array concatenation and memory fragmentation. There are two ways out of this mess. First, there's the Unix Way - don't use the results array at all and print out info records immediately as they appear. Your program will use under 3 MB of RAM. :) But if you really have to do some extra processing of results, then you can reduce the memory used like 6 times by using an Appender instead of concatenating arrays and by reserving a reasonable number of records, to limit possible initial fragmentation when the array is resized. My program used 145 MB whereas the output file was 101 MB. I think it's good enough. But that's scanning just one, non-system drive. Won't even try to scan them all. Try it out: import std.datetime; import std.file; import std.stdio; import std.array; struct info { string name; bool isDir; ulong size; SysTime timeCreated; SysTime timeLastAccessed; SysTime timeLastModified; this(DirEntry d) { this.name = d.name; this.isDir = d.isDir; this.size = d.size; this.timeCreated = d.timeCreated; this.timeLastAccessed = d.timeLastAccessed; this.timeLastModified = d.timeLastModified; } } alias Appender!(info[]) InfoAppender; void main() { writeln(Scanning drives...); info[] results; InfoAppender app = appender(results); app.reserve(512*1024); // for (char c = 'D'; c = 'D'; c++) { if (exists(c ~ :\\)) { app.put(info(DirEntry(c ~ :\\))); scan(c ~ :\\, app); } } File f = File(driveInfo.txt, w); foreach (i; app.data) { f.writeln(i); } f.close(); writeln(memSize(app.data)); } void scan(string dir, ref InfoAppender app) { try { auto de = dirEntries(dir, SpanMode.shallow); foreach (d; de) { app.put(info(d)); if (d.isDir()) scan(d.name, app); } } catch (FileException fe){} } size_t memSize(T)(T[] t) { return t.length * T.sizeof; } And the preferred version to scan whole filesystem without wasting RAM: :) import std.datetime; import std.file; import std.stdio; struct info { string name; bool isDir; ulong size; SysTime timeCreated; SysTime timeLastAccessed; SysTime timeLastModified; this(DirEntry d) { this.name = d.name; this.isDir = d.isDir; this.size = d.size; this.timeCreated = d.timeCreated; this.timeLastAccessed = d.timeLastAccessed; this.timeLastModified = d.timeLastModified; } } File f; void main() { writeln(Scanning drives...); f = File(driveInfo.txt, w); for (char c = 'D'; c = 'D'; c++) { if (exists(c ~ :\\)) { f.writeln(info(DirEntry(c ~ :\\))); scan(c ~ :\\); } } f.close(); } void scan(string dir) { try { auto de = dirEntries(dir, SpanMode.shallow); foreach (d; de) { f.writeln(info(d)); if (d.isDir()) scan(d.name); } } catch (FileException fe){} }
Array concatenation vs. Appender
On 2013-02-02 13:50, Era Scarecrow wrote: On Saturday, 2 February 2013 at 11:33:07 UTC, Namespace wrote: I'm was quite surprised as I had heard the first time of these 'appender'. Therefore I'm asking me: Why is the 'appender' method so much more efficient? Because concatenation likely will end up relocating the memory over and over again (possibly lots of abandoned slices too) whereas the appender will allocated reuse the same buffer. On the other hand you might be better off (depending on the need) with just reserving a lot more memory (close to what you need or slightly larger) and then concatenation will perform much better. But if it need to reallocate then you've still got the same problem with slices where with the appender you probably won't. Yeah but let us move reallocation out of the equation. Reserving space limits the amount of RAM used and can avoid reallocations all together but in a little test it came out that still appender is 2.5-4 times faster than tab ~= str, where tab is char[] (same when it is ubyte[]). Why is that? Let's say we have this code: char[] tab; string fill = 1234; uint loops = 100_000_000; tab.reserve(loops * fill.length); foreach (i; 0..loops) tab ~= fill; Using Appender changes the above loop into something like this: size_t capacity = tab.capacity; foreach (i; 0..loops) { size_t flen = fill.length; size_t len = tab.length; if (len + flen capacity) { ... // use GC.extend or GC.qalloc memcpy // update capacity and assign tab = memory_block[0..len] } tab = tab.ptr[0..len+flen]; tab.ptr[len..len+flen] = fill[]; } Why cannot tab ~= fill achieve similar performance as this code? Am I missing something important?
Re: Why are commands executing out of order?
On 2013-02-02 16:22, Josh wrote: Maybe because of output buffering and you need to add flush? How do I do that? I've never heard of flush before. writeln(...); stdout.flush(); C also has flush, in the form of fflush(stdout); I've never come across Appenders before. Could you please explain them a little bit, and what each call in your modified code does? I'm baffled myself as to why they perform better than normal array concatenation. We'll see if some interesting explanation appears. That's why I changed the topic to Array concatenation vs. Appender.
Re: Associative Array, key and value as type of string or char[]
On 2013-02-02 16:06, Namespace wrote: string[string] ch_Description = [ kill : kills a process, pause : pauses a process ]; writeln(ch_Description); // does not work, but it should Doesn't work in the current version? In DMD 2.060 it works.
Re: new T[size] vs .reserve
On 2013-02-02 19:01, Namespace wrote: Example: struct Color { public: ubyte[4] colors; } ubyte[] data = new ubyte[color_data.length * 4]; // enough storage foreach (ref const Color col; color_data) { data ~= col.colors; } Sorry, but what is the point of data having only 4 bytes reserved at the beginning? What is wrong with this: ubyte[] data; data.reserve(color_data.length * 4); foreach (ref const Color col; color_data) data ~= col.colors; Are you uncomfortable, because it may allocate twice as much space as you need (for bigger color_data)?
Re: new T[size] vs .reserve
On 2013-02-02 19:53, Namespace wrote: Are you uncomfortable, because it may allocate twice as much space as you need (for bigger color_data)? Yes, that's the point. Sorry, I cannot express myself very well in English. You're right. It's surprising for anyone used to dealing with std::vector, that it actually reserves more than you specify. Another odd thing - when pushing back to a vector its capacity grows: 1, 2, 4, 8, 16, 32 ..., but with D arrays it's like 7, 15, 31, 63... Why 2**n - 1? What secret data is hidden after the block? ;)
Re: new T[size] vs .reserve
On 2013-02-02 22:57, FG wrote: On 2013-02-02 22:33, Steven Schveighoffer wrote: Heap block sizes start at 16. One byte overhead is used to store the array length, so the minimum size of ANY array allocation is 15 bytes. How is the length stored because I see only strange numbers in that byte. foreach (end; 2..31) { ubyte[] x; foreach (i; 0..end) { x ~= cast(ubyte)i; } writeln(x.length, , x.capacity, , x.ptr[end]); } Ah, sorry. Silly me. I have figured out that the length byte would have to be aligned to the end of the block, so that is where I should look. The updated code: // size_t ends = [1,2,7,15,31]; // crashes DMD foreach (end; 2..31) { ubyte[] x; foreach (i; 0..end) { x ~= cast(ubyte)i; } writeln(x.length, , x.capacity, , x.ptr[x.capacity]); } return; shows that indeed, there's length written at the end. :) Output: 2 15 2 3 15 3 4 15 4 5 15 5 6 15 6 7 15 7 8 15 8 9 15 9 10 15 10 11 15 11 12 15 12 13 15 13 14 15 14 15 15 15 16 31 16 17 31 17 18 31 18 19 31 19 20 31 20 21 31 21 22 31 22 23 31 23 24 31 24 25 31 25 26 31 26 27 31 27 28 31 28 29 31 29 30 31 30
Re: new T[size] vs .reserve
On 2013-02-02 22:47, monarch_dodra wrote: I suggest you read this: http://dlang.org/d-array-article.html It is a very interesting read, especially for those of us with C++ background. Thank you for pointing me to that article. I have read it months ago and forgotten the important parts. Now it (slices arrays) finally started making sense again. :)
Re: Understanding the GC
On 2013-02-01 16:37, Steven Schveighoffer wrote: Actually, that's a different problem. File is a struct, and structs do NOT have their destructor run by the GC. Only Objects do. This is a GC limitation, since structs do not contain a pointer to their typeinfo like classes do, and there is no provision for storing a pointer to the typeinfo of a block. It could be fixed by a more precise GC. AIUI, we have something like that coming, but I've been hearing that for more than a year ;) So currently the only way to make a struct's destructor work when the struct is on the heap is to encapsulate that struct in a class? I have tested the following: struct A { ... } class C { A a; ... } A a = A(); // OK A *b = new A(); // BAD, no finalization C c = new C(); // OK, a's destructor will be called
Re: Not able to get scaled performance on increasing number of threads
On 2013-02-01 16:42, Sparsh Mittal wrote: When I run it, and compare this parallel version with its serial version, I only get speedup of nearly 1.3 for 2 threads. When I write same program in Go, scaling is nearly 2. Also, in D, on doing top, I see the usage as only 130% CPU and not nearly 200% or 180%. So I was wondering, if I am doing it properly. Please help me. Probably because the SolverSlave doesn't have enough work to do to call for dividing it into threads and barriers with their overhead. Like Dmitry wrote, std.parallelism may be a better tool for the job. I've tested your code on 2 cores (but have put whole main() in a loop). It's taking about 82% of both cores. After increasing gridSize to 1024 it was using 88% of the CPU.
Re: Not able to get scaled performance on increasing number of threads
On 2013-02-01 20:33, Dmitry Olshansky wrote: Mine reiteration on it, with a bit of help from std.parallelism. std.parallelism uses thread pool thus it's somewhat faster then creating threads anew. Interestingly, threads+barrier here wasn't much slower than tasks: 14% slower for dmd32, only 5% for gdc64 (and taskpool in dmd 13% slower than in gdc).
Re: How does array assignment for different sized types work?
On 2013-01-31 10:47, Timon Gehr wrote: The reason is that array literals have special conversion rules It's because floating point literals are double by default. In the first assignment float type can be deduced from v1. To make the second one work, you can explicitly make them float: float[3] v1 = [1.0, 2.0, 3.0]; float[3] v = [1.0f, 2.0f, 3.0f].dup; or duplicate v1:float[3] v = v1.dup;
Re: Looking for command for synchronization of threads
On 2013-01-31 03:29, Sparsh Mittal wrote: Thanks. I wrote this: [...] It compiles but barrier does not get released. Can you please point out the fault. Pardon my mistake. I searched whole web, there are almost no examples of it online. Barrier doesn't release because you've only called wait() from one thread, while initializing the Barrier to use two threads. The following code works for me. Notice that the Barrier and wait() are used in 3 threads. But better have this verified by someone who had done more threading in D. :) #!/usr/bin/env rdmd import std.stdio; import std.concurrency; import std.algorithm; import core.sync.barrier; import core.thread; __gshared Barrier barrier = null; void sorter(Tid owner, shared(int)[] sliceToSort, int mynumber) { writefln(Came inside %s, mynumber); sort(sliceToSort); writefln(Going out of %s, mynumber); barrier.wait(); } void main() { shared numbers = [ 6, 5, 4, 3, 2, 1 ]; barrier = new Barrier(3); spawn(sorter, thisTid, numbers[0 .. $ / 2], 0); spawn(sorter, thisTid, numbers[$ / 2 .. $], 1); writefln(Waiting for barrier in main); barrier.wait(); writefln(All done); writeln(numbers); }
Re: gtkD GUI design
On 2013-01-31 13:35, SaltySugar wrote: Thanks, setBorderWidth() is working but button's size isn't changing. I don't have a working gtk environment to test it, but try this: (maybe hBox2 isn't even needed and you could vBox.add(algn1);) import gtk.MainWindow; import gtk.Label; import gtk.Button; import gtk.VBox; import gtk.HBox; import gtk.Entry; import gtk.Main; import gtk.Alignment; class Application : MainWindow { this() { super(GtkD App); setDefaultSize(200, 200); HBox hBox = new HBox(false, 3); HBox hBox1 = new HBox(false, 3); VBox vBox = new VBox(false, 5); // Alignment(xalign, yalign, xscale, yscale) // xscale = 0 stops the child from stretching in X axis Alignment algn1 = new Alignment(0.5, 0, 0, 0); HBox hBox2 = new HBox(false, 3); Button btnLog = new Button(LOGIN ---); Label lblNick = new Label(User: ); Entry txtNick = new Entry(); Label lblPass = new Label(Password: ); Entry txtPass = new Entry(); btnLog.setSizeRequest(70, 30); vBox.packStart(hBox, true, true, 3); vBox.packStart(hBox1, true, true, 3); vBox.setBorderWidth(8); hBox.add (lblNick); hBox.add (txtNick); hBox1.add (lblPass); hBox1.add (txtPass); algn1.add (btnLog); hBox2.add (algn1); vBox.add (hBox2); add(vBox); showAll(); } } void main(string[] args) { Main.init(args); new Application(); Main.run(); }
Re: gtkD GUI design
On 2013-01-31 14:33, SaltySugar wrote: I have two more questions; First, how to remove an arrow on the window's bottom? By making the window fixed-size, not scalable? Second, when I run my program it runs together with console. I want to run only window of application. How to do it? This has already been asked in this list. Apparently you have to compile like this: dmd.exe -L/SUBSYSTEM:WINDOWS app.d
Re: Is there a string remove method, that takes an index
On 2013-01-30 04:27, Ali Çehreli wrote: s = s[0..7] ~ s[8..$]; As with the other slicing approaches, it would be best to check first if s.length = i (with i = 8 in this case).
Sorted output from an associative array
Let's say i have an array: int[string] wordCount. How to print key:value pairs ordered by descending value? Or generally how to to store wordCount in an array of structs or type tuples for later sorting? In Python I would use something like this: sorted(wordCount.items(), key=lambda a: a[1], reverse=True).
Re: Sorted output from an associative array
Thanks for showing me how to use tuples in this problem. Just for the record, the sort comparison should be reversed: a b.
Re: typeid + toString = runtime error
On 2012-12-30 17:04, Ali Çehreli wrote: Application error: core.exception.InvalidMemoryOperationError My guess is that by the time that destructor is executed, the runtime has been shut down sufficiently that the ~ operator cannot work. I've encountered this error before when using ~ in a destructor even without shutting down the program. I think the garbage collector by throwing this error tries to protect itself by disallowing the creation of any new managed objects while a collection is running. Otherwise things would get too complicated. :)
Re: double free or corruption error when using parallel foreach
On 2012-12-28 01:08, Minas Mina wrote: Note that there is more code after bool hit = ... but I didn't include it because the problem is in the trace function (I commented it out and everything else worked -- apart from the things are dependent on it of course) Why don't you show the trace function then? Where's the rest of the code? [xcb] Unknown request in queue while dequeuing [xcb] Most likely this is a multi-threaded client and XInitThreads has not been called [xcb] Aborting, sorry about that. raytracing: ../../src/xcb_io.c:178: dequeue_pending_request: Assertion `!xcb_xlib_unknown_req_in_deq' failed. bash: line 1: 18982 Aborted (core dumped) /home/minas/Projects/D/raytracing/raytracing/bin/Release/raytracing This sheds some light on the problem. Probably it would go away if only a single thread was made responsible for calls into libxcb. That's a preferable, safer approach than initializing for multi-threading (but have you done the initializing?). double free or corruption IMO that's just a consequence of several threads manipulating same data without any locks or synchronization in place.
Re: Running out of memory
On 2012-12-28 05:41, Jonathan M Davis wrote: The idea is that if you want to be manually freeing memory, you shouldn't be using GC memory in the first place. It's unsafe to be freeing it. Let the GC do that. If you want to manually manage memory, then manually manage it with malloc and free. If you really need to, then core.memory has the functions for managing the GC's memory, but you really shouldn't be doing that normally. I don't require manual malloc. I wanted to make a hint to the GC, that this block can be freed, because I know there are no other pointers into it (that would be used later), while the imprecise GC finds false pointers and prevents the block from being released. Of course delete is not safe in general, but if the program is designed to process data in completely isolated batches, then it shouldn't pose a threat.
GtkD - missing DLLs in Gtk win32 runtime
I'm trying out the latest GtkD binding. The lib has built without problems, some example programs also compile, but I can't run them. The Gtk-Runtime-3.6 archive provided at https://github.com/gtkd-developers/GtkD/downloads is missing several win32 DLL libraries: LIBRARY.GLGDK: libgdkglext-win32-3.0-0.dll, LIBRARY.GLGTK: libgtkglext-win32-3.0-0.dll, LIBRARY.GDA: libgda-4.0-4.dll, LIBRARY.GSV: libgtksourceview-3.0-0.dll, LIBRARY.GSTREAMER: libgstreamer-0.10.dll, LIBRARY.GSTINTERFACES: libgstinterfaces-0.10.dll I found four of them on the net but can't locate these two anywhere: libgdkglext-win32-3.0-0.dll and libgtkglext-win32-3.0-0.dll Please help.
Re: Running out of memory
On 2012-12-27 15:31, bearophile wrote: delete is deprecated in D. There is destroy(), and a replacement for delete in the memory/GC module. destroy() had no effect on program's behavior, even the docs state that it does not initiate a GC cycle or free any GC memory. So I hope delete will still remain an option. Very useful for freeing such large chunks like in this example. What do you mean as the delete replacement?
Re: Running out of memory
On 2012-12-27 16:14, bearophile wrote: FG: What do you mean as the delete replacement? Take a look here (at free()): http://dlang.org/phobos/core_memory.html Oh, I didn't expect this to work on arrays but it does as good as delete: GC.free(cast(void*)s);
Re: Running out of memory
On 2012-12-27 16:31, bearophile wrote: Don't cast arrays arrays to pointers, it's unclean, because dynamic arrays are two words long. Use the .ptr property: GC.free(s.ptr); Things appeared sorted out, but it's not over yet. delete still wins. Performance-wise free() worked like delete, but there's a nasty glitch. The following code crashes after a few hundred loops with core.exception.InvalidMemoryOperationError. import std.stdio, core.memory; char[1000] filler = '.'; int fill_times = 1; void main(string[] args) { char[] s; for (int i=0; i 10; i++) { for (int j=0; j fill_times; j++) s ~= filler; writeln(loop , i + 1, , length: , s.length); stdout.flush(); // delete s; GC.free(s.ptr); s = []; } } Surprisingly, when fill_times = 3736, it always crashes after the 341th loop (relies on the filler having 1000 bytes. Some other numbers also trigger it). What could be responsible for this odd behavior of free()?