자바 메소드 호출 비용
나는 초보자이고 코드를 반복하는 것이 나쁘다는 것을 항상 읽었습니다. 그러나 그렇게하지 않으려면 일반적으로 추가 메서드 호출이 필요합니다. 다음 수업이 있다고 가정 해 봅시다.
public class BinarySearchTree<E extends Comparable<E>>{
private BinaryTree<E> root;
private final BinaryTree<E> EMPTY = new BinaryTree<E>();
private int count;
private Comparator<E> ordering;
public BinarySearchTree(Comparator<E> order){
ordering = order;
clear();
}
public void clear(){
root = EMPTY;
count = 0;
}
}
실제 메서드를 호출하는 대신 clear () 메서드의 두 줄을 생성자에 복사하여 붙여 넣는 것이 더 최적일까요? 그렇다면 얼마나 많은 차이가 있습니까? 생성자가 각각 인스턴스 변수를 값으로 설정하여 10 개의 메서드 호출을 수행하면 어떻게됩니까? 최고의 프로그래밍 방법은 무엇입니까?
실제 메서드를 호출하는 대신 clear () 메서드의 두 줄을 생성자에 복사하여 붙여 넣는 것이 더 최적일까요?
컴파일러는 이러한 최적화를 수행 할 수 있습니다. JVM도 마찬가지입니다. 컴파일러 작성자 및 JVM 작성자가 사용하는 용어는 "인라인 확장"입니다.
그렇다면 얼마나 많은 차이가 있습니까?
그것을 측정하십시오. 종종 차이가 없다는 것을 알게 될 것입니다. 그리고 이것이 성능 핫스팟이라고 생각한다면 잘못된 위치를 찾고있는 것입니다. 그것이 당신이 그것을 측정해야하는 이유입니다.
생성자가 각각 인스턴스 변수를 값으로 설정하여 10 개의 메서드 호출을 수행하면 어떻게됩니까?
다시 말하지만 이는 생성 된 바이트 코드와 Java Virtual Machine에서 수행하는 런타임 최적화에 따라 다릅니다. 컴파일러 / JVM이 메서드 호출을 인라인 할 수있는 경우 런타임에 새 스택 프레임을 만드는 오버 헤드를 방지하기 위해 최적화를 수행합니다.
최고의 프로그래밍 방법은 무엇입니까?
조기 최적화 방지. 가장 좋은 방법은 읽기 쉽고 잘 설계된 코드를 작성한 다음 애플리케이션의 성능 핫스팟에 맞게 최적화하는 것입니다.
최적화에 대해 다른 사람들이 말한 것은 절대적으로 사실입니다.
성능 관점 에서 메서드를 인라인 할 이유가 없습니다 . 성능 문제인 경우 JVM의 JIT가이를 인라인합니다. 자바에서 메서드 호출은 무료에 가깝기 때문에 생각할 가치가 없습니다.
즉, 여기에는 다른 문제가 있습니다. 즉, 그것은 이다 덮어 쓸 방법 (즉, 아닌 하나의 전화 나쁜 프로그래밍 연습 final
, static
또는 private
생성자에서이). (Effective Java, 2nd Ed., p. 89 항목의 "상속을위한 설계 및 문서 또는 금지"항목)
누군가 다음 과 같은 코드로 모든 공용 메서드를 재정의하는 BinarySearchTree
called 하위 클래스를 추가하면 어떻게 되나요?LoggingBinarySearchTree
public void clear(){
this.callLog.addCall("clear");
super.clear();
}
그러면 LoggingBinarySearchTree
결코 건설 할 수 없습니다! 문제는이 this.callLog
될 것입니다 null
때 BinarySearchTree
생성자가 실행되지만 clear
불려 가도록는 오버라이드 (override)이며, 당신이를 얻을 수 있습니다 NullPointerException
.
여기서 Java와 C ++는 다릅니다. C ++에서 virtual
메서드 를 호출하는 슈퍼 클래스 생성자는 결국 재정의 된 것이 아니라 슈퍼 클래스에 정의 된 생성자를 호출합니다 . 두 언어를 전환하는 사람들은 때때로 이것을 잊어 버립니다.
이를 감안할 때 생성자에서 호출 될 때clear
메서드 를 인라인하는 것이 귀하의 경우 더 깨끗하다고 생각 하지만 일반적으로 Java에서는 원하는 모든 메서드 호출을 수행해야합니다.
나는 그것을 그대로 두겠다. clear()
논리 를 변경하면 어떨까요? 두 줄의 코드를 복사 한 모든 위치를 찾는 것은 비현실적입니다.
가장 좋은 방법은 두 번 측정하고 한 번 자르는 것입니다.
시간 최적화를 낭비한 후에는 다시는 되 찾을 수 없습니다! (따라서 먼저 측정하고 최적화 할 가치가 있는지 자문 해보십시오. 실제 시간을 얼마나 절약 할 수 있습니까?)
이 경우 Java VM은 이미 사용자가 말하는 최적화를 수행하고있을 것입니다.
Generally speaking (and as a beginner this means always!) you should never make micro-optimisations like the one you're considering. Always favour readability of code over things like this.
Why? Because the compiler / hotspot will make these sorts of optimisations for you on the fly, and many, many more. If anything, when you try and make optimisations along these sorts of lines (though not in this case) you'll probably make things slower. Hotspot understands common programming idioms, if you try and do that optimisation yourself it probably won't understand what you're trying to do so it won't be able to optimise it.
There's also a much greater maintenance cost. If you start repeating code then it's going to be much more effort to maintain, which will probably be a lot more hassle than you might think!
As an aside, you may get to some points in your coding life where you do need to make low level optimisations - but if you hit those points, you'll definitely, definitely know when the time comes. And if you don't, you can always go back and optimise later if you need to.
The cost of a method call is the creation (and disposal) of a stack frame and some extra byte code expressions if you need to pass values to the method.
The pattern that I follow, is whether or not this method in question would satisfy one of the following:
- Would it be helpful to have this method available outside this class?
- Would it be helpful to have this method available in other methods?
- Would it be frustrating to rewrite this every time i needed it?
- Could the versatility of the method be increased with the use of a few parameters?
If any of the above are true, it should be wrapped up in it's own method.
Keep the clear()
method when it helps readability. Having unmaintainable code is more expensive.
Optimizing compilers usually do a pretty good job of removing the redundancy from these "extra" operations; in many instances, the difference between "optimized" code and code simply written the way you want, and run through an optimizing compiler is none; that is to say, the optimizing compiler usually does just as good a job as you'd do, and it does it without causing any degradation of the source code. In fact, many times, "hand-optimized" code ends up being LESS efficient, because the compiler considers many things when doing the optimization. Leave your code in a readable format, and don't worry about optimization until a later time.
"Premature optimization is the root of all evil." - Donald Knuth
I wouldn't worry about method call as much but the logic of the method. If it was critical systems, and the system needed to "be fast" then, I would look at optimising codes that takes long to execute.
Given the memory of modern computers this is very inexpensive. Its always better to break your code up into methods so someone can quickly read whats going on. It will also help with narrowing down errors in the code if the error is restricted to a single method with a body of a few lines.
As others have said, the cost of the method call is trivial-to-nada, as the compiler will optimize it for you.
That said, there are dangers in making method calls to instance methods from a constructor. You run the risk of later updating the instance method so that it may try to use an instance variable that has not been initiated yet by the constructor. That is, you don't necessarily want to separate out the construction activities from the constructor.
Another question--your clear() method sets the root to EMPTY, which is initialized when the object is created. If you then add nodes to EMPTY, and then call clear(), you won't be resetting the root node. Is this the behavior you want?
참고URL : https://stackoverflow.com/questions/6495030/java-how-expensive-is-a-method-call
'code' 카테고리의 다른 글
브라우저는 JSP로 전달되는 서블릿을 호출 할 때 CSS, 이미지 및 링크와 같은 관련 리소스에 액세스하거나 찾을 수 없습니다. (0) | 2020.10.17 |
---|---|
MySQLdb를 사용하여 커서를 닫는 경우 (0) | 2020.10.17 |
JavaScript-문자열 일치에 변수 사용 (0) | 2020.10.16 |
Android의 16 진수 색상은 8 자리 숫자입니다. (0) | 2020.10.16 |
특정 속성에 대한 최대 값을 가진 Ruby 배열의 요소 찾기 (0) | 2020.10.16 |