代码之家  ›  专栏  ›  技术社区  ›  sloth JohnnBlade

打字性能

  •  53
  • sloth JohnnBlade  · 技术社区  · 15 年前

    两者之间是否存在可测量的性能差异?

    ((TypeA) obj).method1();
    ((TypeA) obj).method2();
    ((TypeA) obj).method3();
    

    var A = (TypeA) obj;
    A.method1();
    A.method2();
    A.method3();
    

    什么时候用了很多次?

    我经常看到

    if (((TextBox)sender).Text.Contains('.') || ((TextBox)sender).Text.Contains(','))
    

    想知道这是不是在浪费性能。

    2 回复  |  直到 11 年前
        1
  •  51
  •   Jon Skeet    15 年前

    它可能是可测量的,如果它正在做数十亿次,而其他工作很少。我不知道clr是否会有效地缓存演员表工作的事实,所以它不需要再这样做-如果现在不这样做,它可能在以后的版本中这样做。它可以在64位的JIT中实现,但不能在32位的版本中实现,反之亦然——你明白了。不过,我怀疑它会对正常代码产生重大影响。

    我个人喜欢 可读性 更重要的是,第二种形式。

        2
  •  39
  •   Anatoliy Nikolaev    11 年前

    @我测试了两种方法。这是我在电脑上找到的东西:

    他们是关于 相同的 在表演中。实际上,我发现第二种方法稍慢一些。原因(我相信)是额外变量和初始铸造的成本。当然,如果你使用足够的石膏,你可能会得到性能成本回来。看起来你只有在节省20-30次演员后才能在表现上达到收支平衡。

    以下是最近两次测试运行的结果:

    TestMuliCast\_3x:      00:00:00.5970000   
    TestSingleCast\_3x:    00:00:00.6020000   
    TestMuliCast\_30x:     00:00:06.0930000   
    TestSingleCast\_30x:   00:00:06.0480000   
    
    TestMuliCast\_3x:      00:00:00.6120000   
    TestSingleCast\_3x:    00:00:00.6250000   
    TestMuliCast\_30x:     00:00:06.5490000   
    TestSingleCast\_30x:   00:00:06.4440000   
    

    我还测试了 castclass isinst . 根据我读到的:

    http://m3mia.blogspot.com/2007/11/comparing-isinst-to-castclass.html
    http://www.codeproject.com/KB/cs/csharpcasts.aspx
    http://discuss.joelonsoftware.com/default.asp?dotnet.12.635066.13

    我以为ISISINT会比CastClass更快,即使没有例外。然而,在创建了自己的基准之后,我发现 更慢的 比CastClass更重要。非常有趣。以下是我的结果:

    TestEmptyLoop:        00:00:00.0870000   
    TestDCast\_castclass:  00:00:00.2640000   
    TestDCast\_isinst:     00:00:00.3780000   
    
    TestEmptyLoop:        00:00:00.0870000   
    TestDCast\_castclass:  00:00:00.2600000   
    TestDCast\_isinst:     00:00:00.3750000   
    

    所以,斯基特先生,我接受纠正。

    环境:

    Windows Vista
    最大核心速度3.2GHz
    .NET Framework 2.0.50727版

    以下是我创建和运行的基准的完整来源: (利用jon skeets微标记框架 here )

    using System;   
    using System.Collections;
    
    public class CastingBenchmark   
    {
        static Int64 Iterations=100000000;
        static Int64 TestWork = 0;
    
        public static void Init(string[] args)
        {
            if (args.Length>0)
                Iterations = Int64.Parse(args[0]);
        }
    
        public static void Reset()
        {
            TestWork = 0;
        }
    
        internal class BaseType { public void TestBaseMethod() { TestWork++; } }
    
        internal class DerivedType : BaseType { 
            public void TestDerivedMethod() { TestWork++; }
            public void TestDerivedMethod2() { TestWork++; }
            public void TestDerivedMethod3() { TestWork++; } 
    }
    
    [Benchmark]
    public static void TestMuliCast_3x()
    {
        BaseType TestBaseType = new DerivedType();
    
        for (int x = 0; x < Iterations; x++)
        {
            ((DerivedType)TestBaseType).TestDerivedMethod();
            ((DerivedType)TestBaseType).TestDerivedMethod2();
            ((DerivedType)TestBaseType).TestDerivedMethod3();
        }
    }
    
    [Benchmark]
    public static void TestSingleCast_3x()
    {
        BaseType TestBaseType = new DerivedType();
    
        for (int x = 0; x < Iterations; x++)
        {
            DerivedType TestDerivedType = (DerivedType)TestBaseType;
            TestDerivedType.TestDerivedMethod();
            TestDerivedType.TestDerivedMethod2();
            TestDerivedType.TestDerivedMethod3();
        }
    }
    
    [Benchmark]
    public static void TestMuliCast_30x()
    {
        BaseType TestBaseType = new DerivedType();
    
        for (int x = 0; x < Iterations; x++)
        {
            //Simulate 3 x 10 method calls while casting
            for (int y = 0; y < 10; y++) {
    
                ((DerivedType)TestBaseType).TestDerivedMethod();
                ((DerivedType)TestBaseType).TestDerivedMethod2();
                ((DerivedType)TestBaseType).TestDerivedMethod3();
            }
        }
    }
    
    [Benchmark]
    public static void TestSingleCast_30x()
    {
        BaseType TestBaseType = new DerivedType();
    
        for (int x = 0; x < Iterations; x++)
        {
            DerivedType TestDerivedType = (DerivedType)TestBaseType;
    
            //Simulate 3 x 10 method calls on already-cast object
            for (int y = 0; y < 10; y++)
            {
                TestDerivedType.TestDerivedMethod();
                TestDerivedType.TestDerivedMethod2();
                TestDerivedType.TestDerivedMethod3();
            }
        }
    }
    
        [Benchmark]
        public static void TestEmptyLoop()
        {
            for (int x = 0; x < Iterations; x++)
            {
            }
        }
    
        [Benchmark]
        public static void TestDCast_castclass()
        {
            BaseType TestDerivedType = new DerivedType();
    
            for (int x = 0; x < Iterations; x++)
            {
                ((DerivedType)TestDerivedType).TestDerivedMethod();
            }    
        }
    
        [Benchmark]
        public static void TestDCast_isinst()
        {
            BaseType TestDerivedType = new DerivedType();
    
            for (int x = 0; x < Iterations; x++)
            {
                (TestDerivedType as DerivedType).TestDerivedMethod();
            }
        }
    }
    

    以及由此产生的IL 伊辛 铸钢类 方法:

    method public hidebysig static void TestDCast_isinst() cil managed
    {
        .custom instance void BenchmarkAttribute::.ctor()
        .maxstack 2
        .locals init (
            [0] class CastingBenchmark/BaseType TestDerivedType,
            [1] int32 x)
        L_0000: newobj instance void CastingBenchmark/DerivedType::.ctor()
        L_0005: stloc.0 
        L_0006: ldc.i4.0 
        L_0007: stloc.1 
        L_0008: br.s L_0019
        L_000a: ldloc.0 
        L_000b: isinst CastingBenchmark/DerivedType
        L_0010: callvirt instance void CastingBenchmark/DerivedType::TestDerivedMethod()
        L_0015: ldloc.1 
        L_0016: ldc.i4.1 
        L_0017: add 
        L_0018: stloc.1 
        L_0019: ldloc.1 
        L_001a: conv.i8 
        L_001b: ldsfld int64 CastingBenchmark::Iterations
        L_0020: blt.s L_000a
        L_0022: ret 
    }
    
    .method public hidebysig static void TestDCast_castclass() cil managed
    {
        .custom instance void BenchmarkAttribute::.ctor()
        .maxstack 2
        .locals init (
            [0] class CastingBenchmark/BaseType TestDerivedType,
            [1] int32 x)
        L_0000: newobj instance void CastingBenchmark/DerivedType::.ctor()
        L_0005: stloc.0 
        L_0006: ldc.i4.0 
        L_0007: stloc.1 
        L_0008: br.s L_0019
        L_000a: ldloc.0 
        L_000b: castclass CastingBenchmark/DerivedType
        L_0010: callvirt instance void CastingBenchmark/DerivedType::TestDerivedMethod()
        L_0015: ldloc.1 
        L_0016: ldc.i4.1 
        L_0017: add 
        L_0018: stloc.1 
        L_0019: ldloc.1 
        L_001a: conv.i8 
        L_001b: ldsfld int64 CastingBenchmark::Iterations
        L_0020: blt.s L_000a
        L_0022: ret 
    }