performance - tomcat8 튜닝




최후의 수단의 성능 최적화 전략 (20)

이미이 사이트에 많은 성능 관련 질문이 있지만 거의 모든 것이 매우 문제가 많고 좁은 편입니다. 그리고 조기 최적화를 피하기 위해 거의 모든 조언을 반복합니다.

가정 해 봅시다.

  • 코드가 이미 올바르게 작동하고 있습니다.
  • 선택한 알고리즘은 문제의 상황에 대해 이미 최적입니다.
  • 코드가 측정되었고 문제의 루틴이 격리되었습니다.
  • 최적화에 대한 모든 시도는 문제가 악화되지 않도록하기 위해 측정됩니다.

여기서 내가 바라는 것은 남은 일이 없을 때 중요한 알고리즘에서 마지막 몇 퍼센트까지 짜내는 전략과 트릭입니다.

이상적으로는 언어에 구별되지 않는 답변을 시도하고 적용 가능한 경우 제안 된 전략에 대해 아래쪽을 표시하십시오.

내 자신의 초기 제안과 함께 회신을 추가하고, 스택 오버플로 커뮤니티가 생각할 수있는 것이 무엇이든 기대합니다.


나는 이것이 이미 다른 방식으로 말한 것이라고 생각한다. 그러나 프로세서 집약적 인 알고리즘을 다룰 때는 가장 안쪽의 루프 안의 모든 것을 단순화시켜야합니다.

일부 사람들에게는 이것이 분명해 보일지 모르지만, 내가 작업하고있는 언어에 관계없이 집중하려고합니다. 예를 들어 중첩 루프를 다루는 경우 레벨을 따라 코드를 가져올 수있는 기회를 발견하면 코드의 속도를 크게 높일 수 있습니다. 또 다른 예로, 할 수있을 때마다 부동 소수점 변수 대신 정수로 작업하고 가능할 때마다 나누기 대신 곱셈을 사용하는 것과 같은 작은 것들을 생각해보십시오. 다시 말하지만, 이들은 당신의 가장 내적인 루프를 위해 고려해야 할 사항입니다.

때로는 내부 루프 내부의 정수에 대해 수학 연산을 수행 한 다음 나중에이를 처리 할 수있는 부동 소수점 변수로 스케일링하는 이점을 얻을 수 있습니다. 이것은 다른 섹션의 속도를 향상시키기 위해 한 섹션에서 속도를 희생시킨 예이지만 일부 경우에는 성과가 좋을 수도 있습니다.


나는이 곳에서 내 삶의 대부분을 보낸다. 광범위한 스트로크는 프로파일 러를 실행하여 기록하도록합니다.

  • 캐시 미스 . 데이터 캐시는 대부분의 프로그램에서 1 위를 차지합니다. 더 나은 지역을 만들기 위해 문제가되는 데이터 구조를 재구성하여 캐시 적중률을 향상시킵니다. 팩 구조와 수치 형을 낭비 바이트를 없애기 위해 (따라서 낭비되는 캐시 가져 오기); 데이터를 가능한 한 프리 페치하여 스톨을 줄입니다.
  • 적중 - 상점 . 포인터 앨리어싱에 대한 컴파일러 가정과 메모리를 통해 연결이 끊긴 레지스터 세트간에 데이터가 이동되는 경우 전체 CPU 파이프 라인이로드 연산에서 지워지도록 특정 병적 동작을 유발할 수 있습니다. 수레, 벡터 및 정수가 서로 캐스팅되고 제거되는 위치를 찾습니다. 컴파일러에서 앨리어싱을 약속하기 위해 __restrict 자유롭게 사용하십시오.
  • 마이크로 코드 작업 . 대부분의 프로세서는 파이프 라인 될 수없는 작업이 있지만 대신 ROM에 저장된 작은 서브 루틴을 실행합니다. PowerPC의 예는 정수 곱하기, 나누기 및 가변 시프트입니다. 문제는이 작업이 실행되는 동안 전체 파이프 라인이 중지 된 것입니다. 이러한 작업의 사용을 제거하거나 최소한 구성 파이프 라인 작업으로 분해하여 프로그램의 나머지 부분에서 superscalar 디스패치의 이점을 얻을 수 있도록하십시오.
  • 분기 예측 오류 . 이것들은 파이프 라인을 너무 비웠다. CPU가 분기 이후에 파이프를 다시 채우는 데 많은 시간을 소비하는 경우를 찾아 가능한 경우 분기 힌트를 사용하여보다 정확하게 예측하도록하십시오. 또는 더 나은 점은 가능하면 분기를 조건부 이동으로 바꾸는 것입니다. 특히 부동 소수점 연산 이후에는 파이프가 더 깊기 때문에 fcmp가 조건 플래그를 읽는 것이 실속을 초래할 수 있습니다.
  • 순차 부동 소수점 연산 . 이 SIMD를 만드십시오.

