1 /+ dub.sdl:
2     dependency "numparse" path=".."
3  +/
4 module bench.integer;
5 
6 import std.datetime.stopwatch;
7 import std : uniform, tuple, Tuple, format, to, stderr;
8 
9 import numparse;
10 
11 enum Base
12 {
13     bin = 2,
14     oct = 8,
15     dec = 10,
16     hex = 16
17 }
18 
19 enum N = 5_000_000;
20 
21 string getFormat(Base b, bool longfmt)
22 {
23     final switch (b)
24     {
25         case Base.bin: return longfmt ? "%032b" : "%b";
26         case Base.oct: return longfmt ? "%011o" : "%o";
27         case Base.dec: return longfmt ? "%010d" : "%d";
28         case Base.hex: return longfmt ? "%08x" : "%x";
29     }
30 }
31 
32 float test(Base base)(bool canEmpty=false, bool longFmt=true)
33 {
34     Tuple!(uint, string)[] list;
35     list.length = N;
36 
37     immutable fmt = getFormat(base, longFmt);
38 
39     foreach (i; 0 .. N)
40     {
41         const v = uniform(0, uint.max);
42         const str = format(fmt, v);
43         list[i] = tuple(cast()v, canEmpty ? (v ? str : "") : str);
44     }
45 
46     static void checkValid(uint orig, uint parsed, string str, size_t line=__LINE__)
47     {
48         if (orig == parsed) return;
49         throw new Exception("wrong parse: %s(%d) parsed as %d".format(str, orig, parsed), __FILE__, line);
50     }
51 
52     auto t0 = StopWatch(AutoStart.yes);
53     foreach (v; list)
54     {
55         uint tmp;
56         auto err = parseUintNumber!(base)(tmp, v[1]);
57         if (err != ParseError.none)
58             throw new Exception("parse error: %s".format(err));
59         checkValid(v[0], tmp, v[1]);
60     }
61     t0.stop();
62 
63     auto t1 = StopWatch(AutoStart.yes);
64     foreach (v; list)
65     {
66         uint tmp;
67         if (v[1].length) tmp = v[1].to!uint(cast(int)base);
68         checkValid(v[0], tmp, v[1]);
69     }
70     t1.stop();
71 
72     const t0f = cast(float)t0.peek().total!"hnsecs";
73 
74     stderr.writeln("Base: ", base, " canEmpty: ", canEmpty, " longFmt: ", longFmt);
75     stderr.writeln("numparse: ", t0.peek());
76     stderr.writeln("std impl: ", t1.peek());
77     const win = t1.peek().total!"hnsecs" / t0f;
78     stderr.writeln("     win: ", win);
79     return win;
80 }
81 
82 void main()
83 {
84     import std : EnumMembers;
85 
86     stderr.writeln("number count: ", N);
87 
88     float swin = 0;
89     size_t k = 0;
90 
91     enum params = 
92     [
93         tuple(true, true),
94         tuple(true, false),
95         tuple(false, false),
96         tuple(false, true),
97     ];
98 
99     foreach (pp; params)
100     {
101         static foreach (b; EnumMembers!Base)
102         {
103             swin += test!b(pp.expand);
104             k++;
105         }
106     }
107 
108     stderr.writeln("avg win: ", swin / k);
109 }