Apa yang bisa saya lakukan untuk mempercepat start-up saya?

41

Apa beberapa hal dasar yang bisa saya lakukan untuk mengurangi waktu start-up?

Apakah ada hal khusus yang harus saya perhatikan?

Catatan: Waktu mulai dapat dikurangi dengan memulai Emacs lebih jarang (sekali per sesi) dan membuka file dalam instance yang sedang berjalan . Pertanyaan ini adalah tentang meminimalkan waktu startup, untuk memulai sesi atau waktu lain ketika memulai Emacs diperlukan.


Lihat juga pertanyaan yang sama dijawab di Stack Overflow, dengan skor tanya dan jawab lebih dari 50 dan 30 - beberapa penanda "favorit". Jawaban yang baik di sini harus melampaui apa yang tersedia di Stack Overflow.

caisah
sumber
1
Saya ingin memiliki data tentang ini, tetapi dugaan saya adalah bahwa untuk sebagian besar pengguna ada satu atau dua paket yang membuat sebagian besar waktu startup. Dalam kasus saya itu adalah helm. Perhatikan bahwa jika Anda menggunakan helm Anda tidak dapat benar-benar menunda inisialisasi, Anda ingin segera menggunakannya. Saya beralih ke ivy dan itu membuat waktu mulai saya turun dari sekitar 12 detik menjadi kurang dari satu detik. Saya bahkan berhenti menggunakan pengaturan server / klien. (Ngomong-ngomong, saya tidak beralih untuk mengurangi waktu startup, itu hanya keuntungan sampingan yang bagus.)
Omar

Jawaban:

43

Inilah poin saya tentang pengurangan emacs-init-time, ini tidak mencakup hal-hal seperti menggunakan daemon atau server, tidak perlu dikatakan bahwa Anda harus jarang pernah menutup emacs.