그리고 내가하고 싶은 또 하나의 일 :

  • 컴파일러를 출력하여 어셈블리 목록을 출력 하고 코드에서 핫스팟 함수에 대해 방출 된 내용을 살펴보십시오. "훌륭한 컴파일러가 자동으로 수행 할 수 있어야합니다"라는 영리한 최적화가 있습니까? 실제 컴파일러가이를 수행하지 않을 가능성이 있습니다. 나는 GCC가 정말 WTF 코드를 방출하는 것을 보았다.

마이크 Dunlavey의 대답을 좋아하지만, 실제로 그것은 실제로 예제를 지원하는 훌륭한 대답입니다, 나는 그것이 매우 간단하게 표현 될 수 있다고 생각합니다 :

시간이 가장 많이 걸리는 것을 먼저 찾아 내서 그 이유를 이해하십시오.

시간대 돼지의 식별 과정은 알고리즘을 어디에서 수정해야 하는지를 이해하는 데 도움이됩니다. 이것은 이미 완전히 최적화 된 문제를 찾을 수있는 유일하고 포괄적 인 언어 불가 지론적인 대답입니다. 또한 당신은 속도에 대한 탐구에서 독립적 인 아키텍처가되고 싶다고 가정합니다.

따라서 알고리즘을 최적화 할 수는 있지만 구현이 적절하지 않을 수 있습니다. 식별을 통해 알고리즘 또는 구현의 어느 부분인지 알 수 있습니다. 그래서 어느 것이 든 시간을 들여서 가장 많이 리뷰하는 후보자입니다. 그러나 당신이 마지막 몇 %를 쥐어 짜기를 원한다고 말했기 때문에 처음에는 자세히 조사하지 않은 부분을 조사하는 것이 좋습니다.

마지막으로 동일한 솔루션 또는 잠재적으로 다른 알고리즘을 구현하는 다양한 방법으로 성능 수치를 시험하고 오류를 분석하면 시간 낭비와 시간 절약을 파악하는 데 도움이되는 통찰력을 얻을 수 있습니다.

HPH, asoudmove.


많은 성능 문제에 데이터베이스 문제가 관련되어 있으므로 쿼리 및 저장 프로 시저를 튜닝 할 때 살펴볼 몇 가지 구체적인 사항을 알려 드리겠습니다.

대부분의 데이터베이스에서 커서를 피하십시오. 루핑도 피하십시오. 대부분의 경우 데이터 액세스는 레코드 기반 처리로 설정하지 말고 설정해야합니다. 여기에는 한 번에 1,000,000 개의 레코드를 삽입 할 때 단일 레코드 저장 프로 시저를 다시 사용하지 않는 것이 포함됩니다.

select *를 사용하지 마십시오. 실제로 필요한 필드 만 반환하십시오. 조인 필드가 반복되어 서버와 네트워크 모두에 불필요한로드가 발생하면 조인이있는 경우 특히 그렇습니다.

상관 하위 쿼리를 사용하지 마십시오. 가능한 경우 파생 테이블에 대한 조인을 포함하여 조인을 사용하십시오 (Microsoft SQL Server에서는이 사실을 알고 있지만 다른 백엔드를 사용할 때는 조언을 테스트합니다).

색인, 색인, 색인. 데이터베이스에 해당되는 경우 해당 통계를 업데이트하십시오.

쿼리를 sargable 만듭니다. 의미는 like 절의 첫 번째 문자 나 조인의 함수 또는 where 문의 왼쪽 부분에 와일드 카드를 사용하는 것과 같은 인덱스 사용을 불가능하게하는 것을 방지합니다.

