코드베이스가 균일하게 느려지는 것에 대한 접근법


11

우리는 최적화 노력을 통해 균일하게 느려지 는 적당한 크기의 C ++ 코드베이스 (10Mloc)를 연구하고 있습니다.

이 코드베이스는 우리가 결합하여 작동하도록 라이브러리 세트입니다. 이러한 라이브러리의 통신 방식에 대한 일반적인 프레임 워크가 개발 될 때 성능에 중점을 두었고 나중에 추가 된 부분이 많을 때 일반적인 프레임 워크는 크게 바뀌지 않았습니다. 필요할 때와 하드웨어가 발전함에 따라 최적화가 이루어졌습니다. 이로 인해 고가의 조기 결정이 훨씬 늦게 나타났습니다. 우리는 이제 코드베이스의 많은 부분을 다시 작성해야하기 때문에 추가 최적화가 훨씬 더 비싼 시점에 있습니다. 우리는 원칙적으로 코드가 훨씬 빠르게 실행될 수 있다는 것을 알고 있기 때문에 바람직하지 않은 로컬 최소값에 접근하고 있습니다.

쉬운 최적화 기회로 쉽게 혼동되지 않는 전 세계적으로 최적의 성능을 발휘하는 솔루션으로 코드베이스의 진화를 대체 할 방법을 결정하는 데 도움이되는 성공적인 방법이 있습니까?

편집하다

현재 프로파일 링 방식에 대한 질문에 답변하려면 :

우리는이 코드를 어떻게 사용할 수있는 지에 대해 두 가지 다른 시나리오만을 가지고 있습니다. 프로파일 링은 대량의 입력 샘플에 대한 평균 벽시계 시간과보다 자세한 실행 (명령 비용, 분기 오판 및 캐싱 문제)으로 수행됩니다. 이는 매우 균일 한 머신 (수천 개의 동일한 머신 클러스터)에서만 독점적으로 실행되므로 잘 작동합니다. 우리는 일반적으로 대부분의 시간 동안 대부분의 컴퓨터를 바쁘게 유지하기 때문에 새로운 것을 추가로 볼 수 있습니다. 문제는 새로운 입력 변형이 나타날 때 다른 사용 사례에서 가장 명백한 미세 비 효율성을 제거하여 "최적의 실행"시나리오의 수를 좁히기 때문에 후발 페널티를받을 수 있다는 것입니다.


10
10Mloc은 실제로 거대한 프로젝트입니다.
BЈовић

1
로 계산 된 천만 개 위치 (SI 접두사) sloc입니다. 여기서 "큰"항목이 무엇인지 알 수 없기 때문에 "보통 크기"라고했습니다.
Benjamin Bannier

5
거의 천만은 어느 곳에서나 크고 아마도 가장 큰 곳일 것입니다.
Ryathal

1
굉장합니다, @honk 감사합니다. 10M LOC의 경우 거의 하드웨어 수준에서 최적화 수준이 낮은 것 같습니까? 전통적인 OOP (AOS "구조 배열")는 캐시에서 끔찍하게 비효율적입니다. 클래스를 SOA (배열 구조)로 재정렬하려고했기 때문에 코드에서 작업중인 데이터 요소가 메모리에 일관성이 있습니까? 그 많은 컴퓨터에서 통신 차단 또는 동기화 시간이 걸리는가? 마지막 질문, 당신은 많은 양의 스트리밍 데이터를 다루고 있습니까? 아니면 데이터 세트에 대한 복잡한 작업의 문제입니까?
Patrick Hughes

1
코드가 많으면 내가 언급 한 비 로컬 종류의 잠재적 인 속도가 크게 향상 될 가능성이 뛰어납니다. 수천 개의 스레드 / 프로세스가 있으면 아무런 차이가 없습니다. 임의의 일시 중지로 인해 손가락이 손가락에 걸리거나 잘못되었음을 증명할 수 있습니다.
Mike Dunlavey

답변:


9

