Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/312.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 奇怪的性能测试行为_C#_Performance - Fatal编程技术网

C# 奇怪的性能测试行为

C# 奇怪的性能测试行为,c#,performance,C#,Performance,作为我昨天发布的问题的后续,我决定继续编写一个简单的RealNumberclass wrappingdecimal,以启用通用数学,并进行一些简单的测试以查看性能比较(请不要评论为什么、为什么或如何实现十进制包装器,这不是本问题的目的) 我决定比较以下两种实现: RealNumberStruct:接口选项 RealNumberClass:抽象基类选项 RealNumberStruct的代码如下: internal interface IArithmetic : IEquatable<IAr

作为我昨天发布的问题的后续,我决定继续编写一个简单的
RealNumber
class wrapping
decimal
,以启用通用数学,并进行一些简单的测试以查看性能比较(请不要评论为什么、为什么或如何实现十进制包装器,这不是本问题的目的)

我决定比较以下两种实现:

  • RealNumberStruct
    :接口选项
  • RealNumberClass
    :抽象基类选项
  • RealNumberStruct的代码如下:

    internal interface IArithmetic : IEquatable<IArithmetic>
    {
        IArithmetic Add(IArithmetic right);
        IArithmetic Subtract(IArithmetic right);
        IArithmetic Multiply(IArithmetic right);
        IArithmetic Divide(IArithmetic right);
        IArithmetic Negate();
    }
    
    public struct RealNumberStruct : IArithmetic
    {
        private readonly decimal value;
    
        private RealNumberStruct(decimal d)
        {
            this.value = d;
        }
    
        public static implicit operator decimal(RealNumberStruct value)
        {
            return value.value;
        }
    
        public static implicit operator RealNumberStruct(decimal value)
        {
            return new RealNumberStruct(value);
        }
    
        public static RealNumberStruct operator +(RealNumberStruct left, RealNumberStruct right)
        {
            return new RealNumberStruct(left.value + right.value);
        }
    
        public static RealNumberStruct operator -(RealNumberStruct value)
        {
            return new RealNumberStruct(-value.value);
        }
    
        public static RealNumberStruct operator -(RealNumberStruct left, RealNumberStruct right)
        {
            return new RealNumberStruct(left.value - right.value);
        }
    
        public static RealNumberStruct operator *(RealNumberStruct left, RealNumberStruct right)
        {
            return new RealNumberStruct(left.value * right.value);
        }
    
        public static RealNumberStruct operator /(RealNumberStruct left, RealNumberStruct right)
        {
            return new RealNumberStruct(left.value / right.value);
        }
    
        IArithmetic IArithmetic.Add(IArithmetic right)
        {
            if (!(right is RealNumberStruct))
                throw new ArgumentException();
    
            return this + (RealNumberStruct)right;
        }
    
        IArithmetic IArithmetic.Subtract(IArithmetic right)
        {
            if (!(right is RealNumberStruct))
                throw new ArgumentException();
    
            return this - (RealNumberStruct)right;
        }
    
        IArithmetic IArithmetic.Multiply(IArithmetic right)
        {
            if (!(right is RealNumberStruct))
                throw new ArgumentException();
    
            return this * (RealNumberStruct)right;
        }
    
        IArithmetic IArithmetic.Divide(IArithmetic right)
        {
            if (!(right is RealNumberStruct))
                throw new ArgumentException();
    
            return this / (RealNumberStruct)right;
        }
    
        IArithmetic IArithmetic.Negate()
        {
            return -this;
        }
    
        bool IEquatable<IArithmetic>.Equals(IArithmetic other)
        {
            throw new NotImplementedException();
        }
    }
    
    public abstract class Arithmetic: IEquatable<Arithmetic>
    {
        protected abstract Arithmetic _Add(Arithmetic right);
        protected abstract Arithmetic _Subtract(Arithmetic right);
        protected abstract Arithmetic _Multiply(Arithmetic right);
        protected abstract Arithmetic _Divide(Arithmetic right);
        protected abstract Arithmetic _Negate();
        internal Arithmetic Add(Arithmetic right) { return _Add(right); }
        internal Arithmetic Subtract(Arithmetic right) { return _Subtract(right); }
        internal Arithmetic Multiply(Arithmetic right) { return _Multiply(right); }
        internal Arithmetic Divide(Arithmetic right) { return _Divide(right); }
        internal Arithmetic Negate() { return _Negate(); }
        public abstract bool Equals(Arithmetic other);
    }
    
    public class RealNumberClass : Arithmetic
    {
        private readonly decimal value;
    
        private RealNumberClass(decimal d)
        {
            this.value = d;
        }
    
        public static implicit operator decimal(RealNumberClass value)
        {
            return value.value;
        }
    
        public static implicit operator RealNumberClass(decimal value)
        {
            return new RealNumberClass(value);
        }
    
        public static RealNumberClass operator +(RealNumberClass left, RealNumberClass right)
        {
            return new RealNumberClass(left.value + right.value);
        }
    
        public static RealNumberClass operator -(RealNumberClass value)
        {
            return new RealNumberClass(-value.value);
        }
    
        public static RealNumberClass operator -(RealNumberClass left, RealNumberClass right)
        {
            return new RealNumberClass(left.value - right.value);
        }
    
        public static RealNumberClass operator *(RealNumberClass left, RealNumberClass right)
        {
            return new RealNumberClass(left.value * right.value);
        }
    
        public static RealNumberClass operator /(RealNumberClass left, RealNumberClass right)
        {
            return new RealNumberClass(left.value / right.value);
        }
    
        protected override Arithmetic _Add(Arithmetic right)
        {
            if (!(right is RealNumberClass))
                throw new ArgumentException();
    
            return this + (RealNumberClass)right;
        }
    
        protected override Arithmetic _Subtract(Arithmetic right)
        {
            if (!(right is RealNumberClass))
                throw new ArgumentException();
    
            return this - (RealNumberClass)right;
        }
    
        protected override Arithmetic _Multiply(Arithmetic right)
        {
            if (!(right is RealNumberClass))
                throw new ArgumentException();
    
            return this * (RealNumberClass)right;
        }
    
        protected override Arithmetic _Divide(Arithmetic right)
        {
            if (!(right is RealNumberClass))
                throw new ArgumentException();
    
            return this / (RealNumberClass)right;
        }
    
        protected override Arithmetic _Negate()
        {
            return -this;
        }
    
        public override bool Equals(Arithmetic other)
        {
            throw new NotImplementedException();
        }
    }
    
    现在,如果我继续使用以下代码测试此代码:

        static void TestPerformance(int outerCount)
        {
            int count = 0;
    
            do
            {
                var stopWatch = new Stopwatch();
                int repetitions = 100000;
                testRealNumberStruct(1);
                testRealNumberClass(1);
                testDecimal(1);
                double structAverage = 0, classAverage = 0, decimalAverage = 0;
    
                for (int i = 0; i < outerCount; i++)
                {
                    Console.WriteLine();
                    stopWatch.Start();
                    testRealNumberStruct(repetitions);
                    stopWatch.Stop();
                    structAverage += stopWatch.ElapsedMilliseconds;
                    Console.WriteLine("RealNumber struct test: {0} ms", stopWatch.ElapsedMilliseconds);
    
                    stopWatch = new Stopwatch();
                    stopWatch.Start();
                    testRealNumberClass(repetitions);
                    stopWatch.Stop();
                    classAverage += stopWatch.ElapsedMilliseconds;
                    Console.WriteLine("RealNumber class test: {0} ms", stopWatch.ElapsedMilliseconds);
                    stopWatch.Reset();
    
                    stopWatch = new Stopwatch();
                    stopWatch.Start();
                    testDecimal(repetitions);
                    stopWatch.Stop();
                    decimalAverage += stopWatch.ElapsedMilliseconds;
                    Console.WriteLine("Decimal test: {0} ms", stopWatch.ElapsedMilliseconds);
                    Console.WriteLine();
                }
    
                Console.WriteLine();
                Console.WriteLine("Test #{0} results----------------------------------", ++count);
                Console.WriteLine("RealNumber struct average: {0:F0} ms", structAverage / outerCount);
                Console.WriteLine("RealNumber class average: {0:F0} ms", classAverage / outerCount);
                Console.WriteLine("Decimal average: {0:F0} ms", decimalAverage / outerCount);
    
            } while (Console.ReadKey().Key != ConsoleKey.Q);
        }
    
        private static void testRealNumberStruct(int repetitions)
        {
            for (int i = 0; i < repetitions; ++i)
            {
                IArithmetic d1 = (RealNumberStruct)1.25m;
                IArithmetic d2 = (RealNumberStruct)(-0.25m);
    
                var d = d1.Multiply(d2);
                d = d.Add(d1);
                d = d2.Divide(d);
                d = d1.Subtract(d);
            }
        }
    
        private static void testRealNumberClass(int repetitions)
        {
            for (int i = 0; i < repetitions; ++i)
            {
                Arithmetic d1 = (RealNumberClass)1.25m;
                Arithmetic d2 = (RealNumberClass)(-0.25m);
                var d = d1.Multiply(d2);
                d = d.Add(d1);
                d = d2.Divide(d);
                d = d1.Subtract(d);
            }
        }
    
        private static void testDecimal(int repetitions)
        {
            for (int i = 0; i < repetitions; ++i)
            {
                var d1 = 1.25m;
                var d2 = -0.25m;
                var d = d1 * d2;
                d = d + d1;
                d = d2 / d;
                d = d1 - d;
            }
        }
    
    静态无效测试性能(int-outerCount)
    {
    整数计数=0;
    做
    {
    var stopWatch=新秒表();
    重复整数=100000;
    testRealNumberStruct(1);
    testRealNumberClass(1);
    testDecimal(1);
    双结构平均值=0,类平均值=0,小数平均值=0;
    对于(int i=0;i
    <>我总是得到我认为奇怪的行为。测试的输出(<代码> OutTeCube=3 )如下:

    RealNumber结构测试:40ms

    RealNumber类测试:35毫秒

    十进制测试:29毫秒

    RealNumber结构测试:64毫秒

    RealNumber类测试:32毫秒

    十进制测试:27毫秒

    RealNumber结构测试:62毫秒

    RealNumber类测试:33毫秒

    十进制测试:27毫秒

    测试#1结果-----------------------------------

    RealNumber结构平均值:55毫秒

    RealNumber类平均值:33毫秒

    十进制平均值:28毫秒

    请注意,在第一次运行中,
    realmumberstruct
    realmumberclass
    的性能相似(40 ms vs 35 ms),但在运行2和3
    realmumberstruct
    时性能下降(62和52 ms)而
    RealNumberClass
    decimal
    的性能保持不变。无论我运行多少次,这似乎都是一个一致的行为;第一次运行总是要快得多。有人能告诉我为什么会发生这种情况吗?是GC在某种程度上妨碍了我吗

    测试在调试器外部的发布版本中运行。其他人是否可以复制此行为


    编辑:修复了代码中的一些输入错误。

    您没有在
    realmount struct
    之前重建秒表,因此
    realmount struct
    的后续运行包括之前的
    Decimal
    测试的时间。

    我不能肯定,但只要看一眼,
    IArithmetic d1=(realmounterstruct)1.25m;
    将其分配给类型为
    IArithmetic
    的本地时会导致装箱,这可能会影响性能。请尝试完全删除结构上的接口。@vcsjones但为什么第一次运行与外部循环的其他两次之间有差异?很难说。您发布的代码无法编译。@vcs琼斯:是的,很抱歉有一些打字错误。代码现在应该可以编译了。哈哈,我讨厌我自己。@在这两者之间,容易出现的错误是最难看到的。:)