mirror of
				https://github.com/KevinMidboe/linguist.git
				synced 2025-10-29 17:50:22 +00:00 
			
		
		
		
	* fix benchmark - require json for Hash.to_json * better heuristic distinction of .d files - properly recongnize dtrace probes - recongnize \ in Makefile paths - recongnize single line `file.ext : dep.ext` make targets - recognize D module, import, function, and unittest declarations - add more representative D samples D changed from 31.2% to 28.1% DTrace changed from 33.5% to 32.5% Makefile changed from 35.3% to 39.4% See https://gist.github.com/MartinNowak/fda24fdef64f2dbb05c5a5ceabf22bd3 for the scraper used to get a test corpus.
		
			
				
	
	
		
			188 lines
		
	
	
		
			4.5 KiB
		
	
	
	
		
			D
		
	
	
	
	
	
			
		
		
	
	
			188 lines
		
	
	
		
			4.5 KiB
		
	
	
	
		
			D
		
	
	
	
	
	
| /**
 | |
|  * Benchmark for array ops.
 | |
|  *
 | |
|  * Copyright: Copyright Martin Nowak 2016 -.
 | |
|  * License:   $(LINK2 http://www.boost.org/LICENSE_1_0.txt, Boost License 1.0)
 | |
|  * Authors:   Martin Nowak
 | |
|  */
 | |
| import core.cpuid, std.algorithm, std.datetime, std.meta, std.stdio, std.string,
 | |
|     std.range;
 | |
| 
 | |
| float[6] getLatencies(T, string op)()
 | |
| {
 | |
|     enum N = (64 * (1 << 6) + 64) * T.sizeof;
 | |
|     auto a = Array!T(N), b = Array!T(N), c = Array!T(N);
 | |
|     float[6] latencies = float.max;
 | |
|     foreach (i, ref latency; latencies)
 | |
|     {
 | |
|         auto len = 1 << i;
 | |
|         foreach (_; 1 .. 32)
 | |
|         {
 | |
|             a[] = 24;
 | |
|             b[] = 4;
 | |
|             c[] = 2;
 | |
|             auto sw = StopWatch(AutoStart.yes);
 | |
|             foreach (off; size_t(0) .. size_t(64))
 | |
|             {
 | |
|                 off = off * len + off;
 | |
|                 enum op = op.replace("const", "2").replace("a",
 | |
|                         "a[off .. off + len]").replace("b",
 | |
|                         "b[off .. off + len]").replace("c", "c[off .. off + len]");
 | |
|                 mixin(op ~ ";");
 | |
|             }
 | |
|             latency = min(latency, sw.peek.nsecs);
 | |
|         }
 | |
|     }
 | |
|     float[6] res = latencies[] / 1024;
 | |
|     return res;
 | |
| }
 | |
| 
 | |
| float[4] getThroughput(T, string op)()
 | |
| {
 | |
|     enum N = (40 * 1024 * 1024 + 64 * T.sizeof) / T.sizeof;
 | |
|     auto a = Array!T(N), b = Array!T(N), c = Array!T(N);
 | |
|     float[4] latencies = float.max;
 | |
|     size_t[4] lengths = [
 | |
|         8 * 1024 / T.sizeof, 32 * 1024 / T.sizeof, 512 * 1024 / T.sizeof, 32 * 1024 * 1024 / T
 | |
|         .sizeof
 | |
|     ];
 | |
|     foreach (i, ref latency; latencies)
 | |
|     {
 | |
|         auto len = lengths[i] / 64;
 | |
|         foreach (_; 1 .. 4)
 | |
|         {
 | |
|             a[] = 24;
 | |
|             b[] = 4;
 | |
|             c[] = 2;
 | |
|             auto sw = StopWatch(AutoStart.yes);
 | |
|             foreach (off; size_t(0) .. size_t(64))
 | |
|             {
 | |
|                 off = off * len + off;
 | |
|                 enum op = op.replace("const", "2").replace("a",
 | |
|                         "a[off .. off + len]").replace("b",
 | |
|                         "b[off .. off + len]").replace("c", "c[off .. off + len]");
 | |
|                 mixin(op ~ ";");
 | |
|             }
 | |
|             immutable nsecs = sw.peek.nsecs;
 | |
|             runMasked({latency = min(latency, nsecs);});
 | |
|         }
 | |
|     }
 | |
|     float[4] throughputs = void;
 | |
|     runMasked({throughputs = T.sizeof * lengths[] / latencies[];});
 | |
|     return throughputs;
 | |
| }
 | |