나는이 문제에 대한 범용 접근법을 모르지만 과거에는 다소 관련이있는 두 가지 접근법이 나에게 잘 적용되었습니다. 더 나은 용어가 없기 때문에 번들링수평 최적화 라고했습니다 .

번칭 접근 방식은 많은 수의 짧고 빠른 작업을 하나의 느리게 실행되는 고도로 전문화 된 단일 작업으로 대체하여 궁극적으로 동일한 결과를 생성하려는 시도입니다.

: 시각적 규칙 편집기의 느린 동작 하나를 프로파일 링 한 후 "낮은 중단 결실"을 발견하지 못했습니다. 실행 시간의 2 % 이상을 차지하는 단일 작업은 없었지만 전체 작업은 느리게 느껴졌습니다. 그러나 에디터가 서버에 많은 수의 작은 요청을 보내고 있음을 발견했습니다. 편집자가 개별 응답을 신속하게 처리했지만 요청 / 응답 상호 작용의 수는 곱한 효과를 가져 왔으므로 전체 작업 시간은 몇 초였습니다. 장기 실행 작업 중에 편집기의 상호 작용을 신중하게 카탈로그 한 후 서버 인터페이스에 새 명령을 추가했습니다. 추가 명령은 짧은 작업의 하위 집합을 수행하는 데 필요한 데이터를 허용하므로 더욱 전문화되었습니다. 최종 데이터 집합을 반환하기 위해 데이터 종속성을 탐색하고 서버로 한 번의 여행으로 모든 개별 소규모 작업을 완료하는 데 필요한 정보가 포함 된 응답을 제공했습니다. 이렇게하면 코드에서 처리 시간이 줄어들지 않았지만 값 비싼 클라이언트-서버 왕복을 제거하여 대기 시간이 크게 줄었습니다.

수평 최적화는 실행 환경의 특정 기능을 사용하여 시스템의 여러 구성 요소에 얇게 분산 된 "느림"을 제거 할 때 관련된 기술입니다.

: 장기 실행 작업을 프로파일 링 한 후 애플리케이션 도메인 경계에서 많은 호출을 수행함을 발견했습니다 (.NET에만 해당). 우리는 어떤 통화도 제거 할 수 없었고 함께 묶을 수 없었습니다. 그들은 시스템의 매우 다른 섹션에서 다른 시간에오고 있었고 요청한 것은 이전 요청에서 반환 된 결과에 달려있었습니다. 각 호출에는 비교적 적은 양의 데이터에 대한 직렬화 및 역 직렬화가 필요했습니다. 다시 말하지만, 개별 통화 시간은 짧았지만 매우 많았습니다. 우리는 직렬화를 거의 피하는 스키마를 설계하여 앱 도메인 경계를 가로 질러 포인터를 전달하는 것으로 대체했습니다. 완전히 관련되지 않은 클래스의 많은 요청이 단일 응용 프로그램의 결과로 즉시 훨씬 빨라 졌기 때문에 이것은 큰 승리였습니다.수평 솔루션.


경험을 공유해 주셔서 감사합니다.이 점은 명심해야 할 유용한 최적화입니다. 또한 문제가있는 부품을 별도의 장소로 들어 올리기 때문에 앞으로 더 잘 제어 할 수 있습니다. 어떤 의미에서 그들은 처음에는 무슨 일이 일어 났는지, 이제는 하드 데이터로만 돌아 왔습니다.
Benjamin Bannier

3

이로 인해 고가의 조기 결정이 훨씬 늦게 나타났습니다. 우리는 이제 코드베이스의 많은 부분을 다시 작성해야하기 때문에 추가 최적화가 훨씬 더 비싼 시점에 있습니다.

이 다시 쓰기를 시작하면 여러 가지 작업을 다르게 수행해야합니다.

먼저. 그리고 가장 중요합니다. "최적화"를 중지하십시오. "최적화"는 그다지 중요하지 않습니다. 보시다시피 도매 재 작성 만 중요합니다.

따라서.