Jangan:

  • Jangan memerlukan paket di init Anda, jika paket tidak memiliki cookie muat-otomatis yang tepat, pastikan Anda mengatur pengisian-otomatis pada perintah entri. Jadi jika pertama kali Anda menggunakan paket foobarakan dengan menelepon foobar-modedan foobartidak datang pra-autoload Anda akan membutuhkan sesuatu seperti ini:

    (autoload 'foobar-mode "foobar")
    

    ini akan memungkinkan Anda untuk menelepon foobar-modebahkan ketika foobarpaket belum dimuat. Cara foobarini tidak akan dimuat sebelum Anda benar-benar meneleponfoobar-mode

  • Jangan jalankan package-refresh-contentsjika Anda tidak perlu menginstal paket saat startup. Jika Anda init sedang menyiapkan untuk menginstal secara otomatis paket yang hilang, pertimbangkan untuk menyiapkan arg baris perintah untuk Anda tentukan kapan pemasangan otomatis akan terjadi.

  • Seperti di atas, jangan lakukan apapun yang berhubungan dengan jaringan.
  • Jangan memuat desktopinit Anda kecuali Anda benar-benar ingin.

Melakukan

  • Gunakan sesuatu seperti use-packagemengelola paket Anda. Ini membuatnya mudah untuk menentukan apa yang diperlukan, apa yang akan dimuat nanti, apa yang secara otomatis memuat apa dan membuat profil init Anda pada suatu paket berdasarkan paket menjadi mudah.

  • Ketahui perbedaan antara memuat tema dan mengaktifkannya. Singkatnya, Anda dapat memuat sebanyak yang Anda inginkan, tetapi pastikan Anda tidak mengaktifkan lebih dari satu. Idealnya, hanya memuat dan mengaktifkan satu tema. load-thememembutuhkan arg opsional untuk mencegah pengaktifan tema. Mungkin mudah untuk secara tidak sengaja mengaktifkan beberapa tema yang lambat dan jelek saat startup.

  • Jangan curang: Seringkali ada mode global besar yang ingin Anda muat di init, hal-hal seperti undo-tree, autocomplete, ido-mode dll. Pastikan fungsi entri memiliki pengaturan pengisian otomatis lalu mulai penghitung waktu kosong di init Anda untuk memuat paket . Saya melakukan ini akan undo-tree-mode, idodan yang lainnya dan tidak pernah melihat penundaan karena pada saat saya benar-benar perlu menggunakannya, mereka sudah dimuat.

    Pembaruan: paket penggunaan telah sedikit berubah, baca readme resmi sebelum Anda mulai menggunakan fitur-fitur pengatur waktu.

    Misalnya: jika Anda ingin sedikit menunda pemuatan, global-undo-tree-modeAnda dapat memasukkan ini ke init Anda:

    (run-with-idle-timer 1 nil (lambda () (global-undo-tree-mode t)))
    

    Sekarang init Anda dapat terus berlanjut dengan bahagia dan global-undo-tree-modetidak akan benar-benar diaktifkan sampai setelah semuanya siap untuk pergi dan Anda berada di belakang kemudi.

    use-packagememiliki dukungan untuk perilaku seperti ini yang dibangun menggunakan kata kunci: idle. Ini adalah undo-treekonfigurasi dari .init.el saya:

    (use-package undo-tree
      :idle (global-undo-tree-mode 1)
      :bind (("C-c j" . undo-tree-undo)
             ("C-c k" . undo-tree-redo)
             ("C-c l" . undo-tree-switch-branch)
             ("C-c ;" . undo-tree-visualize))
      :ensure t)
    
  • Lakukan profil init Anda, selalu mengejutkan untuk melihat di mana perlambatan sebenarnya. profile-dotemacs.el adalah alat luar biasa yang saya gunakan untuk membantu saya menurunkan init saya dari ~ 6 detik menjadi <1 detik.

use-packageInit yang dikonfigurasi dengan baik bisa sangat cepat. Saya tidak byte-compile init saya dan digunakan use-packageuntuk mengkonfigurasi 95 paket dan mulai dalam <1 detik.

Jordon Biondo
sumber
7
"Lakukan profil init-mu, selalu mengejutkan untuk melihat di mana pelambatan sebenarnya." Peringatan spoiler, itu (require 'org)garis itu. :-)
Malabarba
@Jordan, bisakah Anda memperluas sedikit tentang bagaimana Anda memastikan fungsi entri memiliki pengaturan autloads kemudian mulai timer idle di init Anda untuk memuat paket, khususnya untuk undo-tree-mode? Terima kasih.
Francisco Dibar
@FranciscoDibar Saya telah memperbarui posting saya dengan contoh.
Jordon Biondo
2
Saya menggunakan ido-mode segera, Cx Cf atau Mx untuk smex adalah hal pertama yang saya hampir selalu ketika saya membuka emacs, dan saya tidak pernah melihat masalah. Juga jika Anda ingin membatalkan sesuatu dalam sedetik setelah membuka emacs ... Yah, saya tidak punya apa-apa untuk dikatakan tentang itu. Jika Anda benar-benar peduli, cobalah sendiri, atau cukup gunakan timer non-idle atau setelah init hook.
Jordon Biondo
1
Saran pengatur waktu idle berguna. Sintaks memuat yang sedikit lebih pendek adalah (run-with-idle-timer 1 nil #'global-undo-tree-mode)'. If the function you are loading takes parameters you can just provide them after the perintah # '`.
Andrew Swann
8

Sesuatu yang baru-baru ini muncul di emacs reddit : kurangi jumlah permintaan pengumpulan sampah dengan meletakkannya di dekat bagian awal file init Anda:

(setq gc-cons-threshold 50000000)

(add-hook 'emacs-startup-hook 'my/set-gc-threshold)
(defun my/set-gc-threshold ()
  "Reset `gc-cons-threshold' to its default value."
  (setq gc-cons-threshold 800000))

Dalam contoh di atas, GC dipanggil setiap ~ 50MB (bukan default ~ 800kb), yang tampaknya masuk akal pada sistem modern dengan banyak RAM.

ffevotte
sumber
1
Kecuali bahwa nilainya (a) mungkin jauh lebih tinggi dari yang Anda butuhkan (saya tidak melihat perbedaan dengan sepersepuluh dari itu); dan (b) jelas bukan nilai yang ingin Anda pertahankan di luar permulaan, karena ambang GC yang besar setara dengan penundaan yang lebih lama setiap kali GC terjadi. Jika Anda mengaturnya tinggi untuk init, atur kembali lebih rendah setelah init. Saya pikir itu emacs-startup-hookadalah tempat yang baik untuk melakukan itu.
phils
1
@phils Terima kasih! (a) Pada pengaturan saya, 50MB memberikan jumlah GC minimum (dan waktu startup minimum). Jika saya pergi serendah 10MB, perbedaannya terlihat / terukur (meskipun tidak banyak berubah dalam praktik ...) (b) ide bagus, terima kasih. Saya mengedit posting untuk mencerminkan komentar Anda.
ffevotte
6

Waktu yang Anda habiskan untuk mengoptimalkan waktu startup Anda kemungkinan akan lebih besar daripada semua waktu ekstra yang seharusnya Anda tunggu untuk memulai Emacs.

Saat ini saya melakukan 25 requirepanggilan dalam file init saya sehingga Flycheck dapat menemukan kesalahan ejaan dalam kode saya. Waktu startup saya adalah ...

$ time emacs --eval '(save-buffers-kill-terminal)'

real    0m2.776s
user    0m2.305s
sys     0m0.148s

Juga, pada sistem saya, time emacs -Q --eval '(save-buffers-kill-terminal)'memiliki realdari 0m0.404s. Jumlah maksimum teoretis waktu yang bisa saya hemat adalah 2,3 detik.

Katakanlah bahwa saya menghabiskan satu jam membuat semua masalah optimasi ke file init saya. (Saya tidak akan menghitung tambahan 15-30 menit yang dihabiskan di kemudian hari mencoba mencari tahu mengapa perubahan saya tidak berpengaruh karena file init saya sedang byte-dikompilasi.) (Saya juga tidak akan menghitung waktu yang Flycheck akan menyelamatkan saya di debugger jika saya tidak menghapus requirepanggilan.) Ada 3600 detik dalam satu jam, jadi jika saya berhasil menyelamatkan seluruh 2,3 detik, investasi saya pada waktunya hanya akan terbayar setelah 1565 startup.

Dengan asumsi saya memulai kembali Emacs 3 kali sehari, setiap hari, itu akan memakan waktu satu setengah tahun untuk investasi untuk melunasi. Jika saya membiarkan instance Emacs yang sama berjalan selama berhari-hari pada suatu waktu (seperti yang sering saya lakukan), saya mungkin hanya akan memulai kembali 2-5 kali seminggu, dalam hal ini akan membutuhkan waktu 6 hingga 15 tahun agar investasi itu terbayar.

Saya bersikap murah hati, karena Anda cenderung menghabiskan lebih dari satu jam untuk mengoptimalkan startup Anda, dan Anda mungkin tidak akan menghemat jumlah teoritis maksimum detik.

Jackson
sumber
12
Tapi Anda berpotensi lebih bahagia.
phils
2
Itu mungkin benar untuk satu orang, tetapi inti dari StackExchange adalah tentang berbagi. Bagaimana dengan trik yang membutuhkan waktu 30 menit bagi satu orang untuk menemukannya, tetapi mencukur 1 detik waktu startup dari lusinan orang? Apakah Anda masih menganggapnya sebagai investasi yang buruk?
ffevotte
@phils Ironisnya, saya mempertimbangkan untuk mengatakan hal yang sama, tetapi untuk mendukung sudut pandang saya sendiri! "Sebelum Anda mengeluh tentang waktu startup Anda, pikirkanlah sendiri, 'Saya senang saya tidak membuang waktu untuk mengoptimalkan ini!'"
Jackson
@ Francesco Dan posting ini adalah trik saya yang menghemat banyak waktu orang.
Jackson
@ Jackson Saya masih tidak setuju dengan Anda tentang masalah khusus ini, tapi setidaknya sekarang saya mengerti maksud Anda. Terima kasih :)
ffevotte