elisp 코드의 성능을 어떻게 측정합니까?


26

elisp 코드의 성능을 어떻게 측정합니까? 소요 시간을 측정 할 수있는 도구 / 외부 패키지는 무엇입니까?

총 시간 외에도 기능별 소요 시간을 보여주는 프로필을 볼 수 있습니까? 메모리 사용량도 프로파일 링 할 수 있습니까?


1
질문이 너무 광범위합니다. 어떤 종류의 성능? 어디에? 언제? " 이맥스 성능 "은 무엇이든 모든 것을 의미 할 수 있습니다.
Drew

@Drew 다른 많은 프로그래밍 언어에는 벤치 마크 세트가 있습니다 (예 : Python : speed.pypy.org , JS : Sunspider 등). elisp 인터프리터와 동등한 언어가 있기를 바랐습니다.
Wilfred Hughes

기능 benchmark및 프로파일 러가 제공하는 벤치마킹 은 Emacs 성능을 측정하지 않습니다 . 특정 표현식을 평가하는 성능을 측정합니다. 그것은 성능을 비교하는 데 도움이됩니다 이맥스. Emacs 자체의 성능을 측정하려면 Emacs 이외의 다른 성능과 비교해야합니다. 그리고 이맥스의 폭이 넓어집니다. 이를 위해 Emacs vs XYZ를 측정 할 수 있지만 Emacs 성능을 전체적으로 측정하려면 그러한 비교가 가장 필요합니다.
Drew

" Emacs에서 성능을 어떻게 측정 합니까?"라는 의미입니까?
Drew

2
OK, 저는 Emacs 벤치마킹에 대해 emacs.stackexchange.com/q/655/304열었고이 질문은 elisp 프로그램 벤치마킹 / 프로파일 링에 관한 것입니다.
Wilfred Hughes

답변:


31

기준

가장 간단한 옵션은 내장 benchmark패키지입니다. 사용법은 매우 간단합니다.

(benchmark 100 (form (to be evaluated)))

자동로드되므로 필요하지 않아도됩니다.

프로파일 링

벤치 마크는 전체 테스트에 적합하지만 성능 문제가있는 경우 어떤 기능이 문제를 일으키는 지 알려주지 않습니다. 이를 위해 (내장) 프로파일 러가 있습니다.

  1. 로 시작하십시오 M-x profiler-start.
  2. 시간이 많이 걸리는 작업을 수행하십시오.
  3. 로 보고서를 받으십시오 M-x profiler-report.

탐색 가능한 함수 호출 트리가있는 버퍼로 이동해야합니다.
프로파일 러 스크린 샷


benchmark함수가 작동하지 않는 것 같습니다 : 열린 .c파일 내부에서 할 때 (benchmark 100 (c-font-lock-fontify-region 0 17355))계속 계속 void-function jit-lock-bounds됩니다.
Hi-Angel

1
FTR : benchmark기능 대신 benchmark-run및 기능이 있습니다 benchmark-run-compiled. 저에게 가장 큰 차이점은 두 기능이 실제로 작동한다는 것입니다 (이전 주석 참조)
Hi-Angel

14

@Malabara의 답변 외에도 사용자 정의 with-timer매크로를 사용하여 코드의 다양한 부분 (예 : init.el파일) 을 영구적으로 계측 하는 경향이 있습니다 .

차이점은 benchmark계측하는 특정 코드 비트의 성능을 연구 할 수 있지만 with-timer항상 코드의 각 계측 된 부분에 소요되는 시간 (충분히 큰 부분에 대한 오버 헤드없이)을 제공한다는 점입니다. 어떤 부분을 더 조사해야하는지