올바른 데이터 유형을 사용하십시오. 날짜 필드에서 날짜 연산을하는 것이 문자열 데이터 유형을 날짜 데이터 유형으로 변환 한 다음 계산을 수행하는 것보다 빠릅니다.

어떤 종류의 고리도 트리거에 넣지 마십시오!

대부분의 데이터베이스에는 쿼리 실행 방법을 확인할 수있는 방법이 있습니다. Microsoft SQL Server에서이를 실행 계획이라고합니다. 먼저 문제 영역이 어디에 있는지 확인하십시오.

쿼리를 실행하는 빈도와 최적화해야 할 항목을 결정할 때 실행하는 데 걸리는 시간을 고려하십시오. 때로는 한 달에 한 번 실행되는 long_running 쿼리에서 시간을 지우는 것보다 하루에 수백만 회 실행되는 쿼리에 약간의 조정만으로 더 많은 성능을 얻을 수 있습니다.

프로파일 러 도구의 일종을 사용하여 실제로 데이터베이스와주고받는 것을 찾으십시오. 과거에 스토어드 프로 시저가 빠를 때로드 속도가 느린 이유를 알 수 없었던 한 번은 기억할 수 있습니다. 프로파일 링을 통해 웹 페이지가 한 번이 아닌 여러 번 쿼리를 요청하고 있음을 알게되었습니다.

프로파일 러는 또한 누구를 막고 있는지 찾아내는 데 도움을줍니다. 혼자 실행하는 동안 빠르게 실행되는 일부 쿼리는 다른 쿼리의 잠금으로 인해 매우 느려질 수 있습니다.


아마도 "Google 관점"을 고려해야합니다. 즉, 응용 프로그램이 크게 병렬화되고 동시화되는 방식을 결정해야합니다. 어떤 점에서 다른 시스템과 네트워크에 응용 프로그램을 배포해야하므로 필연적으로 거의 선형 적으로 확장 할 수 있습니다 당신이 그것에 던지는 하드웨어.

반면에 Google 직원은 전담 엔지니어 팀을 보유하여 gcc의 전체 프로그램 최적화 와 같이 사용중인 프로젝트, 도구 및 인프라의 일부 문제를 해결하는 데 많은 인력과 자원을 투입 한 것으로도 유명합니다 Google의 일반적인 사용 사례 시나리오를 준비하기 위해 gcc 내부를 해킹합니다.

마찬가지로 응용 프로그램을 프로파일 링한다는 것은 시스템 코드에서 중복 및 최적화 가능성을 식별하기 위해 더 이상 프로그램 코드뿐만 아니라 주변의 모든 시스템 및 인프라 (네트워크, 스위치, 서버, RAID 어레이)를 프로파일 링하는 것을 의미하지 않습니다.


오늘날 가장 중요한 제한 요소는 제한된 메모리 대역폭 입니다. 대역폭이 코어 사이에 공유되므로 멀티 코어는 이러한 상황을 더욱 악화시키고 있습니다. 또한 캐시를 구현하는 데 사용되는 제한된 칩 영역도 코어와 스레드로 나뉘어이 문제를 더욱 악화시킵니다. 마지막으로, 서로 다른 캐시를 일관성있게 유지하는 데 필요한 칩간 신호 전달은 증가 된 코어 수와 함께 증가합니다. 이것은 또한 페널티를 추가합니다.

이것이 귀하가 관리해야하는 효과입니다. 때로는 코드를 마이크로 관리해야하지만 때로는 신중하게 고려하고 리팩토링해야합니다.

많은 주석은 이미 캐시 친화적 인 코드를 언급합니다. 이것의 적어도 2 개의 명백한 풍미가있다 :

  • 메모리 가져 오기 대기 시간을 피하십시오.
  • 메모리 버스 압력 (대역폭)을 낮추십시오.

첫 번째 문제는 특히 데이터 액세스 패턴을보다 규칙적으로 만드는 것과 관련이 있으며 하드웨어 프리 페처가 효율적으로 작동하도록합니다. 데이터 객체를 메모리에 퍼뜨리는 동적 메모리 할당을 피하십시오. 링크 된 목록, 해시 및 트리 대신 선형 컨테이너를 사용하십시오.

