IT TIP

TypeCasting의 성능

itqueen 2020. 12. 4. 21:41
반응형

TypeCasting의 성능


사이에 측정 가능한 성능 차이가 있습니까?

((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(','))

이것이 성능 낭비인지 궁금합니다.


다른 작업이 거의없이 수십억 번 수행되면 측정 가능할 수 있습니다. CLR이 캐스트가 작동했다는 사실을 효과적으로 캐시할지 여부를 알 수 없으므로 다시 수행 할 필요가 없습니다. 지금 수행하지 않으면 이후 릴리스에서 수행 할 수 있습니다. 64 비트 JIT에서는 가능하지만 32 비트 버전에서는 불가능하거나 그 반대의 경우도 마찬가지입니다. 아이디어를 얻을 수 있습니다. 그래도 일반 코드에서 중요한 차이를 만들지 의심됩니다.

개인적으로 저는 두 번째 형식 가독성 이 더 좋으며 그게 훨씬 더 중요합니다.


@dkson : 두 가지 방법을 모두 테스트했습니다. 내 컴퓨터에서 찾은 내용은 다음과 같습니다.

성능면 에서 거의 동일 합니다. 사실, 두 번째 방법은 약간 느립니다. 그 이유는 (내 생각에) 추가 변수와 초기 캐스트 비용 때문입니다. 물론 충분한 캐스트를 사용하면 성능 비용을 되 찾을 수 있습니다. 캐스트를 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

예외가 없더라도 isinst가 castclass보다 빠를 것이라고 생각했습니다. 그러나 내 자신의 벤치 마크를 만든 후 isinst 가 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   

그래서, Skeet 씨, 저는 정정되었습니다.

환경:

Windows Vista
최대 코어 속도 3.2Ghz
.NET Framework v2.0.50727

다음은 내가 만들고 실행 한 벤치 마크의 전체 소스입니다. ( 여기에서 사용할 수있는 Jon Skeets Microbenchmarking 프레임 워크를 사용 합니다. )

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();
        }
    }
}

isinstcastclass방법에 대한 결과 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 
}

참고 URL : https://stackoverflow.com/questions/1165602/performance-of-typecasting

반응형