대부분의 개발자는 성능 최적화가 복잡하고 많은 경험과 지식이 필요하다고 당연한 것으로 여겨집니다. 글쎄, 이것이 완전히 잘못되었다고 말할 수는 없습니다. 최적의 성능을 위해 애플리케이션을 최적화하는 것은 쉬운 일이 아닙니다. 그러나 이것이이 지식이 없다면 아무것도 할 수 없다는 것을 의미하지는 않습니다. 다음은 잘 수행하기 쉬운 11 가지 팁과 모범 사례를 통해 잘 실적이 좋은 응용 프로그램을 만들 수 있습니다.
대부분의 제안은 Java를위한 것입니다. 그러나 언어 독립적이며 모든 응용 프로그램 및 프로그래밍 언어에 적용될 수있는 몇 가지 제안이 있습니다. Java를위한 성능 튜닝 기술을 논의하기 전에 일반적인 팁을 살펴 보겠습니다.
1. 필요하다는 것을 알 때까지 최적화하지 마십시오
이것은 아마도 가장 중요한 성능 튜닝 팁 중 하나 일 것입니다. 일반적인 모범 사례를 따르고 사용 사례를 효율적으로 구현해야합니다. 그러나 이것이 필요한 것을 입증하기 전에 표준 라이브러리를 교체하거나 복잡한 최적화를 구축해야한다는 의미는 아닙니다.
대부분의 경우 조기 최적화는 많은 시간이 걸릴뿐만 아니라 코드를 읽고 유지하기가 어렵습니다. 더 나쁜 것은, 이러한 최적화는 일반적으로 어떤 혜택도 가져 오지 않습니다. 최적화에 많은 시간을 소비하는 것은 응용 프로그램의 비정상적인 부분이기 때문입니다.
그렇다면 무언가를 최적화해야한다는 것을 어떻게 증명합니까?
먼저, 예를 들어 모든 API 호출에 대한 최대 응답 시간을 지정하거나 특정 시간 범위에서 가져올 레코드 수를 지정하는 등 애플리케이션 코드가 얼마나 빨리 응용 프로그램 코드인지 정의해야합니다. 이 작업을 마치면 응용 프로그램의 어느 부분이 너무 느리게 개선하기에는 측정 할 수 있습니다. 그런 다음 두 번째 트릭을 살펴 보겠습니다.
2. 분석기를 사용하여 실제 병목 현상을 찾으십시오
첫 번째 제안을 따르고 응용 프로그램의 일부가 개선이 필요하다고 판단한 후 어디에서 시작해야합니까?
두 가지 방법으로 문제를 해결할 수 있습니다.
코드를 확인하고 의심스러워 보이거나 문제가 있다고 생각되는 부분부터 시작하십시오.
또는 분석기를 사용하고 코드의 각 부분의 동작 및 성능에 대한 자세한 정보를 얻으십시오.
바라건대 왜 두 번째 방법을 따라야하는지 설명 할 필요가 없습니다.
파서 기반 접근 방식을 사용하면 코드의 성능 영향을 더 잘 이해하고 가장 중요한 부분에 집중할 수 있습니다. 파서를 사용했다면 코드의 어떤 부분에 성능 문제가 있는지 알아내는 것이 얼마나 놀랐는지 기억해야합니다. 솔직히 말해서, 나의 첫 번째 추측은 나를 두 번 이상 잘못된 방향으로 이끌었습니다.
3. 전체 애플리케이션에 대한 성능 테스트 스위트 생성
이것은 생산에 성능 향상을 배치 한 후 종종 발생하는 예상치 못한 많은 문제를 피하는 데 도움이되는 또 다른 보편적 인 팁입니다. 항상 전체 애플리케이션을 테스트하고 성능 향상 전후에 실행하는 성능 테스트 제품군을 정의해야합니다.
이러한 추가 테스트 실행은 변경된 기능 및 성능 부작용을 식별하고 좋은 업데이트보다 해를 끼치 지 않도록하는 데 도움이됩니다. 데이터베이스 또는 캐시와 같은 응용 프로그램의 여러 다른 부분에서 사용하는 구성 요소에서 작업하는 경우 특히 중요합니다.
4. 먼저 가장 큰 병목 현상을 처리합니다
테스트 스위트를 만들고 분석기를 사용하여 응용 프로그램을 분석 한 후 성능을 향상시키기 위해 해결해야 할 다양한 문제를 나열 할 수 있습니다. 이것은 훌륭하지만 여전히 시작 해야하는 질문에 답하지 않습니다. 빠른 작용 솔루션에 집중하거나 가장 중요한 질문으로 시작할 수 있습니다.
첫 번째 결과를 빠르게 보여줄 수 있기 때문에 빠른 행동 체계는 처음에는 매력적 일 수 있습니다. 그러나 때로는 다른 팀원이나 경영진에게 성과 분석이 그만한 가치가 있다고 확신해야 할 수도 있습니다. 현재 영향이 없기 때문입니다.
그러나 전반적으로 가장 중요한 성능 문제를 먼저 다루는 것이 좋습니다. 이를 통해 성능 향상을 제공 할 수 있으며 성능 요구 사항을 충족하기 위해 이러한 문제 중 일부를 더 이상 해결할 필요가 없습니다.
일반적인 성능 튜닝 팁은 여기서 끝납니다. Java 특정 팁을 자세히 살펴 보겠습니다.
5. StringBuilder를 사용하여 문자열을 프로그래밍 방식으로 연결하십시오
자바에서 문자열을 연결하는 다양한 옵션이 있습니다. 예를 들어 StringBuffer 또는 StringBuilder뿐만 아니라 Simple + 또는 + =를 사용할 수 있습니다.
그렇다면 어떤 방법을 선택해야합니까?
답은 문자열을 연결하는 코드에 따라 다릅니다. 예를 들어 For Loop에서 프로그래밍 방식으로 문자열에 새 컨텐츠를 추가하는 경우 StringBuilder를 사용해야합니다. 사용하기 쉽고 StringBuffer보다 더 나은 성능을 제공합니다. 그러나 StringBuffer와 비교할 때 StringBuilder는 스레드 안전이 아니며 모든 사용 사례에 적합하지 않을 수 있습니다.
새 StringBuilder를 인스턴스화하고 Append 메소드를 호출하여 문자열에 새 부분을 추가하면됩니다. 모든 부품을 추가 한 후에는 ToString () 메소드를 호출하여 연결된 문자열을 검색 할 수 있습니다.
다음 코드 스 니펫은 간단한 예를 보여줍니다. 각 반복하는 동안이 루프는 I를 문자열로 변환하여 공간과 함께 StringBuilder SB에 추가합니다. 따라서 결국이 코드는 로그 파일에 "Test0 1 2 3 4 5 6 7 8 9"를 작성합니다.
StringBuilder sb = new StringBuilder ( "이것은 테스트입니다"); for (int i = 0; i <10; i ++) {sb.append (i); sb.append ( "");} log.info (sb.tostring ());코드 스 니펫에서 볼 수 있듯이 문자열의 첫 번째 요소를 생성자에게 제공 할 수 있습니다. 이렇게하면 제공된 문자열과 16 개의 추가 문자 용량이 포함 된 새 StringBuilder가 생성됩니다. StringBuilder에 더 많은 문자를 추가하면 JVM은 StringBuilder의 크기를 동적으로 증가시킵니다.
문자열에 포함 된 문자 수를 이미 알고 있다면 해당 숫자를 다른 생성자에게 제공하여 정의 된 용량으로 StringBuilder를 인스턴스화 할 수 있습니다. 이것은 용량의 동적 확장이 필요하지 않기 때문에 효율성을 더욱 향상시킵니다.
6. +를 사용하여 문자열을 문자열을 연결합니다.
Java에서 첫 번째 애플리케이션을 구현할 때 누군가는 +를 사용하여 String에 연결해서는 안된다고 말했을 수도 있습니다. 애플리케이션 논리에서 문자열을 연결하는 경우, 이것은 정확합니다. 문자열은 불변이며 각 문자열의 연결 결과는 새 문자열 객체에 저장됩니다. 이렇게하면 추가 메모리가 필요하며 특히 루프 내에서 여러 줄을 연결하는 경우 응용 프로그램 속도가 느려집니다.
이 경우 팁 5를 따라 StringBuilder를 사용해야합니다.
그러나 코드의 가독성을 향상시키기 위해 문자열을 여러 줄로 분할하면 다릅니다.
쿼리 Q = EM.Createquery ( "SELECT A.ID, A.FirstName, A.LastName"
+“저자 A”
+“여기서 a.id = : id”);
이 경우 간단한 +를 사용하여 문자열을 연결해야합니다. Java 컴파일러는이를 최적화하고 컴파일 시간에 연결을 수행합니다. 따라서 런타임에 코드는 1 개의 문자열 만 사용하며 연결이 필요하지 않습니다.
7. 가능한 한 프리미티브를 사용하십시오
오버 헤드를 피하고 응용 프로그램 성능을 향상시키는 또 다른 쉬운 방법은 래퍼 클래스 대신 기본 유형을 사용하는 것입니다. 따라서 정수 대신 int를 사용하는 것이 가장 좋습니다. 이를 통해 JVM은 힙이 아닌 스택에 값을 저장하여 메모리 소비를 줄이고보다 효율적인 처리를 할 수 있습니다.
8. Biginteger와 Bigdecimal을 피하십시오
우리는 데이터 유형에 대해 논의하기 때문에 BigInteger와 Bigdecimal을 간단히 살펴 보겠습니다. 특히, 후자는 정확도로 인기가 있습니다. 그러나 가격이 있습니다.
Biginteger와 Bigdecimal은 단순한 길거나 두 배보다 더 많은 메모리가 필요하며 모든 계산을 크게 느리게합니다. 따라서 정밀도가 추가로 필요하거나 숫자가 장거리를 초과하면 두 번 생각하기 전에 두 번 생각하는 것이 가장 좋습니다. 이것은 아마도 수학 알고리즘을 구현할 때 성능 문제를 해결하기 위해 변경해야 할 유일한 방법 일 것입니다.
9. 먼저 현재 로그 레벨을 확인하십시오
이 제안은 분명해야하지만 불행히도 많은 프로그래머는 대부분 코드를 작성할 때이를 무시합니다. 디버그 메시지를 만들기 전에 항상 현재 로그 레벨을 확인해야합니다. 그렇지 않으면 나중에 무시할 로그 메시지 문자열을 만들 수 있습니다.
다음은 두 가지 부정적인 예입니다.
// thislog.debug ( "user [" + username + "]는 [" + i + "]" "); // thislog.debug (String.format ("user [%s] with [%d] ", username, i);두 경우 모두 로그 프레임 워크가 로그 메시지를 사용하는지 여부를 알지 못하고 로그 메시지를 작성하는 데 필요한 모든 단계를 수행합니다. 따라서 디버그 메시지를 작성하기 전에 현재 로그 레벨을 확인하는 것이 가장 좋습니다.
// do thisif (log.isdebugenabled ()) {log.debug ( "user [" + username + "] method x가 [" + i + "]");}이라고 불렀습니다.10. Apache Commons StringUtils.replace를 사용하여 String.replace를 사용하십시오
일반적으로 String.replace 메소드는 잘 작동하며 특히 Java 9를 사용할 때 매우 효율적입니다. 그러나 응용 프로그램에 많은 교체 작업이 필요하고 최신 Java 버전으로 업데이트되지 않으면 더 빠르고 효율적인 대안을 찾아야합니다.
Apache Commons Lang의 StringUtils.replace 방법에 대한 대안이 있습니다. Lukas Eder가 최근 블로그 게시물에 설명 된 것처럼 StringUtils.replace 메소드는 Java 8의 String.replace 메소드보다 훨씬 우수합니다.
그리고 약간만 변경하면됩니다. 즉, Apache Commons Lang 프로젝트의 Maven 종속성을 Application Pom.xml에 추가하고 모든 통화를 String.replace 메소드로 교체하십시오.
// thistest.replace ( "테스트", "간단한 테스트"); // thisstringUtils.replace (테스트, "테스트", "간단한 테스트")를 대체합니다.
11. 데이터베이스 연결과 같은 비싼 리소스를 캐시합니다
캐싱은 비싸거나 일반적인 코드 스 니펫의 반복적 인 실행을 피하기위한 인기있는 솔루션입니다. 일반적인 아이디어는 간단합니다. 새로운 리소스를 반복적으로 만드는 것보다 이러한 리소스를 재사용하는 것은 저렴합니다.
일반적인 예는 캐시 풀의 데이터베이스 연결입니다. 새로운 연결은 생성하는 데 시간이 걸리며 기존 연결을 재사용하면 피할 수 있습니다.
Java 언어 자체에서 다른 예제를 찾을 수도 있습니다. 예를 들어, 정수 클래스의 가치는 -128에서 127 사이의 값을 캐시합니다. 새 정수를 만드는 데 너무 비싸지 않지만 자주 사용되기 때문에 가장 일반적으로 사용되는 값을 캐싱하면 성능 이점을 제공 할 수 있습니다.
그러나 캐싱을 고려할 때 캐시 구현도 오버 헤드가 발생할 수 있습니다. 재사용 가능한 리소스를 저장하려면 추가 메모리를 사용해야하므로 자원에 액세스 할 수 있도록 캐시를 관리하고 오래된 리소스를 삭제해야 할 수도 있습니다.
따라서 자원을 캐싱하기 전에 캐시를 구현하는 것이 그만한 가치가 있는지 확인하십시오. 즉, 충분히 사용해야합니다.
요약
보시다시피, 때로는 응용 프로그램의 성능을 향상시키는 데 많은 노력이 필요하지 않습니다. 이 기사의 대부분의 제안은 코드에 적용하기 위해 약간의 노력이 필요합니다.
그러나 가장 중요한 것은 어떤 프로그래밍 언어와 관련이없는 트릭입니다.
필요한 것을 알기 전에 분석기를 사용하여 실제 병목 현상을 찾기 위해 최적화하지 마십시오. 먼저 가장 큰 병목 현상을 처리하십시오.
위의 것은이 기사에서 매우 간단하고 이해하기 쉬운 Java 성능 튜닝 기술에 대한 모든 내용입니다. 모든 사람에게 도움이되기를 바랍니다. 관심있는 친구들은이 사이트를 계속 참조 할 수 있습니다.
Java는 WeChat Public Platform Wechat Moments의 기능 공유를위한 자세한 코드를 구현합니다.
Java 원시 직렬화 및 Kryo 직렬화의 성능 사례의 비교 분석
Java 프로그래밍 서브 클래스가 상위 클래스의 정적 메소드를 다시 작성할 수 있는지 여부에 대한 탐색
단점이 있으면 메시지를 남겨 두십시오. 이 사이트를 지원해 주신 친구들에게 감사드립니다!