Java에서는 Getter를 통한 필드를 참조하는 것과 변수를 통한 성능 차이가 있습니까?

StackOverflow https://stackoverflow.com/questions/1195849

문제

행동 사이에 차이가 있습니까?

Field field = something.getSomethingElse().getField();
if (field == 0) {
//do something    
}
somelist.add(field);

~ 대

if (something.getSomethingElse().getField() == 0) {
//do something    
}
somelist.add(something.getSomethingElse().getField());

Getters를 통한 필드에 대한 참조는 성능 페널티를 받거나 할당 된 변수를 참조하는 것과 동일합니까? 나는 변수가 메모리 공간에 대한 참조 일 뿐이라는 것을 이해하므로 Getter는 그 메모리 공간을 얻는 또 다른 방법이어야합니다.

이것은 실용적인 문제보다 오히려 학문적 질문입니다.

도움이 되었습니까?

해결책

그것을 가정합니다 getSomethingElse() 정의됩니다

public SomethingElse getSomethingElse() {
    return this.somethingElse;
}

성능 차이는 최소화됩니다 (또는 상해가 발생하면 0). 그러나 실제 생활에서는 항상 그런 사실을 확신 할 수는 없습니다. 장면 뒤에서 처리가 발생할 수 있습니다 (반드시 객체 자체가 아니라 AOP 프록시를 통해). 따라서 반복 액세스를위한 변수에 결과를 저장하는 것이 좋습니다.

다른 팁

무시할만한 손해입니다. 너무 많이 걱정하지 마십시오. 그렇지 않으면 조기 최적화에 먹이를 줄 것입니다. 응용 프로그램이 느리면 이것이 이유가 아닙니다.

Getters를 통해 변수에 액세스하면 메소드 호출이 발생한다는 것은 차이가 있습니다. JVM은 아마도 어떤 상황에서는 메소드 호출을 최적화 할 수있을 것입니다. ~이다 메소드 호출.

즉, 코드의 가장 큰 병목 현상 또는 성능 문제가 액세서 방법의 오버 헤드라면 걱정할 것이 많지 않다고 말합니다.

성능 페널티가 있습니다 (너무 작을 수 있습니다). 그러나 JVM은이 문제와 성능을 향상시키기위한 모든 전화를 능가 할 수 있습니다.

두 번째 방식으로 떠나면 더 나을 것입니다.

Sun의 핫스팟과 같은 JVM이 좋은 경우가 아닙니다. 그것은 인라인과 컴파일됩니다 (기본 코드).

Getters를 사용하는 것은 일반적으로 방어 측정 및 일반 정보 숨기기로서 매우 좋은 관행입니다.

안드로이드 응용 프로그램을 작성하는 데 Java를 사용하는 경우 다음과 같습니다.http://developer.android.com/training/articles/perf-tips.html#getterssetters

C ++와 같은 모국어에서는 필드에 직접 액세스하는 대신 getters (i = getCount ())를 사용하는 것이 일반적입니다 (i = mcount). 이것은 C ++에게 훌륭한 습관이며 C# 및 Java와 같은 다른 객체 지향 언어로 종종 실시됩니다. 컴파일러는 일반적으로 액세스를 인화 할 수 있기 때문입니다. 필드 액세스를 제한하거나 디버그 해야하는 경우 언제든지 코드를 추가 할 수 있습니다.

그러나 이것은 Android에서 나쁜 생각입니다. 가상 메소드 호출은 인스턴스 필드 조회보다 훨씬 비싸다. 일반적인 객체 지향 프로그래밍 관행을 따르고 공개 인터페이스에 게터와 세터를 갖는 것이 합리적이지만 클래스 내에서는 항상 필드에 직접 액세스해야합니다.

JIT가 없으면 직접 필드 액세스는 사소한 게터를 부르는 것보다 약 3 배 빠릅니다. JIT (직접 필드 액세스가 로컬에 액세스하는 것만 큼 저렴한 곳)를 사용하면 직접 필드 액세스는 사소한 게터를 부르는 것보다 약 7 배 빠릅니다.

Proguard를 사용하는 경우 Proguard가 액세서를 인라인 할 수 있기 때문에 두 가지 세계를 최대한 활용할 수 있습니다.

이 방법이 처리가없는 간단한 getter라면 문제가되지 않습니다. 광범위한 계산이 포함된다면, 속성은 어쨌든 원하는 것을 수행하지 않습니다.

차이에 대해 걱정하는 유일한 시간은 엄청난 수의 반복 (수천 개)이있는 단단한 루프입니다. 그럼에도 불구하고 추가 처리 (예 : 로깅)를 사용하여 측면을 사용하는 경우에만 문제가 될 수 있습니다. 여기에는 수천 개의 추가 객체 (예 : 교착 상태 및 매개 변수자가 항폭) 및 결과 GC 문제가 포함될 수 있습니다.

성능 차이에 대해 걱정하지 않을 것입니다. 당신은 그것에 대해 생각하지 않고 대신 현실적인 시나리오에서 코드를 프로파일 링하는 데 시간을 보내는 것이 좋습니다. 프로그램의 느린 부분이 자신이 생각하는 곳이 아니라는 것을 알게 될 것입니다.

이 게시물은 JVM 대신 CLI VM에 대해 이야기하지만 각각 비슷한 일을 할 수 있으므로 관련이 있다고 생각합니다.

나는이 특별한 문제를 내 JIT를 위해 특별한 방식으로 처리하고 있습니다. 여기의 설명은 개념적이며 코드는 성능 이유에 따라 약간 다른 방식으로이를 구현합니다. 어셈블리를로드하면 회원 필드를 단순히 반환하는 경우 메소드 디스크립터에 메모를합니다. 나중에 다른 방법을 지시 할 때 나는 모두 교체합니다. call 바이트 코드 에서이 방법에 대한 지침은 ldfld 기본 코드 생성기에 전달하기 전에 명령어. 이런 식으로, 나는 할 수있다 :

  1. JIT에서 시간을 절약하십시오 (ldfld Processor 시간이 JIT보다 적습니다 call).
  2. 인라인 속성에서도 기준선 컴파일러.
  3. 대체로 공개 속성/개인 필드 패턴을 사용하면 디버거가 분리 될 때 어떤 종류의 성능 페널티가 발생하지 않을 것이라고 보장합니다. (디버거가 첨부되면 액세서를 인화 할 수 없습니다.)

VM Technologies의 큰 이름이 이미 제품과 비슷한 것과 비슷한 것을 구현하고 있다는 것은 의심의 여지가 없습니다.

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