두 번째 문제는 데이터 재사용 개선과 관련이 있습니다. 사용 가능한 캐시에 적합한 데이터 하위 집합에 대해 작업하도록 알고리즘을 변경하고 캐시에있는 동안 가능한 한 많이 해당 데이터를 다시 사용하십시오.

데이터를보다 강력하게 패킹하고 핫 루프의 캐시 라인에있는 모든 데이터를 사용하는지 확인하면 이러한 다른 효과를 피하고 캐시에 더 유용한 데이터를 넣을 수 있습니다.


우선 몇 가지 사전 답변에서 언급했듯이 성능이 무엇인지 물어보십시오. 메모리 또는 프로세서, 네트워크 또는 데이터베이스 또는 다른 것입니다. 그것에 따라 ...

  • ... 그것이 기억 인 경우 - "컴퓨터 프로그래밍의 기술"시리즈 중 하나 인 Knuth가 오래전에 쓴 책 중 하나를 찾습니다. 정렬 및 검색에 대한 가능성이 가장 높습니다. 내 기억이 잘못되면 느린 테이프 데이터 저장을 처리하는 방법에 대해 이야기해야합니다. 정신적으로 자신의 메모리 / 테이프 쌍을 캐시 / 주 메모리 쌍 (또는 L1 / L2 캐시 쌍)으로 각각 변환하십시오. 그가 기술 한 모든 트릭을 연구하십시오. 문제를 해결할만한 것을 찾지 못하면 전문 컴퓨터 과학자를 고용하여 전문 연구를 수행하십시오. 메모리 문제가 우연히 FFT (radix-2 버터 플라이를 할 때 비트 역 색인에서 캐시 미스)되면 우연히 과학자를 고용하지 마라. 대신에 당신이이기거나 승리 할 때까지 수동으로 패스를 하나씩 최적화한다. 막 다른 골목에. 지난 몇 퍼센트까지 쥐어 짜는 걸 언급하셨습니까? 실제로 그것이 거의 없다면 당신은 가장 이길 가능성이 높습니다.

  • ... 프로세서 인 경우 - 어셈블리 언어로 전환하십시오. 연구 프로세서 사양 - 진드기 , VLIW, SIMD가 필요한 항목. 함수 호출은 대체 가능 틱 - 먹는 사람입니다. 루프 변환을 배우십시오 - 파이프 라인, 언롤. 곱셈과 나눗셈은 비트 쉬프트로 대체 / 보간 될 수 있습니다 (작은 정수에 의한 곱셈은 덧셈으로 대체 가능). 더 짧은 데이터로 트릭을 시도해보십시오. 운이 좋다면 64 비트의 명령 하나가 32 비트의 2 비트 또는 16 비트의 4 비트 또는 8 비트의 8 비트로 대체 가능할 수도 있습니다. 더 긴 데이터를 사용해보십시오 - 예를 들어 플로트 계산이 특정 프로세서에서 두 배보다 느리게 계산 될 수 있습니다. 삼각 함수를 사용하는 경우 미리 계산 된 표를 사용하여 싸우십시오. 또한 정밀도의 손실이 허용 된 한도 내에 있으면 작은 값의 사인이 그 값으로 대체 될 수 있음을 명심하십시오.

  • ... 네트워크 인 경우 - 데이터를 압축하면 데이터가 전달됩니다. 바이너리로 XML 전송 대체. 연구 프로토콜. 어떻게 든 데이터 손실을 처리 할 수 ​​있다면 TCP 대신 UDP를 사용해보십시오.

  • ... 데이터베이스라면, 어떤 데이터베이스 포럼으로 가서 조언을 구하십시오. 메모리 내 데이터 그리드, 쿼리 계획 최적화 등

HTH :)


