我正在尝试使用 MiscUtils 实现一些通用数学类。示例代码不使用 MiscUtils,只是简单地包装了一个类型,它存在一些主要的性能问题:
在内置值类型上使用数学至少快 15 倍。简单地将值类型包装在结构中大约慢 2 倍。使用动态绕过运算符类型约束大约慢 30 倍!!!!
我的目标是有一个简单的类
class Vector<T> { ... }
并且能够使用 Vector 之类的东西来添加 T 列表而不会显着影响性能(T 将是原始类型)。
结果:
带调试的调试模式:
V = 1.0x (Direct ValueType addition)
WE = 6.4x (Wrapped ValueType empty addition)
WA = 17.9x (Wrapped ValueType MiscUtils addition)
D = 17.8x (Dynamic ValueType addition)
DE = 37.1x (Dynamid Wrapped Valuetype empty addition)
DA = 37.7x (Dynamid Wrapped Valuetype MiscUtils addition)
无需调试的释放模式:
V - 0.36s
WE - 0.27s
WA - 1.25s
D - 1.34s
DE - 7.74s
DA - 7.22s
V = 1.3x
WE = 1.0x
WA = 4.5x
D = 4.9x
DE = 28.2x
DA = 26.3x
V - 0.18s
WE - 0.14s
WA - 0.62s
D - 0.66s
DE - 3.01s
DA - 3.65s
V = 1.3x
WE = 1.0x
WA = 4.5x
D = 4.8x
DE = 21.9x
DA = 26.6x
V - 0.12s
WE - 0.09s
WA - 0.41s
D - 0.44s
DE - 2.17s
DA - 2.42s
V = 1.3x
WE = 1.0x
WA = 4.4x
D = 4.8x
DE = 23.7x
DA = 26.5x
无论如何,可以看出 MiscUtils 比预期的要慢(网站说几个百分比)并且动态非常糟糕。
任何想法发生了什么或如何改善结果?
#define __MiscUtils
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Diagnostics;
#if __MiscUtils
using MiscUtil;
#endif
namespace GenericNumerics
{
struct num1<T> where T : struct
{
public readonly T a;
public num1(T v) { a = v; }
public static num1<T> operator +(num1<T> c1, num1<T> c2) { return new num1<T>(); }
public static implicit operator num1<T>(T d) { return new num1<T>(); }
}
#if __MiscUtils
struct num2<T> where T : struct
{
public readonly T a;
public num2(T v) { a = v; }
public static num2<T> operator +(num2<T> c1, num2<T> c2) { return Operator.Add(c1.a, c2.a); }
public static implicit operator num2<T>(T d) { return new num2<T>(); }
}
#endif
class Program
{
public static Stopwatch Stopwatch = new Stopwatch();
static void Main(string[] args)
{
var cntV = 0L; var cntWE = 0L; var cntWA = 0L; var cntD = 0L; var cntDE = 0L; var cntDA = 0L;
double time = 2000;
for (int k = 0; k < 1; k++)
{
{
Console.Write("V - ");
var x = 1D; var y = 0D; var z = 0D;
Stopwatch.Restart();
while(Stopwatch.ElapsedMilliseconds < time)
{
x = y + z; y = y + z; z = x + z; x = x + z; x = y + z; x = y + z; y = y + z; z = x + z; x = x + z; x = y + z; x = y + z; y = y + z; z = x + z; x = x + z; x = y + z; y = y + z; z = x + z; x = x + z; x = y + z; z = x + z; x = x + z; x = y + z; y = y + z; z = x + z;
x = y + z; y = y + z; z = x + z; x = x + z; x = y + z; x = y + z; y = y + z; z = x + z; x = x + z; x = y + z; x = y + z; y = y + z; z = x + z; x = x + z; x = y + z; y = y + z; z = x + z; x = x + z; x = y + z; z = x + z; x = x + z; x = y + z; y = y + z; z = x + z;
cntV++;
}
Console.WriteLine(String.Format("{0:0.00}s", time/cntV*1000));
}
{
Console.Write("WE - ");
num1<double> x = 1D; num1<double> y = 0D; num1<double> z = 0D;
Stopwatch.Restart();
while (Stopwatch.ElapsedMilliseconds < time)
{
x = y + z; y = y + z; z = x + z; x = x + z; x = y + z; x = y + z; y = y + z; z = x + z; x = x + z; x = y + z; x = y + z; y = y + z; z = x + z; x = x + z; x = y + z; y = y + z; z = x + z; x = x + z; x = y + z; z = x + z; x = x + z; x = y + z; y = y + z; z = x + z;
x = y + z; y = y + z; z = x + z; x = x + z; x = y + z; x = y + z; y = y + z; z = x + z; x = x + z; x = y + z; x = y + z; y = y + z; z = x + z; x = x + z; x = y + z; y = y + z; z = x + z; x = x + z; x = y + z; z = x + z; x = x + z; x = y + z; y = y + z; z = x + z;
cntWE++;
}
Console.WriteLine(String.Format("{0:0.00}s", time / cntWE * 1000));
}
#if __MiscUtils
{
Console.Write("WA - ");
num2<double> x = 1D; num2<double> y = 0D; num2<double> z = 0D;
Stopwatch.Restart();
while (Stopwatch.ElapsedMilliseconds < time)
{
x = y + z; y = y + z; z = x + z; x = x + z; x = y + z; x = y + z; y = y + z; z = x + z; x = x + z; x = y + z; x = y + z; y = y + z; z = x + z; x = x + z; x = y + z; y = y + z; z = x + z; x = x + z; x = y + z; z = x + z; x = x + z; x = y + z; y = y + z; z = x + z;
x = y + z; y = y + z; z = x + z; x = x + z; x = y + z; x = y + z; y = y + z; z = x + z; x = x + z; x = y + z; x = y + z; y = y + z; z = x + z; x = x + z; x = y + z; y = y + z; z = x + z; x = x + z; x = y + z; z = x + z; x = x + z; x = y + z; y = y + z; z = x + z;
cntWA++;
}
Console.WriteLine(String.Format("{0:0.00}s", time / cntWA * 1000));
}
#endif
{
Console.Write("D - ");
dynamic x = 1D; dynamic y = 0D; dynamic z = 0D;
Stopwatch.Restart();
while (Stopwatch.ElapsedMilliseconds < time)
{
x = y + z; y = y + z; z = x + z; x = x + z; x = y + z; x = y + z; y = y + z; z = x + z; x = x + z; x = y + z; x = y + z; y = y + z; z = x + z; x = x + z; x = y + z; y = y + z; z = x + z; x = x + z; x = y + z; z = x + z; x = x + z; x = y + z; y = y + z; z = x + z;
x = y + z; y = y + z; z = x + z; x = x + z; x = y + z; x = y + z; y = y + z; z = x + z; x = x + z; x = y + z; x = y + z; y = y + z; z = x + z; x = x + z; x = y + z; y = y + z; z = x + z; x = x + z; x = y + z; z = x + z; x = x + z; x = y + z; y = y + z; z = x + z;
cntD++;
}
Console.WriteLine(String.Format("{0:0.00}s", time / cntD * 1000));
}
#if __MiscUtils
{
Console.Write("DE - ");
dynamic x = new num2<double>(0); dynamic y = new num2<double>(0); dynamic z = new num2<double>(0);
Stopwatch.Restart();
while (Stopwatch.ElapsedMilliseconds < time)
{
x = y + z; y = y + z; z = x + z; x = x + z; x = y + z; x = y + z; y = y + z; z = x + z; x = x + z; x = y + z; x = y + z; y = y + z; z = x + z; x = x + z; x = y + z; y = y + z; z = x + z; x = x + z; x = y + z; z = x + z; x = x + z; x = y + z; y = y + z; z = x + z;
x = y + z; y = y + z; z = x + z; x = x + z; x = y + z; x = y + z; y = y + z; z = x + z; x = x + z; x = y + z; x = y + z; y = y + z; z = x + z; x = x + z; x = y + z; y = y + z; z = x + z; x = x + z; x = y + z; z = x + z; x = x + z; x = y + z; y = y + z; z = x + z;
cntDE++;
}
Console.WriteLine(String.Format("{0:0.00}s", time / cntDE * 1000));
}
{
Console.Write("DA - ");
dynamic x = new num2<double>(0); dynamic y = new num2<double>(0); dynamic z = new num2<double>(0);
Stopwatch.Restart();
while (Stopwatch.ElapsedMilliseconds < time)
{
x = y + z; y = y + z; z = x + z; x = x + z; x = y + z; x = y + z; y = y + z; z = x + z; x = x + z; x = y + z; x = y + z; y = y + z; z = x + z; x = x + z; x = y + z; y = y + z; z = x + z; x = x + z; x = y + z; z = x + z; x = x + z; x = y + z; y = y + z; z = x + z;
x = y + z; y = y + z; z = x + z; x = x + z; x = y + z; x = y + z; y = y + z; z = x + z; x = x + z; x = y + z; x = y + z; y = y + z; z = x + z; x = x + z; x = y + z; y = y + z; z = x + z; x = x + z; x = y + z; z = x + z; x = x + z; x = y + z; y = y + z; z = x + z;
cntDA++;
}
Console.WriteLine(String.Format("{0:0.00}s", time / cntDA * 1000));
}
#endif
var m = (double)Math.Max(cntV, Math.Max(cntWE, Math.Max(cntWA, Math.Max(cntD, Math.Max(cntDE, cntDA)))));
Console.WriteLine(string.Format("\tV = {0:0.0}x\n\tWE = {1:0.0}x\n\tWA = {2:0.0}x\n\tD = {3:0.0}x\n\tDE = {4:0.0}x\n\tDA = {5:0.0}x\n", m / cntV, m / cntWE, m / cntWA, m / cntD, m / cntDE, m / cntDA));
}
Console.ReadKey();
return;
}
}
}