둘째. 모든 데이터 구조 및 알고리즘 선택의 의미를 이해하십시오.

제삼. 데이터 구조와 알고리즘의 실제 선택을 "늦은 바인딩"문제로 만드십시오. 인터페이스 뒤에 사용되는 여러 구현 중 하나를 가질 수있는 디자인 인터페이스.

데이터 구조 나 알고리즘을 완전히 변경할 수있는 인터페이스 세트가 정의되어 있다면 지금하고있는 작업 (재 작성)이 훨씬 덜 고통 스럽습니다.


1
답변 주셔서 감사합니다. 우리는 여전히 (1과 2에 해당하는) 최적화해야하지만 3의 배후에있는 생각을 정말로 좋아합니다. 데이터 구조, 알고리즘 및 액세스를 늦게 명시 적으로 정의함으로써 많은 사람들을 처리 할 수 ​​있어야합니다. 우리가 겪고있는 문제. 일관성있는 언어로 작성해 주셔서 감사합니다.
Benjamin Bannier

실제로 최적화 할 필요는 없습니다. 올바른 데이터 구조를 갖추면 최적화가 노력의 낭비가됩니다. 프로파일 링은 잘못된 데이터 구조와 잘못된 알고리즘이있는 위치를 보여줍니다. 사이의 성능 차이와 장난 ++하고하는 것은 +=1부적절 거의 측정 할 수없는 것입니다. 그것은 당신이 지속 하는 것 입니다.
S.Lott

1
순수한 추론으로 모든 잘못된 알고리즘을 찾을 수있는 것은 아닙니다. 가끔 앉아서 앉을 필요가 있습니다. 이것이 초기 추측이 옳은지를 알아내는 유일한 방법입니다. 이것이 실제 비용 (BigO + const)을 추정 할 수있는 유일한 방법입니다.
Benjamin Bannier

프로파일 링은 잘못된 알고리즘을 나타냅니다. 완전히 맞습니다. 그것은 여전히 ​​"최적화"가 아닙니다. 그것은 여전히 ​​디자인을 변경하는 근본적인 디자인 결함의 수정입니다. 최적화 (트위 킹, 미세 조정 등)가 프로파일 링에 거의 보이지 않습니다.
S.Lott

3

실용적인 테스트 방법은 단위 테스트 스위트를 성능 테스트 스위트로 사용하는 것 입니다.

다음 접근법은 내 코드 기반에서 잘 작동했습니다.

  1. 단위 테스트 범위가 양호한 지 확인하십시오 (이미 이미 했습니까?).
  2. 테스트 실행 프레임 워크가 각 개별 테스트 에서 런타임을보고하는지 확인하십시오 . 성능이 저하 되는 위치 를 찾으려고하므로 중요합니다 .
  3. 테스트가 느리게 실행 되는 경우이 영역에서 다이빙을하고 최적화를 목표 로하는 방법으로 사용하십시오 . 성능 문제를 식별하기 전에 최적화하는 것은 시기상조로 간주 될 수 있으므로이 방법의 가장 큰 장점은 성능이 저하되었다는 확실한 증거를 먼저 얻는 것입니다. 필요한 경우 테스트를 여러 측면을 벤치마킹하는 더 작은 테스트로 나누면 근본 문제의 위치를 ​​식별 할 수 있습니다.
  4. 테스트가 매우 빠르게 실행되면 일반적으로 좋습니다.하지만 다른 매개 변수를 가진 루프에서 테스트를 실행하는 것을 고려할 수도 있습니다. 이를 통해 성능 테스트가 향상되고 매개 변수 공간의 테스트 범위가 늘어납니다.
  5. 엔드 투 엔드 트랜잭션 시간 또는 1,000 개의 규칙 애플리케이션을 완료하는 시간과 같이 성능을 구체적으로 목표로하는 몇 가지 추가 테스트를 작성하십시오. 작동하지 않는 특정 성능 요구 사항 (예 : 300ms 미만의 응답 시간)이있는 경우 너무 오래 걸리면 테스트에 실패합니다.