제안 :

  • 상대적으로 제한된 입력 범위를 갖는 계산을 포함하는 모든 반복 또는 반복 된 호출을 다시 계산하는 대신 사전 계산하십시오. 유효 범위의 모든 값에 대해 해당 계산 결과를 포함하는 조회 (배열 또는 사전)를 고려하십시오. 입력. 그런 다음 알고리즘 내부에서 간단한 검색을 사용하십시오.
    아래쪽 : 미리 계산 된 값 중 실제로 사용되는 값이 거의 없다면 문제가 악화 될 수 있고 조회가 상당한 메모리를 차지할 수도 있습니다.
  • 라이브러리 메소드를 사용하지 마십시오 . 대부분의 라이브러리는 다양한 시나리오에서 올바르게 작동하도록 작성되어야하고 매개 변수에 대해 널 검사를 수행해야합니다. 메소드를 다시 구현하면 많은 로직을 제거 할 수 있습니다. 당신이 그것을 사용하고있는 정확한 상황에 적용되지 않습니다.
    아래쪽 : 코드를 추가 작성하면 버그의 표면적이 증가합니다.
  • 도서관 방법을 사용하십시오 : 자신을 모순하기 위해 언어 라이브러리는 당신이나 나보다 훨씬 똑똑한 사람들이 씁니다. 확률은 더 좋고 더 빨랐습니다. 실제로 더 빨리 만들 수 없다면 직접 구현하지 마십시오 (예 : 항상 측정하십시오!).
  • 속임수 : 경우에 따라 정확한 계산이 문제에 대해 발생할 수 있지만 '정확한'필요하지 않을 수도 있습니다. 때로는 근사값이 '충분하고'거래가 훨씬 빠를 수도 있습니다. 답을 1 % 나 내면 정말 중요할까요? 5 %? 심지어 10 %?
    아래쪽 : 음 ... 그 대답은 정확하지 않을 것입니다.

Did you know that a CAT6 cable is capable of 10x better shielding off extrenal inteferences than a default Cat5e UTP cable?

비 - 오프라인 프로젝트의 경우 최상의 소프트웨어 및 최상의 하드웨어를 보유하고 전체 프로젝트가 약한 경우 해당가는 선은 데이터를 압축하여 지연 시간을 밀리 초 단위로 줄 것입니다 ... 그러나 마지막으로 드랍 한 경우 , 그것은 보내거나받은 모든 포장에 대해 24/7의 할인을 얻었습니다.


OS와 프레임 워크를 조정하십시오.

그것은 과잉으로 들릴지 모르지만 이것에 대해 생각해보십시오. 운영 체제와 프레임 워크는 많은 일을하도록 설계되었습니다. 귀하의 응용 프로그램은 매우 구체적인 것들을 수행합니다. OS에서 애플리케이션이 필요로하는 것을 정확하게 수행 할 수 있고 애플리케이션이 프레임 워크 (php, .net, java)의 작동 방식을 이해하게 만들면 하드웨어를 훨씬 잘 활용할 수 있습니다.

예를 들어 페이스 북 은 리눅스의 일부 커널 수준을 변경하고 memcached가 작동하는 방식을 변경했다. 예를 들어 memcached 프록시를 작성하고 tcp 대신 udp를 사용했다 .

이를위한 또 다른 예는 Window2008입니다. Win2K8에는 X 응용 프로그램 (예 : 웹 응용 프로그램, 서버 응용 프로그램)을 실행하는 데 필요한 기본 OS 만 설치할 수있는 버전이 있습니다. 이것은 OS가 실행중인 프로세스에 가하는 오버 헤드를 줄이고 더 나은 성능을 제공합니다.

물론, 당신은 항상 더 많은 하드웨어를 첫 번째 단계로 던져야합니다 ...


분열과 정복

처리중인 데이터 세트가 너무 큰 경우 해당 데이터 세트를 반복하십시오. 코드를 올바르게 작성했다면 구현이 쉬워야합니다. 모 놀리 식 프로그램이 있다면 이제는 더 잘 알 것입니다.


캐싱! 거의 모든 것을 더 빠르게 만드는 저렴한 방법 (프로그래머의 노력)은 프로그램의 데이터 이동 영역에 캐싱 추상화 계층을 추가하는 것입니다. I / O 또는 객체 / 구조의 전달 / 생성 만하면됩니다. 팩토리 클래스와 리더 / 라이터에 캐시를 추가하는 것이 종종 쉽습니다.

