Mengoptimalkan kinerja kunci font

13

Saya ingin melakukan varian pencocokan kunci font berlabuh. Saya memiliki definisi fungsi yang dimulai dengan daftar nama, dan saya ingin nama-nama itu disorot di dalam tubuh fungsi.

Saya telah membuat fungsi yang melakukan ini dan mendaftarkannya sebagai fungsi jit-lock dengan jit-lock-register, namun, kinerjanya sangat buruk dan gulir keterlambatan dalam file yang lebih besar.

  • Bagaimana saya bisa mengukur kinerja? Jika saya hanya waktu memanggil fungsi saya pada file besar (dengan float-time sebelum dan sesudah atau dengan elp) saya mendapatkan kinerja yang sangat bervariasi, dibutuhkan sekitar 0,65 hingga 12 detik. Apakah ada cara yang disarankan untuk mengukur kinerja kunci font?
  • Apakah ada perbedaan kinerja antara pencocokan berlabuh yang didefinisikan dalam font-lock-keywords dan menambahkan fungsi melalui jit-lock-register?

Sunting: Tampaknya variabilitas dalam kinerja terkait dengan pengumpulan sampah, pemanggilan fungsi jit-lock saya semakin lama semakin lambat dengan setiap pemanggilan sampai pengumpulan sampah dijalankan, pada titik mana mereka menjadi cepat lagi.

Joakim Hårsman
sumber
Untuk item pertama, coba profiler.
Malabarba
Saya dapat (dan telah) menggunakan profiler juga melihat bagian mana dari kode saya yang membutuhkan waktu, tetapi karena kinerjanya sangat tidak konsisten, sulit untuk mengatakan apakah ada perubahan yang saya lakukan merupakan peningkatan atau tidak.
Joakim Hårsman
Apakah Anda memiliki beberapa kode yang dapat kami uji? Itu mungkin banyak membantu kita.
PythonNut
1
Meskipun bukan tentang pembuatan profil atau optimasi mikro, namun: Saya telah menemukan paket font-lock-studio sebagai alat bantu lain untuk memahami kinerja font-lock. Ini dapat membantu dengan cara yang sama seperti debugger loncatan interaktif lainnya dapat membantu - Anda mungkin menemukan jalur eksekusi bukan yang Anda harapkan, dan itulah masalah kinerja utama.
Greg Hendershott
Terima kasih atas tip tentang font-lock-studio, ini luar biasa! Meskipun tidak membantu dengan fungsi-kunci-jit, tapi tentu saja tidak dengan yang lainnya.
Joakim Hårsman

Jawaban:

8

Ternyata kinerja yang sangat bervariasi terkait dengan pengumpulan sampah. Setiap panggilan ke fungsi akan menjadi lebih lambat sampai pengumpulan sampah dijalankan. Dengan emacs saham, gc dijalankan setiap beberapa detik, tetapi saya memiliki garis di init.el saya untuk meningkatkan waktu startup yang menetapkan gc-cons-threshold menjadi 20 MB, dan itu berarti gc dijalankan lebih jarang, menyebabkan tolok ukur untuk laporkan lebih lambat dan waktu lebih lambat sampai gc dijalankan setelah beberapa menit, maka waktu akan menurun dan cepat lagi.

Setelah kembali ke ambang default gc-cons-threshold, pembandingan menjadi lebih mudah.

Saya kemudian membuat profil untuk memori dengan built in profiler ( M-x profiler-start), dan menemukan bahwa panggilan ke sintaks-pps menyebabkan alokasi terbanyak, jadi setelah beberapa optimasi untuk memanggil sintaks-pps kurang sering saya mencapai kinerja yang dapat diterima.

Menggunakan mode jit-lock-mode (menambahkan fungsi melalui jit-lock-register) tampaknya menjadi cara termudah untuk mendapatkan penguncian font multi baris agar dapat bekerja dengan andal, jadi itulah metode yang saya pilih.

Sunting: Setelah menemukan bahwa kinerja masih tidak cukup baik di buffer yang sangat besar, saya menghabiskan banyak waktu untuk mengoptimalkan penggunaan dan alokasi cpu, mengukur peningkatan kinerja dengan built in Emacs profiler ( M-x profiler-start). Namun, Emacs masih akan gagap dan menggantung ketika menggulir dengan cepat melalui buffer yang sangat besar. Menghapus fungsi jit-lock yang saya daftarkan jit-lock-registerakan menghilangkan kegagapan dan hang, tetapi profiling menunjukkan fungsi jit-lock selesai sekitar 8 ms yang seharusnya cukup cepat untuk pengguliran yang lancar. Menghapus panggilan ke jit-lock-registerdan sebagai gantinya menggunakan pencocokan font-lock-keywords biasa menyelesaikan masalah.

TLDR: Melakukan ini lambat dan akan gagap:

(defun my-font-lock-function (start end)
"Set faces for font-lock between START and END.")

(jit-lock-register 'my-font-lock-function)

Melakukan ini dengan cepat dan tidak akan gagap:

(defun my-font-lock-function (start end)
"Set faces for font-lock between START and END.")

(defun my-font-lock-matcher (limit)
    (my-font-lock-function (point) limit)
   nil)

(setq font-lock-defaults
  (list 
     ...
    ;; Note that the face specified here doesn't matter since
    ;; my-font-lock-matcher always returns nil and sets the face on
    ;; its own.
    `(my-font-lock-matcher (1 font-lock-keyword-face nil))))
Joakim Hårsman
sumber
Bisakah Anda membagikan kode yang Anda gunakan? Solusi Anda mungkin membantu orang lain yang ingin mencapai hal yang sama.
Manuel Uberti
Saya tidak benar-benar menggunakan kode spesifik apa pun, saya hanya kurang memanggil sintaks-pps. Anda dapat memeriksa kode yang dimaksud di sini: bitbucket.org/harsman/dyalog-mode/src/… Cari dyalog-fontify-locals.
Joakim Hårsman
Saya kira dyalog-fontify-locals-matcherseharusnya my-font-lock-matcherdan salah satu yang endseharusnya limit. Pokoknya, penemuan yang sangat menarik!
Lindydancer
@ Lydydancer: Ya, terima kasih. Tetap.
Joakim Hårsman
1
Re:, gc-cons-thresholdjika Anda mengacaukan nilai internal semata-mata untuk meningkatkan waktu mulai, saya sarankan Anda gunakan emacs-startup-hookuntuk mengembalikannya setelah itu.
phils