문제

하다 밖으로 매개 변수 씨# 내가 알아야 할 성능 영향이 있습니까? (예외와 같은)

내 말은, 방법을 갖는 것이 좋은 생각입니까? out 1 초에 몇 백만 번 실행되는 루프의 매개 변수?

못 생겼다는 걸 알아요. Int32.TryParse 그것들을 사용하고 있습니다 - 반환 a bool 어떤 검증이 성공했는지 알기 위해 out 성공한 경우 일부 추가 데이터를 포함하는 매개 변수.

도움이 되었습니까?

해결책

나는 당신이 out 매개 변수. 어떻게 든 발신자에게 정보를 다시 가져와야합니다. out 다른 방법 일뿐입니다. 당신은있을 수 있습니다 약간 페널티 메소드 내에서 아웃 매개 변수를 광범위하게 사용하는 경우 각 액세스에 대한 추가 리디렉션 수준을 의미 할 수 있습니다. 그러나 나는 그것이 중요 할 것으로 기대하지 않을 것입니다. 일반적으로 가장 읽기 쉬운 코드를 작성하십시오 성능이 이미 충분한 지 테스트하십시오 추가 최적화를 시도하기 전에.

편집 : 나머지는 효과적으로 제쳐두고 있습니다. 그것은 큰 값 유형과 관련하여 실제로 관련이 있으며, 보통 어쨌든 피해야합니다 :)

그래도 "모든 유형에 대한 반환 값> 32 비트는 어쨌든 기계 레벨에서 인수와 유사하거나 동일하게 처리됩니다"에 대한 Konrad의 주장에 동의하지 않습니다. 다음은 작은 테스트 앱입니다.

using System;
using System.Diagnostics;
using System.Runtime.CompilerServices;

struct BigStruct
{
    public Guid guid1, guid2, guid3, guid4;
    public decimal dec1, dec2, dec3, dec4;
}

class Test
{
    const int Iterations = 100000000;

    static void Main()
    {
        decimal total = 0m;
        // JIT first
        ReturnValue();
        BigStruct tmp;
        OutParameter(out tmp);

        Stopwatch sw = Stopwatch.StartNew();
        for (int i=0; i < Iterations; i++)
        {
            BigStruct bs = ReturnValue();
            total += bs.dec1;
        }
        sw.Stop();
        Console.WriteLine("Using return value: {0}",
                          sw.ElapsedMilliseconds);

        sw = Stopwatch.StartNew();
        for (int i=0; i < Iterations; i++)
        {
            BigStruct bs;
            OutParameter(out bs);
            total += bs.dec1;
        }
        Console.WriteLine("Using out parameter: {0}",
                          sw.ElapsedMilliseconds);
    }

    [MethodImpl(MethodImplOptions.NoInlining)]
    public static BigStruct ReturnValue()
    {
        return new BigStruct();
    }

    [MethodImpl(MethodImplOptions.NoInlining)]
    public static void OutParameter(out BigStruct x)
    {
        x = new BigStruct();
    }
}

결과:

Using return value: 11316
Using out parameter: 7461

기본적으로 Out 매개 변수를 사용하여 작은 메소드의 스택 프레임에 작성한 다음 메인 메소드의 스택 프레임에 다시 복사하는 대신 데이터를 최종 대상에 직접 작성합니다.

그래도 벤치 마크 앱을 비판하십시오. 뭔가 놓쳤을 수도 있습니다!

다른 팁

성능 문제가 아니라 일찍 일어난 것 - C# 4.0에서 차이로 사용할 수 없습니다..

개인적으로 나는 사용하는 경향이 있습니다 out 매개 변수 내에서 상당한 금액 사적인 코드 (즉, 클래스 내부, 별도의 유형을 사용하지 않고 여러 값을 반환하는 메소드) - 그러나 나는 공개 API에서 피하는 경향이 있습니다. bool Try{Something}(out result) 무늬.

성능 영향은 없습니다. out 기본적으로 기술적 인 관점에서 통과하는 오래된 인수와 동일합니다. 엄청난 양의 데이터가 복사된다는 것이 그럴듯하게 들릴 수 있지만 (예 : 큰 스트러크의 경우), 이것은 실제로 반환 값과 동일합니다.

실제로 모든 유형의 반환 값> 32 비트는 out 에 대한 논쟁 기계 수준 그래도.

마지막 진술은 value ==를 반환하는 것을 제안하지 않습니다. out .NET의 매개 변수. Jon의 벤치 마크는 이것이 사실이 아니라는 것을 보여줍니다. 사실, 동일하게 만들기 위해 리턴 값 최적화 명명 C ++ 컴파일러에 사용됩니다. 미래의 JIT 버전에서 큰 구조물의 성능을 향상시키기 위해 유사한 일이 잠재적으로 수행 될 수 있습니다 (그러나 큰 구조는 .NET에서는 매우 드물기 때문에 불필요한 최적화 일 수 있습니다).

하지만, (그리고 x86 어셈블리에 대한 나의 매우 제한된 지식으로) 함수 호출에서 객체를 반환하면 일반적으로 콜 사이트에 충분한 공간을 할당하여 스택의 주소를 밀고 반환 값을 복사하여 채우는 것이 수반됩니다. 이것은 기본적으로 동일합니다 out 대상 메모리 위치에 직접 액세스 할 수 있으므로 불필요한 임시 값 사본 만 생략합니다.

매개 변수를 피하는 주된 이유는 성능보다는 코드 가독성입니다.

가치 유형의 경우 어쨌든 실제 차이는 없으며 (항상 복사) 참조 유형의 경우 기본적으로 Ref를 통과하는 것과 동일합니다.

10 명 중 9 번은 Out 매개 변수를 사용하는 대신 자신만의 멍청한 레코드 클래스를 만드는 것이 좋습니다. 이는 나중에 코드로 돌아올 때 읽고 이해하는 것이 더 간단합니다.

아웃 매개 변수는 Ref. 그래서 포인터 만 스택에 통과했습니다.

값 유형이 크면 사본이 적지 만 각 변수 사용에 대해 포인터를 피해야합니다.

Out 매개 변수를 사용해도 성능이 손상되지 않습니다. Out 매개 변수는 기본적으로 참조 매개 변수이므로 발신자와 Callee는 모두 동일한 메모리를 가리 킵니다.

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top