Elisp kodunun performansını nasıl ölçebilirim?


26

Elisp kodumun performansını nasıl ölçebilirim? Alınan zamanı ölçmek için hangi araçlar / harici paketler mevcut?

Toplam süreye ek olarak, işlev başına geçen süreyi gösteren bir profil görebilir miyim? Bellek kullanımını da profillendirebilir miyim?


1
Soru çok geniş. Ne tür bir performans? Nerede? Ne zaman? " Emacs performansı " her şey ve her şey anlamına gelebilir.
Drew

@Drew Diğer birçok programlama dili bir takım ölçütlere sahiptir (örn. Python: speed.pypy.org , JS: Sunspider vs.) ve elisp tercümanı için bir eşdeğeri olduğunu umuyordum.
Wilfred Hughes,

İşlev benchmarkve profiler tarafından sağlananlar gibi kıyaslama Emacs performansını ölçmez . Belirli ifadeleri değerlendiren performansı ölçer. Emacs içindeki performansların karşılaştırılmasında yardımcıdır . Emacs'in performansını ölçmek için onu Emac'lardan başka bir şeyle karşılaştırmanız gerekir. Ve burası Emac'ların genişliğinin devreye girdiği yer. Bunun için veya XYZ'e göre Emacs'i ölçebilirsiniz, ancak Emacs'ın performansını bir bütün olarak ölçmek için on beş gibi bir karşılaştırma yapmanız gerekir.
Drew

Belki de " Emacs'taki performansı nasıl ölçebilirim " demek istediniz ?
Drew

2
Tamam, emacs.stackexchange.com/q/655/304'ü Emacs'i kıyaslama konusunda açmak üzere açtım ve bu soruyu kıyaslama / elisp programlarını karşılaştırma konusunda yeniden sordum.
Wilfred Hughes,

Yanıtlar:


31

Karşılaştırma

En basit seçenek, yerleşik benchmarkpakettir. Kullanımı oldukça basittir:

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

Otomatik olarak yüklenmiştir, bu yüzden ihtiyaç duymanıza bile gerek kalmaz.

profil oluşturma

Kıyaslama genel testlerde iyidir, ancak performans sorunlarınız varsa, hangi işlevlerin soruna neden olduğunu size söylemez. Bunun için (ayrıca yerleşik) bir profilleyiciye sahipsiniz .

  1. Başla M-x profiler-start.
  2. Biraz zaman alan işlemler yapın.
  3. Raporu al M-x profiler-report.

Gezinilebilir bir işlev çağrısı ağacı olan bir ara belleğe götürülmeniz gerekir.
Profiler ekran görüntüsü


benchmarkişlev çalışmıyor gibi görünüyor: açık bir .cdosya içinde yaptığım zaman (benchmark 100 (c-font-lock-fontify-region 0 17355))alıyorum void-function jit-lock-bounds.
Hi-Angel

1
FTR: Bir alternatif benchmarkolarak fonksiyonlar vardır benchmark-runve benchmark-run-compiled. Benim için temel fark, her iki fonksiyonun da gerçekten işe yaramasıydı (önceki yorumu inceleyin) : Ь
Hi-Angel

14

@ Malabara'nın cevabına ek olarak, kodumun with-timerçeşitli bölümlerini (örn init.el. Dosyam) kalıcı olarak enstrümantasyon yapmak için ısmarlama bir makro kullanma eğilimindeyim .

Aradaki fark, sizin belirlediğiniz benchmarkbelirli bir kod bitinin performansını incelemenize izin verirken , size with-timerher zaman kodun işlenmiş bölümlerinde (yeterince büyük parçalar için fazla yük olmadan) harcadığınız zamanı verir. hangi bölüm daha fazla araştırılmalıdır.

(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))))))

Örnek kullanım:

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

*Messages*tamponda şu çıktıyı vererek :

Doing things... done (0.047s)

Bunun, Jon Wiegley'in use-package-with-elapsed-timermakrosundan mükemmel use-packageuzantısında büyük ölçüde ilham aldığından bahsetmeliyim .


İnit.el'i ölçüyorsanız, muhtemelen emacs başlangıç ​​profili oluşturucusuyla ilgileneceksiniz .
Wilfred Hughes,

Makrolar harika. Bu daha fazla oy hak ediyor.
Malabarba

2
Emacs toplam başlangıç ​​zamanını kaydeder. Komutla gösterebilirsin emacs-init-time.
Joe

1
@WilfredHughes evet, kullanıyorum esupve hoşuma gidiyor. Fakat bir kez daha, böyle bir şeyin ilgisi bir şeyi with-timerdikkatlice incelemek için çok fazla değildir. Asıl ilgi her zaman profil bilgisine sahip olmanızdır . Ne zaman emacs başlatsam, tamponumda *Messages*hangi kısmın ne kadar sürdüğünü söyleyen bir demet param var . Anormal bir şey tespit edersem, o zaman herhangi bir şeyi profillemek ve optimize etmek için daha uygun araçlardan birini kullanabilirim.
ffevotte

@JoeS Evet, emacs-init-timeilginç bilgiler üretir. Bununla birlikte, başlatmanın her bir parçasını parçalama imkanı olmadan yalnızca kapsayıcı bir geçen süre verir.
ffevotte

3

@ Malabarba'nın cevabına ek olarak , kodunuzun derlenmiş çalıştırma zamanını ile ölçebileceğinizi unutmayın benchmark-run-compiled. Bu metrik genellikle size verilen yorumlanmış yürütme süresinden çok daha fazla alakalı 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)

Üç sayı, geçen toplam süre, GC çalışma sayısı ve GC'de harcanan zamandır.


1

Kıyaslama sadece rakamları almakla kalmaz, aynı zamanda sonuç analizine dayanarak kararlar almakla da ilgilidir.

Orada benchstat.el o özellikleri almak için kullanabileceğiniz MELPA üzerindeki paket benchstat programı sağlar.

XPerformans özelliklerini karşılaştırdığınız yerlerde karşılaştırmaya dayalı kıyaslama yapar Y.

Benchstat işlevleri, benchmark-run-compiledyalnızca bilgileri toplayan değil, aynı zamanda yorumlama biçimini kolayca okunabilen bir sarmalayıcı olarak görülebilir . O içerir:

  • XVe arasında geçen zaman aralığıY
  • Ortalama ortalama zaman
  • Tahsis tutarı

Çok basit kullanım örneği:

(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)

Bu benchstat-compare, sonuçları geçici bir tamponda gösterecektir:

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)

benchstatYine de program ikili dosyasına ihtiyacınız olacak . Go programlama dilini kullandıysanız, büyük olasılıkla sisteminizde zaten bir tane vardır. Aksi halde kaynaklardan derleme seçeneği vardır.

Linux / amd64 için önceden derlenmiş bir ikili dosya github sürüm sayfasında bulunabilir .

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.