[c#] 정적 메서드와 인스턴스 메서드의 성능

내 질문은 정적 메서드 대 인스턴스 메서드의 성능 특성 및 확장 성과 관련이 있습니다. 이 시나리오에서는 모든 클래스 정의가 단일 어셈블리에 있고 여러 개의 개별 포인터 형식이 필요하다고 가정합니다.

치다:

public sealed class InstanceClass
{
      public int DoOperation1(string input)
      {
          // Some operation.
      }

      public int DoOperation2(string input)
      {
          // Some operation.
      }

      // … more instance methods.
}

public static class StaticClass
{
      public static int DoOperation1(string input)
      {
          // Some operation.
      }

      public static int DoOperation2(string input)
      {
          // Some operation.
      }

      // … more static methods.
}

위의 클래스는 도우미 스타일 패턴을 나타냅니다.

인스턴스 클래스에서 인스턴스 메서드를 해결하는 데는 StaticClass와 달리 시간이 걸립니다.

내 질문은 다음과 같습니다.

  1. 상태를 유지하는 것이 문제가되지 않을 때 (필드 나 속성이 필요하지 않음) 항상 정적 클래스를 사용하는 것이 더 낫습니까?

  2. 이러한 정적 클래스 정의가 상당수있는 경우 (예 : 각각 여러 정적 메서드가있는 100 개) 동일한 수의 인스턴스 클래스 정의에 비해 실행 성능이나 메모리 소비에 부정적인 영향을 미칩니 까?

  3. 동일한 인스턴스 클래스 내의 다른 메서드가 호출 될 때 인스턴스 확인이 계속 발생합니까? 예를 들어 동일한 인스턴스 this.DoOperation2("abc")내에서 와 같이 [this] 키워드를 사용합니다 DoOperation1.



답변

이론적으로 정적 메서드는 추가 숨겨진 this매개 변수로 인해 인스턴스 메서드보다 약간 더 나은 성능을 발휘해야합니다 .

실제로 이것은 다양한 컴파일러 결정의 소음에 숨겨 질 정도로 거의 차이가 없습니다. (따라서 두 사람이 다른 사람보다 더 나은 결과를 “증명”할 수 있습니다.) 특히 this는 일반적으로 레지스터에서 전달되고 종종 해당 레지스터에서 시작되기 때문입니다.

이 마지막 요점은 이론적으로 객체를 매개 변수로 사용하고 동일한 객체의 인스턴스와 동등한 것보다 약간 덜 좋은 작업을 수행하는 정적 메서드를 예상해야 함을 의미합니다. 다시 말하지만, 차이가 너무 작아서 측정을 시도하면 다른 컴파일러 결정을 측정하게 될 것입니다. (특히 해당 참조가 레지스터에 있으면 전체 시간이 매우 높기 때문에).

실제 성능 차이는 자연스럽게 정적 인 작업을 수행하기 위해 메모리에 객체를 인위적으로 넣었는지, 아니면 자연스럽게 인스턴스가되어야하는 작업을 수행하기 위해 복잡한 방식으로 객체 전달 체인을 엉키고 있는지 여부에 달려 있습니다.

따라서 1 번입니다. 상태를 유지하는 것이 문제가되지 않을 때는 항상 정적 인 것이 낫습니다. 왜냐하면 그것이 정적 인 것이기 때문입니다 . 성능 문제는 아니지만 컴파일러 최적화를 훌륭하게 수행하는 전체적인 규칙이 있습니다. 누군가 이상하게 사용되는 경우보다 정상적인 사용으로 나타나는 경우를 최적화하려고 노력했을 가능성이 높습니다.

번호 2. 차이가 없습니다. 메타 데이터의 양, 실제 DLL 또는 EXE 파일에 얼마나 많은 코드가 있는지, 얼마나 많은 jitted 코드가 있는지에 따라 각 멤버에 대해 클래스 당 비용이 일정합니다. 이것은 인스턴스이든 정적이든 동일합니다.

항목 3 this도 마찬가지 this입니다. 그러나 참고 :

  1. this매개 변수는 특정 레지스터에 전달됩니다. 같은 클래스 내의 인스턴스 메서드를 호출 할 때, (이 은닉하고 어떤 이유로 사용되는 레지스터하지 않는 한) 그것은 가능성이 이미 레지스터에있을거야 따라서 어떠한 조치가를 설정이 필요하지 않습니다 this이 설정 될 필요가 무엇을 . 이것은 예를 들어 메서드에 대한 처음 두 매개 변수가 호출의 처음 두 매개 변수가되는 데 어느 정도 적용됩니다.

  2. thisnull이 아님 이 분명하므로 경우에 따라 호출을 최적화하는 데 사용할 수 있습니다.

  3. thisnull이 아님 이 분명하기 때문에 메서드 호출을 위조하기 위해 생성 된 코드가 어쨌든 필요한 일부 null 검사를 생략 할 수 있으므로 인라인 메서드 호출을 다시 더 효율적으로 만들 수 있습니다.

  4. 즉, null 검사는 저렴합니다!

인스턴스 메소드가 아닌 객체에 대해 작동하는 일반 정적 메소드가 http://joeduffyblog.com/2011/10/23/on-generics-and-some-of- 에서 논의 된 비용의 일부를 줄일 수 있다는 점은 주목할 가치가 있습니다. the-related-overheads / 는 주어진 정적이 주어진 유형에 대해 호출되지 않는 경우입니다. 그는 “제외로 확장 메서드가 일반적인 추상화를 더 많은 비용을 지불하도록 만드는 좋은 방법이라는 것이 밝혀졌습니다.”

그러나 이것은 메서드에서 사용하는 다른 유형의 인스턴스화에만 관련되며 다른 방법은 존재하지 않습니다. 따라서 실제로 많은 경우에 적용되지 않습니다 (다른 인스턴스 메서드는 해당 유형을 사용하고 다른 코드에서는 해당 유형을 사용했습니다).

요약:

  1. 대부분 인스턴스와 정적의 성능 비용은 무시할만한 수준입니다.
  2. 예를 들어 정적을 남용하거나 그 반대의 경우 일반적으로 어떤 비용이 발생합니다. 정적과 인스턴스 사이의 결정의 일부로 만들지 않으면 올바른 결과를 얻을 가능성이 더 큽니다.
  3. 드물게 다른 유형의 정적 제네릭 메서드가 인스턴스 제네릭 메서드보다 생성되는 유형이 더 적어 드물게 사용되는 작은 이점을 가질 수있는 경우 가 있습니다 (그리고 “드물게”는 호출 빈도가 아니라 응용 프로그램의 수명). 그 기사에서 그가 말한 내용을 알게되면 어쨌든 대부분의 static-vs-instance 결정과 100 % 무관하다는 것을 알게 될 것입니다. 편집 : 그리고 그것은 대부분 jitted 코드가 아닌 ngen에서만 그 비용이 있습니다.

편집 : null 검사가 얼마나 저렴한 지에 대한 메모 (위에서 주장했습니다). .NET의 대부분의 null 검사는 null을 전혀 확인하지 않고 작동 할 것이라는 가정하에 수행 할 작업을 계속하며 액세스 예외가 발생하면 NullReferenceException. 따라서 대부분 개념적으로 C # 코드가 인스턴스 멤버에 액세스하기 때문에 null 검사를 포함 할 때 성공할 경우 비용은 실제로 0입니다. 예외는 일부 인라인 호출 (인스턴스 멤버를 호출 한 것처럼 동작하기를 원하기 때문)이고 필드를 쳐서 동일한 동작을 트리거하므로 매우 저렴하고 어쨌든 여전히 종종 제외 될 수 있습니다. (예를 들어 메서드의 첫 번째 단계가 필드에 액세스하는 것과 관련된 경우).


답변

상태를 유지하는 것이 문제가되지 않을 때 (필드 나 속성이 필요하지 않음) 항상 정적 클래스를 사용하는 것이 더 낫습니까?

그렇습니다. 무언가 static를 선언 할 때 상태 비 저장 실행 의 의도 를 선언합니다 (필수는 아니지만 예상 할 수있는 의도).

이러한 정적 클래스가 상당히 많은 경우 (예를 들어 각각 여러 개의 정적 메서드가있는 100 개) 동일한 수의 인스턴스 클래스에 비해 실행 성능이나 메모리 소비에 부정적인 영향을 미칠까요?

그렇게 생각하지 마십시오. 정적 클래스가 정말로 스텔스 가 없다는 것을 확신하지 않는 한 , 메모리 할당을 엉망으로 만들고 메모리 누수가 발생하기 쉽습니다.

[this] 키워드를 사용하여 동일한 인스턴스 클래스 내에서 다른 메서드를 호출 할 때 인스턴스 확인이 계속 발생합니까?

점 에 대해서는 확실하지 않지만 (순전히 CLR의 구현 세부 사항입니다) 그렇다고 생각하십시오.


답변

정적 메소드는 더 빠르지 만 OOP가 적습니다. 디자인 패턴을 사용하는 경우 정적 메소드는 잘못된 코드 일 가능성이 높고, 정적없이 비즈니스 로직을 더 잘 작성하고, 파일 읽기, WebRequest 등과 같은 일반적인 기능은 정적으로 더 잘 인식합니다. 대답


답변