| 
 | |
| string[] genOps()
 | |
| {
 | |
|     string[] ops;
 | |
|     foreach (op1; ["+", "-", "*", "/"])
 | |
|     {
 | |
|         ops ~= "a " ~ op1 ~ "= b";
 | |
|         ops ~= "a " ~ op1 ~ "= const";
 | |
|         foreach (op2; ["+", "-", "*", "/"])
 | |
|         {
 | |
|             ops ~= "a " ~ op1 ~ "= b " ~ op2 ~ " c";
 | |
|             ops ~= "a " ~ op1 ~ "= b " ~ op2 ~ " const";
 | |
|         }
 | |
|     }
 | |
|     return ops;
 | |
| }
 | |
| 
 | |
| void runOp(string op)()
 | |
| {
 | |
|     foreach (T; AliasSeq!(ubyte, ushort, uint, ulong, byte, short, int, long, float,
 | |
|             double))
 | |
|         writefln("%s, %s, %(%.2f, %), %(%s, %)", T.stringof, op,
 | |
|             getLatencies!(T, op), getThroughput!(T, op));
 | |
| }
 | |
| 
 | |
| struct Array(T)
 | |
| {
 | |
|     import core.stdc.stdlib : free, malloc;
 | |
| 
 | |
|     this(size_t n)
 | |
|     {
 | |
|         ary = (cast(T*) malloc(T.sizeof * n))[0 .. n];
 | |
|     }
 | |
| 
 | |
|     ~this()
 | |
|     {
 | |
|         free(ary.ptr);
 | |
|     }
 | |
| 
 | |
|     T[] ary;
 | |
|     alias ary this;
 | |
| }
 | |
| 
 | |
| version (X86)
 | |
|     version = SSE;
 | |
| else version (X86_64)
 | |
|     version = SSE;
 | |
| else
 | |
|     static assert(0, "unimplemented");
 | |
| 
 | |
| version (SSE)
 | |
| {
 | |
|     uint mxcsr()
 | |
|     {
 | |
|         uint ret = void;
 | |
|         asm
 | |
|         {
 | |
|             stmxcsr ret;
 | |
|         }
 | |
|         return ret;
 | |
|     }
 | |
| 
 | |
|     void mxcsr(uint val)
 | |
|     {
 | |
|         asm
 | |
|         {
 | |
|             ldmxcsr val;
 | |
|         }
 | |
|     }
 | |
| 
 | |
|     // http://softpixel.com/~cwright/programming/simd/sse.php
 | |
|     enum FPU_EXCEPTION_MASKS = 1 << 12 | 1 << 11 | 1 << 10 | 1 << 9 | 1 << 8 | 1 << 7;
 | |
|     enum FPU_EXCEPTION_FLAGS = 1 << 5 | 1 << 4 | 1 << 3 | 1 << 2 | 1 << 1 | 1 << 0;
 | |
| 
 | |
|     void maskFPUExceptions()
 | |
|     {
 | |
|         mxcsr = mxcsr | FPU_EXCEPTION_MASKS;
 | |
|     }
 | |
| 
 | |
|     void unmaskFPUExceptions()
 | |
|     {
 | |
|         mxcsr = mxcsr & ~FPU_EXCEPTION_MASKS;
 | |
|     }
 | |
| 
 | |
|     uint FPUExceptionFlags()
 | |
|     {
 | |
|         return mxcsr & FPU_EXCEPTION_FLAGS;
 | |
|     }
 | |
| 
 | |
|     void clearFPUExceptionFlags()
 | |
|     {
 | |
|         mxcsr = mxcsr & ~FPU_EXCEPTION_FLAGS;
 | |
|     }
 | |
| }
 | |
| 
 | |
| void runMasked(scope void delegate() dg)
 | |
| {
 | |
|     assert(FPUExceptionFlags == 0);
 | |
|     maskFPUExceptions;
 | |
|     dg();
 | |
|     clearFPUExceptionFlags;
 | |
|     unmaskFPUExceptions;
 | |
| }
 | |
| 
 | |
| void main()
 | |
| {
 | |
|     unmaskFPUExceptions;
 | |
| 
 | |
|     writefln("type, op, %(latency%s, %), %-(throughput%s, %)", iota(6)
 | |
|         .map!(i => 1 << i), ["8KB", "32KB", "512KB", "32MB"]);
 | |
|     foreach (op; mixin("AliasSeq!(%(%s, %))".format(genOps)))
 | |
|         runOp!op;
 | |
|     maskFPUExceptions;
 | |
| }
 |