때로는 캐시가별로 도움이되지 않지만 캐시를 전부 추가 한 다음 도움이되지 않는 곳에서는 캐시를 사용하지 않는 쉬운 방법입니다. 코드를 미세하게 분석 할 필요없이 거대한 성능을 얻는 경우가 종종있었습니다.


값 대신에 기준으로 전달


깊이가 없거나 이전 답과 같이 복잡하지는 않지만 여기에 있습니다. (이들은 초급 / 중급 수준입니다)

  • 분명한 : 건조한
  • 루프를 거꾸로 실행하여 변수가 아닌 항상 0으로 비교합니다.
  • 가능할 때마다 비트 연산자를 사용하십시오.
  • 반복적 인 코드를 모듈 / 함수로 나눕니다.
  • 캐시 개체
  • 지역 변수는 약간의 성능 이점이 있습니다.
  • 가능한 한 문자열 조작을 제한하십시오.

저는 대역폭이 낮고 대기 시간이 긴 네트워크 (예 : 위성, 원격, 근해)에서 작동하는 클라이언트 / 서버 비즈니스 시스템을 최적화하는 데 시간을 할애하여 공정 반복적 인 프로세스로 몇 가지 극적인 성능 향상을 달성했습니다.

  • 측정 : 네트워크의 기본 용량 및 토폴로지를 이해하여 시작하십시오. 비즈니스의 관련 네트워킹 담당자와 대화하고 ping 및 traceroute와 같은 기본 도구를 사용하여 일반적인 운영 기간 동안 각 클라이언트 위치에서 네트워크 대기 시간을 설정합니다 (최소). 다음으로, 문제가되는 증상을 나타내는 특정 최종 사용자 기능에 대한 정확한 시간 측정을하십시오. 위치, 날짜 및 시간과 함께 이러한 모든 측정 값을 기록하십시오. 고급 사용자 "네트워크 성능 테스트"기능을 클라이언트 응용 프로그램에 구축하여 고급 사용자가 개선 프로세스에 참여하도록 고려하십시오. 이렇게 힘을 실어주는 것은 실적이 저조한 시스템에 좌절 한 사용자를 상대 할 때 심리적 충격을 줄 수 있습니다 .

  • 분석 : 영향을받는 작업의 실행 중에 어떤 데이터가 전송되고 수신되는지를 정확히 확인하는 데 사용할 수있는 모든 로깅 방법을 사용합니다. 이상적으로, 응용 프로그램은 클라이언트와 서버가 송수신 한 데이터를 캡처 할 수 있습니다. 여기에 타임 스탬프도 포함되면 더 좋습니다. 충분한 로깅을 사용할 수없는 경우 (예 : 폐쇄 시스템 또는 프로덕션 환경에 수정 사항을 배치 할 수없는 경우) 네트워크 스니퍼를 사용하여 네트워크 수준에서 진행중인 작업을 실제로 이해했는지 확인하십시오.

  • 캐시 : 정적 또는 드물게 변경된 데이터가 반복적으로 전송되는 경우를 찾고 적절한 캐싱 전략을 고려하십시오. 일반적인 예로는 "pick list"값이나 다른 "참조 엔터티"가 포함되며 일부 비즈니스 응용 프로그램에서는 놀라 울 정도로 커질 수 있습니다. 대부분의 경우 사용자는 자주 업데이트되는 데이터를 업데이트하기 위해 응용 프로그램을 다시 시작하거나 새로 고쳐야한다는 사실을 인정합니다. 특히 자주 사용되는 사용자 인터페이스 요소를 표시하는 데 상당한 시간을 절약 할 수있는 경우 더욱 그렇습니다. 이미 배치 된 캐싱 요소의 실제 동작을 이해해야합니다. 많은 일반적인 캐싱 방법 (예 : HTTP ETag)은 여전히 ​​일관성을 보장하기 위해 네트워크 왕복을 필요로하며 네트워크 대기 시간이 비싼 곳에서는 함께 피할 수 있습니다 다른 캐싱 접근법.

  • 병렬화 : 논리적으로 순차적으로 발급 될 필요가없는 순차적 트랜잭션을 찾아서 병렬로 처리하도록 시스템을 재 작업하십시오. 엔드 투 엔드 요청이 ~ 2 초의 고유 한 네트워크 지연을 갖는 경우를 다루었는데 단일 트랜잭션의 경우에는 문제가 아니지만 사용자가 클라이언트 애플리케이션을 제어하기 전에 순차적으로 6 회 왕복해야하는 경우 , 그것은 좌절의 거대한 원천이되었습니다. 이러한 트랜잭션이 실제로 독립적이라는 사실을 발견하면 최종 사용자 지연을 단일 왕복 비용에 매우 가깝게 줄여 병렬로 처리 할 수있었습니다.

  • 결합 : 순차적 요청을 순차적 으로 실행 해야하는 경우이를보다 포괄적 인 단일 요청으로 결합 할 수있는 기회를 찾습니다. 대표적인 예로는 새로운 엔티티 생성, 그 엔티티와 다른 기존 엔티티의 관련 요청이 있습니다.

  • 압축 : 텍스트 형식을 바이너리 형식으로 바꾸거나 실제 압축 기술을 사용하여 페이로드의 압축을 활용할 수있는 기회를 찾으십시오. 많은 현대의 (즉, 10 년 안에) 기술 스택은이를 거의 투명하게 지원하므로 구성되어 있는지 확인하십시오. 나는 종종 압축이 심각한 영향을 미쳤다는 것에 놀랐다. 문제는 대역폭보다는 근본적으로 대기 시간이었고 트랜잭션이 단일 패킷 내에 들어갈 수 있도록하거나 그렇지 않으면 패킷 손실을 피할 수 있었고 따라서 초대형 성능에 미치는 영향.

  • 반복 : 처음으로 돌아가서 동일한 위치 및 시간에 작업을 개선하고 작업 결과를 기록하고보고하십시오. 모든 최적화와 마찬가지로 현재 지배적 인 다른 문제를 노출시키는 일부 문제가 해결되었을 수도 있습니다.

