[DelphiCon 요약] 델파이 고성능 구현 (High Performance Delphi)


델파이 고성능 구현 (High Performance Delphi) 를 요약했습니다. (이 요약 번역은 원본 비디오와 내용이 일부 다르거나, Q&A등 일부 생략되었을 수 있습니다.)

이 요약에는 설명된 코드 중 중요한 부분만 적어두었습니다. 실제로 적용하기 전에는 제공되는 전체 코드를 받아서, 언급되지 않는 부분도 확인하기 바랍니다. (전체 코드라고 해도 매우 짧습니다)

델파이 고성능 구현 ‘Delphi High Performance’ 도서 저자의 성능 개선을 데모와 함께 알려줍니다. 여러분 코드에도 적용할 것이 있을 것입니다.

  • 성능 향상 개요
  • 성능 향상 중 알고리즘 향상 예시
    • 더 좋은 알고리즘 선택하기
    • 불필요한 코드 실행 줄이기
    • 불필요한 코드 실행 없애기

발표자 (Primož Gabrijelčič)는 1980년대 8비트 시절부터 파스칼 코드를 써오고 있습니다. 주로 방송용 고가용성 서버 프로그램을 개발하고 있으며, 수준높은 주제를 다루는 수많은 기고를 해오고 있습니다. (웹페이지: http://thedelphigeek.com)

발표자가 저술한 도서:

성능 향상 개요

’성능 향상’이 의미하는 바는 사람들마다 다를 수 있다. 하지만, ‘성능 향상 작업’을 하는 순서는 다음과 같다.

  • 문제 식별 (‘측정’이 중요하다!)
    • TStopwatch, 성능 카운터, GetTickCount 등을 활용하여 명시적으로 측정하자.
    • AQTime 등 전문 프로파일링 도구를 사용하는 것도 좋다.
  • ‘알고리즘 향상’: 가장 좋은 방법!!! (알고리즘 향상이 쉽지 않은 경우, 아래의 방법도 검토하자)
  • 세부적인 코드 튜닝
  • 병렬 처리 적용
  • 외부 라이브러리 사용
    • 더 좋은 알고리즘을 제공하는 라이브러리를 도입하여 빠르게 문제 해결 가능.
    • 주의할 점: 외부 라이브러리 제작자가 유지보수를 하지 않는 상황에 대한 대비가 필요
  • 어셈블러와 같은 저수준 언어로 (성능 향상이 필요한 부분을) 대체
    • 주의할 점: 10년 후에는 지금보다도 저수준 언어 개발자 찾기가 더 어려워 진다는 점을 고려해야 함

알고리즘 향상

이 세션에서는 유용한 2가지를 예제와 함께 살펴본다.

  • ‘더 좋은 알고리즘 적용’
  • ‘불필요한 코드 실행 줄이기와 없애기

알고리즘 복잡도

  • 데이터가 증가할 수록 프로그램이 어떻게 느려질 것인지를 판단할 때에도 유용하다.
  • 프로그램의 성능 문제는 데이터가 많아지면서 발생하는 경우가 많다.

*관련 웹페이지 추천:

O(1)은 데이터가 아무리 증가해도 성능이 저하되지 않는다. 피보나치 수열 재귀호출은 급적하게 저하된다 (역자 주: 재귀 호출은 매우 강력하지만, 코딩 시 매우 주의해야 합니다. 이 세션에서도 재귀 호출과 관련된 예시와 개선 방향이 제시됩니다)

더 좋은 알고리즘 예제: 무작위 단어 검색 프로그램의 성능을 향상해보자

알고리즘 1초 이내 결과 1초 이상 결과 시간 초과 비고
(무작위 단어를 만들고)
정렬되지 않은 TStringList 검색
~ 4글자 5글자 6글자
  • 위 표에서 O(n)에 해당; TStringList.Sorted := false
  • 최악의 경우, 37만번째 단어까지 찾아봐야 결과를 알 수 있다.
(무작위 단어를 만들고)
정렬된 TStringList 검색
~ 6글자 7글자 8글자
  • 위 표에서 O(log n)에 해당; TStringList.Sorted := true;
  • false 보다는 목록 생성 시간이 오래 걸리지만 검색 속도는 더 빠르다.
(무작위 단어를 만들고)
TDictionary 사용
~ 7글자 8글자 9글자  
(무작위 단어 조차 만들지 않고)
글자 수별로 TStringList를 따로 만들어서 사용
거의 무제한 해당 없음 해당 없음
  • 성능 개선을 위한 알고리즘을 창의적으로 만들자.

불필요한 코드 실행 줄이기

  • (일반적인 GUI 프로그램에서는) 초당 수천번씩 화면을 업데이트하지 말자.
  • BeginUpdate와 EndUpdate를 호출하자
  • (멀티 쓰레드 사용 시) 초당 수백만번 씩 운영체제에 메시지를 보내지 말자

불필요한 코드 실행 줄이기 예제: 2GB 파일을 1KB 단위로 읽고, 진행율을 표시하는 프로그램

불필요한 코드 실행 줄이기 예제: TListBox와 TMemo에 각각 10,000 개 항목을 넣는 프로그램

(참고:화면에 항목 하나를 표시하는 것은 그만큼 프로그램이 윈도우 운영체제와 메시지를 주고 받는다는 의미이다.

코드 TListBox 실행 시간 TMemo 실행 시간
루프 안에서 콘트롤에 10,000개 항목 추가 7초 28초
루프 앞뒤에 BeginUpdate와 EndUpdate 호출 0.5초 3초
루프 안에서는 화면이 없는 중간 매체(TStringList 사용)에 항목을 넣고, 루프 밖에서 TMemo에 한번에 넣기 (해당 없음) 0.2초
가상리스트 박스 (이것은 불필요한 코드 실행 없애기에서 따로 설명) 0.003초  

불필요한 코드 실행 없애기

  • UI 가상화: 가상 Listbox, 가상 TreeView 등, 기능은 모두 하면서 불필요한 실행 제거
  • BeginUpdate와 EndUpdate를 호출하자
  • 캐싱 활용

불필요한 코드 실행 없애기 예제: (UI 가상화) 가상 리스트 박스

앞에서 TListbox(와 TMemo)에 10,000개 항목을 넣는 루프의 앞뒤를 BeginUpdate와 EndUpdate로 감싸서 속도가 현격하게 빨라지는 것을 살펴보았다. 하지만, VirtualListbox를 사용하면 더 향상할 수 있다.

여전히 리스트박스에 10,000 항목을 넣고 있는데, 실제로 화면에서 한번에 표시되는 항목은 18개이다. 다른 항목을 보려면 스크롤해야 보인다.

그렇다면 스크롤에 맞는 항목만 즉시 제공할 수 있다면, 10,000개 항목을 미리 가지고 있는 것과 다를 바가 없다.

그렇게 한 결과, 같은 기능을 가진 리스트박스가 0.007초 만에 실행됨 (앞서 BeginUpdate사용 시 0.5초 걸렸음)

  • TListbox 설정 변경 
    • 프로퍼티: Style 프로퍼티를 lbVirtual로 변경 (기본값은 lbStandard)
    • 이벤트: OnData, OnDataFind, OnDataObject 구현
      • OnData: 리스트박스에 값이 제공되는 이벤트
      • OnDataFind: Listbox.Items.IndexOf 함수가 사용될 때 호출되는 이벤트
      • OnDataObject: (리스트박스에 오브젝트가 들어가 있는 경우 사용한다. 지금은 생략)

위와 같이 성능이 문제라면 문제되는 부분 (이 예제에서는 10,000개 항목을 리스트박스에 넣는 부분)을 아예 없애는 것을 고려하자.

불필요한 코드 실행 없애기 예제: (캐싱) 지역변수를 활용한 캐싱

앞서 사용한 FindGoodWord 함수에서 사용자가 지정한 단어의 글자수는 코드에서 여러번 사용된다. 그 때마다 TEdit에서 읽어오는 대신 한번만 읽고 WordLen이라는 지역변수에 넣어서 사용한다. 특히, 값을 계산하거나 가져오는 시간이 오래 걸리는 것일 수록 지역변수를 활용한 캐시 효과는 크다. 그리고 실제로 의외로 많은 코드에서 이런 부분이 간과되어 있다.

불필요한 코드 실행 없애기 예제: (캐싱) 피노나치 수열 계산 시 한번 계산된 값은 배열에 넣어 두기

피보나치 수열 계산 원리는 재귀 호출이다. 하지만, 프로그래밍에서 그대로 재귀 호출로 구현하는 것은 비효율적이다. 재귀 호출로 인한 성능 문제를 해소하기 위해 앞에서 설명한 것처럼 알고리즘을 개선하는 것이 좋다.

대체로 재귀 호출 대신 루프를 사용하여 이 문제를 해소할 수 있다. (코드는 비디오의 54분01초의 위치 참조)

하지만, 혹시 더 좋은 알고리즘을 찾을 수 없다면, 계산을 반복하지 않도록 캐싱을 검토해볼 수 있다. 피보나치 수열 계산을 그대로 재귀 호출을 하더라도, 한번 계산된 값을 배열에 넣어두어서 바로 꺼내쓰도록 하면 재귀 호출 시 같은 계산을 반복하지 않는다. 즉 O(1)이 된다. (코드는 비디오의 52분 17초 위치 참조)

O(1)을 구현한 캐싱 딕셔너리 (사용하기도 쉽다): https://github.com/gabr42/GpDelphiUnits

알고리즘 향상에 관심이 있는 개발자에게 권장하는 자료


AI api C++ c++빌더 code database Delphi fmx IDE ideas interbase ios migration modernization news python RAD스튜디오 tips UI UIUX vcl 개발 개발사례 개발팁 교육 기술레터 기술백서 데이터 데이터베이스 델파이 마이그레이션 모바일 안드로이드 윈도우 윈도우10 인공지능 인터베이스 출시 코드 파이썬 파이어몽키 프로그래밍 프로젝트 현대화