www.digitalmars.com         C & C++   DMDScript  

digitalmars.D - I wrote an AR archive (.a files) parser in D

reply Renato <renato athaydes.com> writes:
Hey,

I wanted to learn how AR archives work, and use D for something 
not so hard to practice a little bit.
Unfortunately, they don't seem to be standardized, but [the 
Wikipedia](https://en.wikipedia.org/wiki/Ar_(Unix)) entry helped 
me a lot.

I got it mostly working and it's able to parse several `.a` files 
I've tried, including libphobos.a and .a files generated on my 
system. It's not complete yet as I didn't parse the "file mode" 
bytes and I didn't consider "System V extensions" (though I did 
include the "BSD Variant" as D uses that on MacOS), but that 
should be easy to do soon.

Just announcing here in case someone may be interested in that 
(the code is very easy to read) and wants to give some feedback 
on my usage of D (I'm not experienced in D, just using it for 
some fun every now and then).
Aug 04
next sibling parent reply Renato <renato athaydes.com> writes:
On Sunday, 4 August 2024 at 20:14:50 UTC, Renato wrote:
 I wanted to learn how AR archives work, and use D for something 
 not so hard to practice a little bit.
 Unfortunately, they don't seem to be standardized, but [the 
 Wikipedia](https://en.wikipedia.org/wiki/Ar_(Unix)) entry 
 helped me a lot.
LINK: https://github.com/renatoathaydes/dar
Aug 04
parent Andrea Fontana <nospam example.org> writes:
On Sunday, 4 August 2024 at 20:15:46 UTC, Renato wrote:
 On Sunday, 4 August 2024 at 20:14:50 UTC, Renato wrote:
 I wanted to learn how AR archives work, and use D for 
 something not so hard to practice a little bit.
 Unfortunately, they don't seem to be standardized, but [the 
 Wikipedia](https://en.wikipedia.org/wiki/Ar_(Unix)) entry 
 helped me a lot.
LINK: https://github.com/renatoathaydes/dar
Nice way to practice!
Aug 05
prev sibling next sibling parent reply IchorDev <zxinsworld gmail.com> writes:
On Sunday, 4 August 2024 at 20:14:50 UTC, Renato wrote:
 Just announcing here in case someone may be interested in that 
 (the code is very easy to read) and wants to give some feedback 
 on my usage of D
First of all, you should really be using `const` instead of `in`. Second, do not cast from `const(ubyte[])` to `string`. This is a violation of D’s type system. `string` is an alias of `immutable(char)[]`. You’re casting to `immutable`—never cast to `immutable`! Immutable data must never change during the lifetime of a program, but `const` data may be changed from elsewhere (e.g. another thread), so this cast violates all the assumptions we make for immutable data! Instead, you should cast to `const(char[])` in those places. You also cast to immutable [here](https://github.com/renatoathaydes/dar/blob/364494cfa18c884621c9ea92a800e281e9e4daac/source/dar.d#L122). Since both mutable and immutable data implicitly cast to `const`, if you want to take both as parameters, then always make your parameters `const`.
Aug 06
parent reply Renato Athaydes <renato athaydes.com> writes:
On Tuesday, 6 August 2024 at 14:55:50 UTC, IchorDev wrote:
 On Sunday, 4 August 2024 at 20:14:50 UTC, Renato wrote:
 Just announcing here in case someone may be interested in that 
 (the code is very easy to read) and wants to give some 
 feedback on my usage of D
First of all, you should really be using `const` instead of `in`. Second, do not cast from `const(ubyte[])` to `string`. This is a violation of D’s type system. `string` is an alias of `immutable(char)[]`. You’re casting to `immutable`—never cast to `immutable`! Immutable data must never change during the lifetime of a program, but `const` data may be changed from elsewhere (e.g. another thread), so this cast violates all the assumptions we make for immutable data! Instead, you should cast to `const(char[])` in those places. You also cast to immutable [here](https://github.com/renatoathaydes/dar/blob/364494cfa18c884621c9ea92a800e281e9e4daac/source/dar.d#L122). Since both mutable and immutable data implicitly cast to `const`, if you want to take both as parameters, then always make your parameters `const`.
Why shouldn't I cast the `read` result directly to immutable when it's literally impossible to get a reference to those bytes that is not immutable? It seems like the best way to achieve what I need. Also, I thought `in` is the new way of using `const` parameters, and they're equivalent according to the docs.
Aug 08
next sibling parent reply Renato Athaydes <renato athaydes.com> writes:
On Thursday, 8 August 2024 at 10:44:49 UTC, Renato Athaydes wrote:
 On Tuesday, 6 August 2024 at 14:55:50 UTC, IchorDev wrote:
 On Sunday, 4 August 2024 at 20:14:50 UTC, Renato wrote:
 Just announcing here in case someone may be interested in 
 that (the code is very easy to read) and wants to give some 
 feedback on my usage of D
Second, do not cast from `const(ubyte[])` to `string`
I supposed this is the code bothering you? auto file = (cast(string) input[0 .. 16]).strip; I do want a `string` there, but I think you're saying that because `input` had a `in` attribute, it "may" be mutable via another reference. I agree with that, specially when the "default" implementation get the bytes from a memory-mapped file. What's the best solution in this case, to dup the bytes and then cast to `string`? Or you mean I can't even use `string` at all in this case, and therefore can't use functions like `std.string : strip, startsWith`?
Aug 08
parent IchorDev <zxinsworld gmail.com> writes:
On Thursday, 8 August 2024 at 10:55:49 UTC, Renato Athaydes wrote:
 I supposed this is the code bothering you?

     auto file = (cast(string) input[0 .. 16]).strip;

 I do want a `string` there, but I think you're saying that 
 because `input` had a `in` attribute, it "may" be mutable via 
 another reference.
 I agree with that, specially when the "default" implementation 
 get the bytes from a memory-mapped file. What's the best 
 solution in this case, to dup the bytes and then cast to 
 `string`?
For `file` you should probably use `.idup` since your struct requires a `string`, but for `sizeStr` you can just cast to `const(char)[]`.
 Or you mean I can't even use `string` at all in this case, and 
 therefore can't use functions like `std.string : strip, 
 startsWith`?
That is plainly ridiculous. Read the documentation for these functions below and take note of how neither of them take `immutable(char)[]` (AKA `string`) as parameters: - [`strip`](https://dlang.org/phobos/std_string.html#.strip) takes an array of any `const` char (`char`, `wchar`, or `dchar`). As a reminder, mutable and immutable both implicitly convert to `const`. - [`startsWith`](https://dlang.org/phobos/std_algorithm_search ng.html#startsWith) takes **any** kind of input range. Also about why you should never cast to `immutable`: The reason we have `immutable` is that while `const` may be useful, it doesn’t guarantee anything: - mutable: this data can be modified here - `const`: this data can’t be modified here - `immutable`: this data will NEVER be modified after initialisation The guarantee that `immutable` data is *actually* immutable is important. Casting the contents of an array to `immutable` completely nullifies this guarantee, and might cause problems with code that is optimised around that guarantee. Is this likely to affect your small case? Technically no, but it’s the first step down the dangerous path of lying to the compiler, which might end up causing you a lot of headaches when everything breaks later. Sometimes violating D’s type system is necessary or even desirable (see: `shared` w/ mutexes), but I wouldn’t recommend it for a beginner or even an intermediate D user.
Aug 08
prev sibling parent reply IchorDev <zxinsworld gmail.com> writes:
On Thursday, 8 August 2024 at 10:44:49 UTC, Renato Athaydes wrote:
 Why shouldn't I cast the `read` result directly to immutable 
 when it's literally impossible to get a reference to those 
 bytes that is not immutable? It seems like the best way to 
 achieve what I need.
You’re still violating the guarantees of immutability—data can’t go from mutable to immutable, that’s what `const` is for. Using `const` would be totally fine, or you can use `.idup` to create an immutable copy of the array.
 Also, I thought `in` is the new way of using `const` parameters
No, it’s an old redundant way of using `const` for parameters. It also doesn’t let you specify what part of the type is constant, like `const(ubyte)[]` vs `const(ubyte[])`. It’s completely useless.
 and they're equivalent according to the docs.
In the future `in` might be replaced with a functional equivalent of `scope ref const` that binds rvalues, which is also mentioned in the spec. You can try this newer functionality with `-preview=in`, but using previews is not ideal for libraries. Also the new behaviour of `in` is basically a waste of time for arrays. It’s moreso for medium-sized structs that would actually be expensive to copy.
Aug 08
next sibling parent reply Renato Athaydes <renato athaydes.com> writes:
On Thursday, 8 August 2024 at 11:07:35 UTC, IchorDev wrote:
 On Thursday, 8 August 2024 at 10:44:49 UTC, Renato Athaydes 
 wrote:
 Why shouldn't I cast the `read` result directly to immutable 
 when it's literally impossible to get a reference to those 
 bytes that is not immutable? It seems like the best way to 
 achieve what I need.
You’re still violating the guarantees of immutability—data can’t go from mutable to immutable, that’s what `const` is for. Using `const` would be totally fine, or you can use `.idup` to create an immutable copy of the array.
 Also, I thought `in` is the new way of using `const` parameters
No, it’s an old redundant way of using `const` for parameters. It also doesn’t let you specify what part of the type is constant, like `const(ubyte)[]` vs `const(ubyte[])`. It’s completely useless.
Wait a second... is that your opinion or official D's position? Because `in` is [documented](https://dlang.org/spec/function.html#param-storage) as being used for function inputs:
 Input parameters behave as if they have the const scope storage 
 classes. Input parameters may also be passed by reference by 
 the compiler.
That's EXACTLY what I want! And it's shorter and nicer looking than const. Sorry, but I will keep using it :).
 That is plainly ridiculous. Read the documentation for these 
 functions...
Sorry, but have I made you angry somehow? Can we just talk in a civilized way please? I thought that functions from a module called `std.string` would take, you know, strings.
  Is this likely to affect your small case? Technically no, but 
 it’s the first step down the dangerous path of lying to the 
 compiler,
The program works and I didn't lie to the compiler. `read` doesn't keep a reference to the byte array, and there's no way to access it since I cast it before assigning it. I get your point, but I don't see why insist on not casting to immutable even when it's patently safe to do so.
Aug 08
parent IchorDev <zxinsworld gmail.com> writes:
On Thursday, 8 August 2024 at 16:42:30 UTC, Renato Athaydes wrote:
 On Thursday, 8 August 2024 at 11:07:35 UTC, IchorDev wrote:
 Input parameters behave as if they have the const scope 
 storage classes. Input parameters may also be passed by 
 reference by the compiler.
That's EXACTLY what I want! And it's shorter and nicer looking than const. Sorry, but I will keep using it :).
You might’ve neglected to read the note above:
 **Note: The following requires the -preview=in switch, 
 available in v2.094.0 or higher. When not in use, in is 
 equivalent to const.**
Again, using previews in libraries is generally not great for code compatibility, but you will have to add the preview switch to your project for `in` to behave the way you want. Right now, your code is still using `in` as an alias to `const`, which could potentially become an issue if the new `in` behaviour becomes the default and your code doesn’t treat those parameters as if they’re also `scope`.
 Sorry, but have I made you angry somehow?
 Can we just talk in a civilized way please?
You were just wrong. It’s not uncivilised to point out how absurdly wrong you were. If you do not like being told that you’re wrong then don’t be wrong.
 I thought that functions from a module called `std.string` 
 would take, you know, strings.
`string` AKA `immutable(char)[]` and `char[]` are both ‘strings’, it’s just that we don’t usually pass around mutable strings. Also `startsWith` is a `public import` from `std.range.searching`. How did you manage to call these functions without reading their documentation?
 `read` doesn't keep a reference to the byte array
That depends on the implementation of the function, which could change to keep a mutable reference without any warning since it isn’t `pure` or anything. Is it right to assume that a given impure function does not and will never in a future revision keep a mutable reference to its return value? I think not opening that can of worms is just simpler to manage, and `const` will work the same way in your case anyway. You’re not sharing data between threads or anything. In your new code you’re casting to `const char[]` a lot when it would probably be preferable to cast to `const(char)[]` to avoid the headaches of having the array itself be `const`, thereby preventing you from reassigning to it. There’s rarely a reason to make an array `const` because it’s just a pointer and a length—it’d be like using `char const * const` in C.
Aug 09
prev sibling parent reply Paul Backus <snarwin gmail.com> writes:
On Thursday, 8 August 2024 at 11:07:35 UTC, IchorDev wrote:
 On Thursday, 8 August 2024 at 10:44:49 UTC, Renato Athaydes 
 wrote:
 Why shouldn't I cast the `read` result directly to immutable 
 when it's literally impossible to get a reference to those 
 bytes that is not immutable? It seems like the best way to 
 achieve what I need.
You’re still violating the guarantees of immutability—data can’t go from mutable to immutable, that’s what `const` is for. Using `const` would be totally fine, or you can use `.idup` to create an immutable copy of the array.
Strictly speaking, you are allowed to cast from const/mutable to immutable if there is only one reference to the data in question:
 A memory location can be transferred from thread-local to 
 immutable or shared if there is only one reference to the 
 location.
Source: https://dlang.org/spec/intro.html#memory-model The recommended way to do this is to use the library function [`assumeUnique`][1], since that communicates the intent of the code better than a naked cast. [1]: https://dlang.org/library/std/exception/assume_unique.html
Aug 09
parent IchorDev <zxinsworld gmail.com> writes:
On Saturday, 10 August 2024 at 00:44:29 UTC, Paul Backus wrote:
 Strictly speaking, you are allowed to cast from const/mutable 
 to immutable if there is only one reference to the data in 
 question:

 A memory location can be transferred from thread-local to 
 immutable or shared if there is only one reference to the 
 location.
Source: https://dlang.org/spec/intro.html#memory-model
Yes, it also says so in [section 2 here](https://dlang.org/spec/const3.html#creating_immutable_data). However, the function doesn’t guarantee or even promise that it returns the only mutable reference, so using an explicit cast cannot be guaranteed to be safe without manual verification. I think `read`’s POSIX implementation does return the only mutable reference, but I’m not that familiar with POSIX functions.
 The recommended way to do this is to use the library function 
 [`assumeUnique`][1], since that communicates the intent of the 
 code better than a naked cast.

 [1]: https://dlang.org/library/std/exception/assume_unique.html
Good point, I forgot about that.
Aug 10
prev sibling parent reply Renato <renato athaydes.com> writes:
On Sunday, 4 August 2024 at 20:14:50 UTC, Renato wrote:
 Just announcing here in case someone may be interested in that 
 (the code is very easy to read) and wants to give some feedback 
 on my usage of D (I'm not experienced in D, just using it for 
 some fun every now and then).
I wrote this also in Dart and Common Lisp as I was curious how D would compare to them. Dart can parse libphobos.a in 1.3 seconds, and Common Lisp in around 1.5. With D, it took only 0.4 seconds! And the code is actually the easiest to read IMHO. A win for D :) Both Dart and Common Lisp are pretty fast (for my usual needs, Lisp in particular is very, very fast for small scripts like this, sometimes beating Rust in my previous comparisons), so the bar was not too low as I see it. I am afraid the speedup may be due to D using mmap, and the other languages just reading the file in chunks. But my goal was not to make a fair benchmark!! It was to write the code for this in the most "natural" way that the language allowed... I used mmap in D because it's in the stdlib! In the other languages, it's possible only via libs. I might later convert D to use the exact same approach as in the other languages, just for curiosity... and I think that should be pretty easy, and if it is, it will prove to me that D really is a flexible language that makes it "easy" to modify code... will see. I know I should also write it in Rust to feel more "convinced" to use D... but I am not sure I will bother because I already know Rust and I just don't feel like using it for anything (it's a combination of hard to write and modify code, ridiculous slow compile times even for small projects, but specially when using libs, which you need to for even the most basic stuff like proper error reporting etc....). Anyway, in the unlikely case someone is curious about what code looks like in these 3 languages: D: https://github.com/renatoathaydes/dar/blob/main/source/dar.d Dart and Common Lisp: https://gist.github.com/renatoathaydes/54a93e91cacfafd08ad875f11615fbc2
Aug 17
parent reply IchorDev <zxinsworld gmail.com> writes:
On Saturday, 17 August 2024 at 19:05:22 UTC, Renato wrote:
 On Sunday, 4 August 2024 at 20:14:50 UTC, Renato wrote:
 I wrote this also in Dart and Common Lisp as I was curious how 
 D would compare to them.

 Dart can parse libphobos.a in 1.3 seconds, and Common Lisp in 
 around 1.5.
 With D, it took only 0.4 seconds! And the code is actually the 
 easiest to read IMHO.

 A win for D :)
Congrats! Which D compiler & flags did you use to test this BTW?
 I might later convert D to use the exact same approach as in 
 the other languages, just for curiosity... and I think that 
 should be pretty easy, and if it is, it will prove to me that D 
 really is a flexible language that makes it "easy" to modify 
 code... will see.
D is generally pretty good for refactoring in my experience; except when you need to swap a class with a struct, which is when it gets a bit messy.
 I already know Rust and I just don't feel like using it for 
 anything (it's a combination of hard to write and modify code, 
 ridiculous slow compile times even for small projects, but 
 specially when using libs, which you need to for even the most 
 basic stuff like proper error reporting etc....).
I tried to learn Rust myself, and it certainly didn’t inspire me to keep coming back for more. I could see that a lot of Rust’s design patterns were clearly from the wish-lists of some long-time sufferers of C, but there were clearly a few lessons they never learned. For one, that `snake_case` and `::` are just awful, genuinely so awful that their prevalence in Rust was very concerning to me. And for two, most programmers don’t want to have only one retained mutable reference at once; in fact many design patterns are completely impossible that way. Before it was too late, I realised that Rust is where happiness goes to die, which didn’t make me feel like my prospects with it were very great. You don’t want to spend 10 years honing your skills in a language that makes you miserable, after all. So I gave up and kept searching back then, and here I am now.
 Anyway, in the unlikely case someone is curious about what code 
 looks like in these 3 languages:

 D: https://github.com/renatoathaydes/dar/blob/main/source/dar.d

 Dart and Common Lisp: 
 https://gist.github.com/renatoathaydes/54a93e91cacfafd08ad875f11615fbc2
The Dart code looks less awful than I was expecting given its… progenitor. Shamefully, I cannot read Lisp for the life of me, despite being infatuated with the language’s design pattern, so I can’t comment on that one.
Aug 17
next sibling parent reply Renato <renato athaydes.com> writes:
On Saturday, 17 August 2024 at 20:36:47 UTC, IchorDev wrote:

 The Dart code looks less awful than I was expecting given its… 
 progenitor. Shamefully, I cannot read Lisp for the life of me, 
 despite being infatuated with the language’s design pattern, so 
 I can’t comment on that one.
Dart is an excellent language and has been getting lots of very useful features lately, and its IDE/tooling support is next to none. If it performed as well as D, honestly, I would use Dart for almost everything. My "main" working languages are Java and Kotlin (but I am tired of them and their build systems specially), and Dart is a bit closer than D to what I know... so it's much more comfortable for me to write it... OTOH I like how D "challenges" me more, and lets me write code about as low level as C if I want to, which those other languages don't. Common Lisp for me is also about "challenging" myself. It's fun to write in the REPL (though you do need to get over the emacs initial learning curve... I've heard some people use the VSCode Lisp plugin as well but haven't tried it yet) and in projects where I want to quickly experiment and iterate, the REPL is very handy. But the language is a bit archaic, specially the tools around it like ASDF and Quicklisp... and the error reporting is pretty awful (to give you an idea, it's much worse than Java stacktraces). Anyway, this may be interesting to language nerds like me :) if D attracts me, and others who like D have similar preferences as me, perhaps these other languages may be interesting to you guys as well.
Aug 19
parent Lance Bachmeier <no spam.net> writes:
On Monday, 19 August 2024 at 08:27:39 UTC, Renato wrote:

 Anyway, this may be interesting to language nerds like me :) if 
 D attracts me, and others who like D have similar preferences 
 as me, perhaps these other languages may be interesting to you 
 guys as well.
I was using Common Lisp before D. It was clearly from a different time period, which I blame on the language becoming standardized and the users bludgeoning anyone that dared to suggest things should be updated, since the language was divinely inspired. Names like set, setq, setf, princ, prin1, mapcar, mapcan, and mapl were more than I could handle. I really liked Clojure. The problem was that you're stuck with the JVM, which for my work made it useless (they intentionally crippled C interop). Scheme is fun to use, but it always felt like it was missing functionality, and the code was fairly slow. S-expressions have always felt like the natural way to write code. I've considered writing an s-expression syntax for D. Then I would be able to change the language if I didn't like it. (I know Walter's opinion on this, I just happen to disagree, because that strategy results in a good language for the guy that writes the compiler but less so for everyone else. I've always felt the main problem with Lisp was people writing bad code, not the things the language let you do.)
Aug 19
prev sibling parent reply Renato <renato athaydes.com> writes:
On Saturday, 17 August 2024 at 20:36:47 UTC, IchorDev wrote:
 Congrats! Which D compiler & flags did you use to test this BTW?
I've just [converted the code](https://github.com/renatoathaydes/dar/commit/c81daa297a523f93fafbe 564d36c15a52c04162) to use file random access, and it's about the same speed or maybe a bit slower than mmap. Changing the D Code was as easy as it could be. No architectural changes required as something like Rust would definitely require. I wasn't sure memory-mapped files would be faster, but it seemed easier to write the code based on that so I started with that... anyway, with random access (basically, `File.rawRead` and `File.seek`) it's a little harder to write, and the phobos lib is parsed in 0.110 secs with DMD (best of 3 tries, it varies a lot but second and third runs are much faster as I guess MacOS keeps the file's contents near memory?!), and 0.086 secs with LDC... very similar timings with the previous implementation, but that can go as low as 0.078 secs (within the "noise"). But using mmap was actually using a lot of memory, about as much memory as the size of the parsed file (~20MB) - perhaps I made a mistake the impl but I expected only the portion of the file I kept in memory at any time to remain in memory. With the random access impl, it used only 1.6MB of RAM. Now, I am curious why D is so much faster than Dart (best time: 1.2 secs - and the Dart code is not even handling the file names properly with the BSD variant, which costs time to do) :D. I've run benchmarks before where Dart was quite a bit faster when compiled to a binary executable (it was basically a deep tree allocation problem, Dart just seems to be able to allocate memory much faster than D).
Aug 20
parent reply IchorDev <zxinsworld gmail.com> writes:
On Tuesday, 20 August 2024 at 19:53:40 UTC, Renato wrote:
 Now, I am curious why D is so much faster than Dart
That’s why I’d really like to know what D compiler & flags you’re measuring the speed with. Like, is it really faster across the board, or only when using optimised LDC2 builds? I can imagine the difference could also be to do with Dart’s libraries introducing some overhead, like always calling stat when loading a file for instance. Also interestingly you say that Dart can allocate faster than D? D’s allocation speed is usually part of its performance advantage over other languages, since many other languages just use C’s malloc. Do you know what Dart’s allocator is?
Aug 22
parent reply Renato Athaydes <renato athaydes.com> writes:
On Thursday, 22 August 2024 at 14:17:52 UTC, IchorDev wrote:
 On Tuesday, 20 August 2024 at 19:53:40 UTC, Renato wrote:
 Now, I am curious why D is so much faster than Dart
That’s why I’d really like to know what D compiler & flags you’re measuring the speed with. Like, is it really faster across the board, or only when using optimised LDC2 builds? I can imagine the difference could also be to do with Dart’s libraries introducing some overhead, like always calling stat when loading a file for instance. Also interestingly you say that Dart can allocate faster than D? D’s allocation speed is usually part of its performance advantage over other languages, since many other languages just use C’s malloc. Do you know what Dart’s allocator is?
I use `dub build --build=release`, as explained in my project's README. I don't know how Dart allocates, I presume it uses the JVM strategy of pre-allocating memory on the heap so each single allocation is practically free.
Aug 22
parent reply IchorDev <zxinsworld gmail.com> writes:
On Thursday, 22 August 2024 at 16:21:45 UTC, Renato Athaydes 
wrote:
 I use `dub build --build=release`, as explained in my project's 
 README.
That doesn’t tell me which compiler you’re using. It should say when you run dub, or if not you can see the commands it runs using `-v`. If it’s dmd then I guess Google must be hiring monkeys to sit at typewriters over there or something.
 I don't know how Dart allocates
Oh well!
Aug 22
parent Renato <renato athaydes.com> writes:
On Thursday, 22 August 2024 at 21:54:33 UTC, IchorDev wrote:
 On Thursday, 22 August 2024 at 16:21:45 UTC, Renato Athaydes 
 wrote:
 I use `dub build --build=release`, as explained in my 
 project's README.
That doesn’t tell me which compiler you’re using.
I already told you (just check previous messages). Latest DMD, latest LDC2. I ran with -v and it spills out the compiler flags it sets, if you're really interested in that: ``` -release -inline -O -w -version=Have_dar -Isource/ source/app.d source/dar.d -c -vcolumns ``` Seems like a pretty good combination. By the way, as I've gone through the D Book, I noticed I could get a `InputRange` implemented by simpler blocking code that uses Fibers, so I made a change to use `std.concurrency.Generator` and I am happier with the code using that (implementing the range methods kind of sucks IMO): https://github.com/renatoathaydes/dar/pull/2/files Performance seems to be the same, though the runtime varies considerably between runs... the RAM usage is the same (very low, like 1MB for parsing a 20MB file).
 It should say when you run dub, or if not you can see the 
 commands it runs using `-v`. If it’s dmd then I guess Google 
 must be hiring monkeys to sit at typewriters over there or 
 something.
I don't understand what you're suggesting. Are you trying to say Google employees are stupid because Dart is slower than D on this particular completely unfair and unscientific comparison? I don't think that's a reasonable assessment.
 I don't know how Dart allocates
Oh well!
Anyway, I found the benchmark where Dart is 2x faster than D, and faster than Java as well (but Java was closer): https://github.com/hanabi1224/Programming-Language-Benchmarks/issues/378 As I mentioned on that Thread, in which the other person unfortunately became defensive ( I was actually trying to make the D example faster as the results didn't make any sense to me at the time, I did expect D to win by far ), the HTTP server in Dart is also quite a bit faster than D's (at least the solutions submitted in the Programming Languages Benchmarks). Just goes to show that things are not as simple as "Language X is faster than Y".
Aug 25