Thread overview
[phobos] enforce() in std.container.Array
Nov 19, 2010
David Simcha
Nov 19, 2010
Jonathan M Davis
November 19, 2010
I'm looking to try out std.container.Array for a few huge arrays that the GC isn't cutting it for.  I noticed that this container is always bounds checked via enforce().  This has huge performance costs:

import std.stdio, std.container, std.datetime;

void main() {
     Array!uint arr;
     arr.length = 10_000_000;
     //auto arr = new uint[10_000_000];
     auto sw = StopWatch(autoStart);
     foreach(i; 0..arr.length) {
         arr[i] = i;
     }

     writeln(sw.peek.milliseconds);
}

This benchmark takes about 86 milliseconds with -O -inline -release. When I use the builtin version instead (comment out the std.container.Array stuff and uncomment the uint[] stuff) it only takes about 18 milliseconds.  Should I change front(), popFront(), opIndex(), etc. to be templates that use assert and give the caller's line and file on failure, just like regular builtin arrays?
November 19, 2010
On Friday, November 19, 2010 05:55:52 David Simcha wrote:
> I'm looking to try out std.container.Array for a few huge arrays that the GC isn't cutting it for.  I noticed that this container is always bounds checked via enforce().  This has huge performance costs:
> 
> import std.stdio, std.container, std.datetime;
> 
> void main() {
>      Array!uint arr;
>      arr.length = 10_000_000;
>      //auto arr = new uint[10_000_000];
>      auto sw = StopWatch(autoStart);
>      foreach(i; 0..arr.length) {
>          arr[i] = i;
>      }
> 
>      writeln(sw.peek.milliseconds);
> }
> 
> This benchmark takes about 86 milliseconds with -O -inline -release.
> When I use the builtin version instead (comment out the
> std.container.Array stuff and uncomment the uint[] stuff) it only takes
> about 18 milliseconds.  Should I change front(), popFront(), opIndex(),
> etc. to be templates that use assert and give the caller's line and file
> on failure, just like regular builtin arrays?

Well, as long as the assertions have error messages which make it very clear that it's the user of Array that's screwing up and not the developers or Array, it seems to me to be a very good idea. One thing that would be interesting to look at though would be the cost if enforce weren't lazy. That wouldn't account for the whole cost (maybe even very little of it), but it would be interesting to look at - especially if the enforce calls in question don't need the laziness for their message arguments.

- Jonathan M Davis.
November 19, 2010
I think we should go with the same level of checking as built-in arrays. That means we can get rid of enforce, but the indexing operation used underneath should use a slice, not a pointer.

Andrei

On 11/19/10 5:55 AM, David Simcha wrote:
> I'm looking to try out std.container.Array for a few huge arrays that the GC isn't cutting it for. I noticed that this container is always bounds checked via enforce(). This has huge performance costs:
>
> import std.stdio, std.container, std.datetime;
>
> void main() {
> Array!uint arr;
> arr.length = 10_000_000;
> //auto arr = new uint[10_000_000];
> auto sw = StopWatch(autoStart);
> foreach(i; 0..arr.length) {
> arr[i] = i;
> }
>
> writeln(sw.peek.milliseconds);
> }
>
> This benchmark takes about 86 milliseconds with -O -inline -release.
> When I use the builtin version instead (comment out the
> std.container.Array stuff and uncomment the uint[] stuff) it only takes
> about 18 milliseconds. Should I change front(), popFront(), opIndex(),
> etc. to be templates that use assert and give the caller's line and file
> on failure, just like regular builtin arrays?
> _______________________________________________
> phobos mailing list
> phobos at puremagic.com
> http://lists.puremagic.com/mailman/listinfo/phobos