(defmacro with-timer (title &rest forms)
  "Run the given FORMS, counting the elapsed time.
A message including the given TITLE and the corresponding elapsed
time is displayed."
  (declare (indent 1))
  (let ((nowvar (make-symbol "now"))
        (body   `(progn ,@forms)))
    `(let ((,nowvar (current-time)))
       (message "%s..." ,title)
       (prog1 ,body
         (let ((elapsed
                (float-time (time-subtract (current-time) ,nowvar))))
           (message "%s... done (%.3fs)" ,title elapsed))))))

사용 예 :

(with-timer "Doing things"
  (form (to (be evaluated))))

*Messages*버퍼에 다음과 같은 출력이 나타납니다 .

Doing things... done (0.047s)

Jon Wiegley의 use-package-with-elapsed-timer뛰어난 use-package확장 기능 에서 큰 영향을 받았다는 점을 언급해야 합니다.


init.el을 측정하는 경우 아마도 emacs 시작 프로파일 러에 관심이있을 것입니다 .
Wilfred Hughes

매크로는 훌륭합니다. 이것은 더 많은 표를받을 가치가 있습니다.
Malabarba

2
이맥스는 총 초기화 시간을 기록합니다. 명령으로이를 표시 할 수 있습니다 emacs-init-time.
Joe

1
@ WilfredHughes 네, 사용 esup하고 싶습니다. 그러나 다시 한 번, with-timer무언가에 대해 관심을 기울이지 않는 것에 대한 관심은 매우 터무니 없다. 실제 관심사는 항상 프로파일 링 정보 가 있다는 것 입니다. 이맥스를 시작할 때마다 *Messages*버퍼에 많은 줄이있어서 어느 부분이 얼마나 오래 걸 렸는지 알려줍니다. 비정상적인 것을 감지하면 더 적합한 도구를 사용하여 프로파일 링하고 최적화 할 수 있습니다.
ffevotte

@JoeS 예, emacs-init-time흥미로운 정보를 생성합니다. 그러나 초기화의 개별 부분을 분해하지 않고 포괄적 인 경과 시간 만 제공합니다.
ffevotte

3

@Malabarba의 답변 외에도을 사용 하여 코드 의 컴파일 된 실행 시간을 측정 할 수 있습니다 benchmark-run-compiled. 이 메트릭은 종종 다음 을 제공 하는 해석 된 실행 시간 보다 훨씬 관련성이 M-x benchmark있습니다.

ELISP> (benchmark-run (cl-loop for i below (* 1000 1000) sum i))
(0.79330082 6 0.2081620540000002)

ELISP> (benchmark-run-compiled (cl-loop for i below (* 1000 1000) sum i))
(0.047896284 0 0.0)

세 개의 숫자는 총 경과 시간, GC 실행 횟수 및 GC에 소요 된 시간입니다.


1

벤치마킹은 숫자를 얻는 것뿐만 아니라 결과 분석을 기반으로 결정을 내리는 것입니다.

MELPA 에는 benchstat.el 패키지 가 있으며 benchstat 프로그램이 제공 하는 기능을 얻는 데 사용할 수 있습니다 .

비교 X속성 벤치마킹을 구현하여 에 대한 성능 속성 을 검사 합니다 Y.

Benchstat 함수는 benchmark-run-compiled정보를 수집 할뿐만 아니라 해석 형식을 쉽게 읽을 수 있는 래퍼 로 볼 수 있습니다 . 다음을 포함합니다 :

  • X와 사이의 경과 시간 델타Y
  • 평균 평균 시간
  • 할당 금액

매우 간단한 사용법 예 :

(require 'benchstat)

;; Decide how much repetitions is needed.
;; This is the same as `benchmark-run-compiled` REPETITIONS argument.
(defconst repetitions 1000000)

;; Collect old code profile.
(benchstat-run :old repetitions (list 1 2))
;; Collect new code profile.
(benchstat-run :new repetitions (cons 1 2))

;; Display the results.
;; Can be run interactively by `M-x benchstat-compare'.
(benchstat-compare)

benchstat-compare임시 버퍼에 결과를 렌더링 :

name   old time/op    new time/op    delta
Emacs    44.2ms ± 6%    25.0ms ±15%  -43.38%  (p=0.000 n=10+10)

name   old allocs/op  new allocs/op  delta
Emacs      23.0 ± 0%      11.4 ± 5%  -50.43%  (p=0.000 n=10+10)

benchstat그래도 프로그램 바이너리 가 필요 합니다. Go 프로그래밍 언어를 사용한 경우 시스템에 이미 언어가있는 것 같습니다. 그렇지 않으면 소스에서 컴파일하는 옵션이 있습니다.

linux / amd64 용 사전 컴파일 된 바이너리는 github release page 에서 찾을 수 있습니다 .

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.