위의 단계에서는 응용 프로그램 관련 최적화 프로세스에 중점을 둡니다. 물론 응용 프로그램을 지원하는 가장 효율적인 방식으로 기본 네트워크 자체가 구성되도록해야합니다. 비즈니스의 네트워킹 전문가를 고용하고 용량 향상, QoS, 네트워크 압축 또는 기타 문제 해결 방법을 적용 할 수 있는지 확인하십시오. 일반적으로 애플리케이션의 요구 사항을 이해하지 못하기 때문에 분석 단계 이후에 논의 할 준비가되어 있어야하며 발생 비용을 비즈니스 사례로 작성해야합니다. . 잘못된 네트워크 구성으로 인해 응용 프로그램 데이터가 육로 링크가 아닌 느린 위성 링크를 통해 전송되는 경우가 발생했습니다.단순히 네트워크 전문가가 "잘 알고있는"TCP 포트를 사용하지 않았기 때문입니다. 이와 같은 문제를 분명히 수정하면 소프트웨어 코드 나 구성 변경이 전혀 필요 없으므로 성능에 심각한 영향을 줄 수 있습니다.


다음은 내가 사용하는 빠르고 최적화 된 기술입니다. 나는 이것을 '첫 단계'최적화라고 생각한다.

시간을 어디에 사용하는지 배우십시오 시간 을 정확히 잡아내는 법 찾으십시오. 파일 IO입니까? 그것은 CPU 시간입니까? 네트워크입니까? 그것은 데이터베이스입니까? 그것이 병목 현상이 아니라면 IO를 최적화하는 것은 쓸모가 없습니다.

환경 파악 일반적으로 최적화 할 위치를 알면 개발 환경에 따라 다릅니다. 예를 들어 VB6에서는 참조로 전달하는 것이 값으로 전달하는 것보다 느리지 만 C 및 C ++에서는 참조로 훨씬 빠릅니다. C에서 리턴 코드가 실패를 나타내는 경우 다른 것을 시도하고 Dot Net에서 예외를 잡는 것이 시도하기 전에 유효한 조건을 확인하는 것보다 훨씬 느립니다.

인덱스 자주 쿼리되는 데이터베이스 필드의 인덱스를 작성합니다. 거의 항상 속도를 위해 공간을 교환 할 수 있습니다.