이 모든 것을 계속하면 시간이 지남에 따라 코드베이스의 평균 성능이 유기적으로 향상됩니다.

또한 과거 테스트 시간을 추적하고 성능 차트를 그리고 평균 성능에서 시간이 지남에 따라 회귀를 확인할 수 있습니다. 새로운 테스트를 변경하고 추가 할 때와 같은 방식으로 비교하는 것이 약간 까다롭기 때문에이 문제에 대해 전혀 신경 쓰지 않았지만 성능이 충분히 중요하다면 흥미로운 연습이 될 수 있습니다.


나는 기술처럼 - 영리 - howevre,이 마이크로 최적화하고 로컬 최소로 개선 - 그것은 건축 전역 최소값을 공격 할 수 있도록 문제가 해결되지 않습니다
jasonk을

@ Jasonk-당신은 절대적으로 맞습니다. 비록 특정 건축 변경이 정당화되는 이유를 설명하는 데 필요한 증거를 제공 할 수도
있다고 덧붙입니다

1

@dasblinkenlight의 답변은 매우 일반적인 문제, 특히 큰 코드 기반 (제 경험상)과 관련이 있습니다. 심각한 성능 문제가있을 수 있지만 현지화되지 않았습니다 . 프로파일 러를 실행하면주의를 끌기 위해 충분한 시간이 걸리는 루틴이 없습니다. (발신자가 포함 된 포함 시간 비율을 가정하면 "자기 시간"을 신경 쓰지 않아도됩니다.)

실제로이 경우 실제 문제는 프로파일 링이 아니라 운이 좋은 통찰력으로 발견되었습니다.

이 문제를 자세하게 설명하고 처리하는 방법에 대한 간단한 PDF 슬라이드 쇼 가있는 사례 연구 가 있습니다. 기본 포인트는 코드가 코드보다 훨씬 느리기 때문에 (정의 적으로) 초과 시간이 제거 될 수있는 일을하는 데 소비된다는 것을 의미합니다.

프로그램 상태의 임의 시간 샘플을 살펴보면 시간이 걸리기 때문에 제거 가능한 활동을 수행하는 것을 수 있습니다. 제거 가능한 활동이 하나의 기능 또는 많은 기능에 국한되지 않을 가능성이 있습니다. 그런 식으로 현지화되지 않습니다.

"핫스팟"이 아닙니다.

그것은 당신이 당신이 보는 것에 대한 설명이며, 그것은 대부분의 시간에 사실입니다. 따라서 검색하기가 간단하지만 수정하기 쉬운 지 여부는 다시 작성해야하는 양에 따라 다릅니다.

(이 접근법은 종종 통계적 타당성에 비해 샘플 수가 너무 적다는 비판이 있습니다. PDF의 슬라이드 13에서 답을 얻을 수 있습니다. 간단히, 예, 잠재적 절감의 "측정"에 대한 불확실성이 높지만 1) 잠재적 절감 효과 의 기대 값 은 본질적으로 영향을받지 않으며, 2) 잠재적 절감 효과 $ x $가 $ 1 / (1-x) $만큼 속도 향상 비율로 변환 될 때 높은 (유익한) 요인으로 치우칩니다.)


답변 주셔서 감사합니다. 우리는 통계 샘플링을 믿지 않으며 valgrind와 함께 계측을 사용합니다. 이것은 우리가하는 대부분의 물건에 대한 "자체"와 "포괄적 인"비용을 모두 잘 평가합니다.
Benjamin Bannier

@honk : 그렇습니다. 그러나 슬프게도 계측기는 여전히 성능 문제가 현지화되어 일상에서 소비되는 시간의 일부를 측정하여 찾을 수 있다는 아이디어를 가지고 있습니다. 확실히 Valgrind 등을 실행할 수 있지만 성능에 대한 진정한 통찰력을 원한다면 슬라이드 쇼를 확인하십시오. .
Mike Dunlavey가
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.