조회를 피하십시오. 최적화 할 루프 내부에서 조회 를하지 않아도됩니다. 루프 외부의 오프셋 및 / 또는 색인을 찾아 데이터를 다시 사용하십시오.

IO를 최소화하십시오. 특히 네트워크 연결을 통해 읽거나 쓰는 횟수를 줄이는 방식으로 디자인을 시도하십시오.

Reduce Abstractions 코드가 작동 해야하는 추상화 계층이 많을수록 느리게 진행됩니다. 임계 루프 내부에서 추상화를 줄입니다 (예 : 여분의 코드를 피하는 하위 수준 방법 공개).

사용자 인터페이스가있는 프로젝트를위한 스레드 를 생성하여 느린 작업을 수행하기 위해 새 스레드를 생성하면 응용 프로그램의 반응 이 느껴 집니다.

전처리 일반적으로 속도를 위해 공간을 교환 할 수 있습니다. 계산 또는 기타 강렬한 작업이있는 경우 중요 루프에 들어가기 전에 일부 정보를 미리 계산할 수 있는지 확인하십시오.


때로는 데이터 레이아웃을 변경하면 도움이 될 수 있습니다. C에서는 배열이나 구조체를 배열 구조체로 또는 그 반대로 바꿀 수 있습니다.


말할 수 없습니다. 그것은 코드가 어떻게 생겼는지에 달려 있습니다. 코드가 이미 있다고 가정 할 수 있다면 간단히 살펴보고 최적화 방법을 알아낼 수 있습니다.

보다 나은 캐시 수준, 루프 언 롤링, 긴 종속성 체인 제거로보다 나은 명령 수준 병렬 처리를 얻으십시오. 가능한 경우 분기를 통한 조건부 이동을 선호하십시오. 가능한 경우 SIMD 명령어를 활용하십시오.

코드가하는 일을 이해하고 실행중인 하드웨어를 이해하십시오. 그렇다면 코드 성능을 향상시키기 위해해야 ​​할 일을 결정하는 것이 매우 간단 해집니다. 그것은 정말로 제가 생각할 수있는 유일한 진정한 조언입니다.

글쎄, 그건, "코드를 SO에 표시하고 해당 코드 조각에 대한 최적화 조언을 요청하십시오".


  • 당신이 능률적 인 알고리즘을 사용하고 있다는 점에 이르면 더 많은 속도와 기억 이 필요한 것입니다. 캐싱을 사용하여 더 빠른 속도를 위해 메모리에서 "지불"하거나 계산을 사용하여 메모리 사용 공간을 줄입니다.
  • 가능하다면 (더 비용 효율적인) 하드웨어를 문제에 던지십시오 - 더 빠른 CPU, 더 많은 메모리 또는 HD로 문제를 빨리 해결 한 다음 코드를 작성하십시오.
  • 가능한 경우 병렬 처리를 사용하십시오 . 코드의 일부를 여러 스레드에서 실행 하십시오 .
  • 작업에 적합한 도구를 사용하십시오 . 일부 프로그래밍 언어는 관리 코드 (예 : Java / .NET)를 사용하여보다 효율적인 코드를 생성하지만 개발 속도를 향상 시키지만 기본 프로그래밍 언어는 더 빠른 실행 코드를 생성합니다.
  • 마이크로 최적화 . 적용 가능한 경우에만 최적화 된 어셈블리를 사용하여 코드의 작은 부분을 빠르게 처리 할 수 ​​있습니다. SSE / 벡터 최적화를 사용하면 올바른 위치에서 성능을 크게 높일 수 있습니다.

  • 어떤 하드웨어를 실행하고 있습니까? 플랫폼 별 최적화 (예 : 벡터화)를 사용할 수 있습니까?
  • 더 나은 컴파일러를 얻을 수 있습니까? 예 : GCC에서 인텔로 전환 하시겠습니까?
  • 알고리즘을 병렬로 실행할 수 있습니까?
  • 데이터를 재구성하여 캐시 미스를 줄일 수 있습니까?
  • 주장을 사용 중지 할 수 있습니까?
  • 귀하의 컴파일러 및 플랫폼을위한 마이크로 최적화. "if / else에서 가장 공통된 문장을 먼저 쓰십시오"라는 스타일로




language-agnostic