Tôi có thể làm gì để tăng tốc khởi nghiệp?


41

Một số điều cơ bản tôi có thể làm để giảm thời gian khởi nghiệp là gì?

Có điều gì đặc biệt tôi nên chú ý, cho vấn đề đó?

Lưu ý: Thời gian khởi động có thể được giảm thiểu bằng cách bắt đầu Emacs ít thường xuyên hơn (một lần mỗi phiên) và mở tệp trong một phiên bản đang chạy . Câu hỏi này là về việc giảm thiểu thời gian khởi động, cho phiên bắt đầu hoặc bất kỳ lúc nào khác khi bắt đầu Emacs là cần thiết.


Xem thêm câu hỏi tương tự được trả lời trên Stack Overflow, với điểm số câu hỏi và câu trả lời trên 50 và 30 - một số dấu trang "yêu thích". Câu trả lời tốt ở đây nên vượt xa những gì có sẵn trên Stack Overflow.


1
Tôi rất muốn có dữ liệu về điều này, nhưng tôi đoán là đối với hầu hết người dùng, có một hoặc hai gói chiếm phần lớn thời gian khởi động. Trong trường hợp của tôi đó là helm. Lưu ý rằng nếu bạn sử dụng helm, bạn thực sự không thể hoãn việc khởi tạo nó, bạn muốn nó sẵn sàng để sử dụng ngay. Tôi chuyển sang cây thường xuân và điều đó khiến thời gian bắt đầu của tôi giảm từ khoảng 12 giây xuống còn chưa đến một giây. Tôi thậm chí đã ngừng sử dụng thiết lập máy chủ / máy khách. (Nhân tiện, tôi đã không chuyển sang giảm thời gian khởi động, đó chỉ là một lợi ích phụ tốt đẹp.)
Omar

Câu trả lời:


43

Đây là quan điểm của tôi về việc giảm emacs-init-time, điều này không bao gồm những thứ như sử dụng daemon hoặc máy chủ, không cần phải nói rằng bạn hiếm khi nên đóng emacs.

Đừng:

  • Không yêu cầu các gói trong init của bạn, nếu gói không có cookie tự động tải đúng, đảm bảo bạn thiết lập tự động tải trên các lệnh nhập. Vì vậy, nếu lần đầu tiên bạn sử dụng gói foobarsẽ bằng cách gọi foobar-modefoobarkhông được tải trước tự động, bạn sẽ cần một cái gì đó như thế này:

    (autoload 'foobar-mode "foobar")
    

    điều này sẽ cho phép bạn gọi foobar-modengay cả khi foobargói chưa được tải. Cách này foobarsẽ không được tải cho đến khi bạn thực sự gọifoobar-mode

  • Đừng chạy package-refresh-contentsnếu bạn không cần cài đặt các gói khi khởi động. Nếu init của bạn được thiết lập để tự động cài đặt các gói bị thiếu, hãy xem xét việc thiết lập một dòng lệnh arg để bạn chỉ định khi nào sẽ tự động cài đặt.

  • Giống như ở trên, không làm bất cứ điều gì liên quan đến mạng.
  • Đừng tải desktopinit của bạn trừ khi bạn thực sự muốn.

Làm

  • Sử dụng một cái gì đó như use-packageđể quản lý các gói của bạn. Điều này giúp bạn dễ dàng chỉ định những gì cần yêu cầu, những gì sẽ tải sau, những gì tự động tải những gì và làm cho hồ sơ init của bạn trên một gói theo cơ sở gói dễ dàng.

  • Phải biết sự khác biệt giữa tải một chủ đề và cho phép nó. Nói tóm lại, bạn có thể tải bao nhiêu tùy ý, nhưng hãy chắc chắn rằng bạn không kích hoạt nhiều hơn một. Lý tưởng nhất, chỉ tải và kích hoạt một chủ đề. load-themecần một đối số tùy chọn để ngăn chặn việc kích hoạt chủ đề. Có thể dễ dàng vô tình kích hoạt nhiều chủ đề chậm và xấu trong quá trình khởi động.

  • Cheat: Thường có các chế độ toàn cầu lớn mà bạn muốn tải trên init, những thứ như undo-tree, autocomplete, ido-mode, v.v. . Tôi làm điều này sẽ undo-tree-mode, idovà những người khác và không bao giờ nhận thấy sự chậm trễ bởi vì khi tôi thực sự cần sử dụng chúng, chúng đã được tải.

    Cập nhật: gói sử dụng đã thay đổi một chút, đọc readme chính thức trước khi bạn bắt đầu sử dụng các tính năng hẹn giờ.

    Ví dụ: nếu bạn muốn trì hoãn một chút việc tải, global-undo-tree-modebạn có thể đặt cái này vào init:

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

    Bây giờ init của bạn có thể tiếp tục vui vẻ và global-undo-tree-modethực sự sẽ không được kích hoạt cho đến khi mọi thứ khác sẵn sàng hoạt động và bạn ngồi sau tay lái.

    use-packageđã hỗ trợ cho loại hành vi này được xây dựng bằng cách sử dụng từ khóa: nhàn rỗi. Đây là undo-treecấu hình từ .init.el của tôi:

    (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)
    
  • Hãy lập hồ sơ cho init của bạn, thật đáng ngạc nhiên khi thấy sự chậm lại thực sự ở đâu. profile-dotemacs.el là một công cụ đáng kinh ngạc mà tôi đã sử dụng để giúp tôi gỡ init từ ~ 6 giây xuống <1 giây.

Một use-packageinit được cấu hình tốt có thể cực kỳ nhanh. Tôi không biên dịch byte của tôi và nó sử dụng use-packageđể cấu hình 95 gói và khởi động trong <1 giây.


7
"Hãy lập hồ sơ cho init của bạn, thật đáng ngạc nhiên khi thấy sự chậm lại thực sự ở đâu." Spoiler alert, đó là (require 'org)dòng. :-)
Malabarba

@Jordan, bạn có thể vui lòng mở rộng một chút về cách bạn đảm bảo các chức năng nhập có thiết lập tự động tải sau đó bắt đầu bộ tính giờ nhàn rỗi trong init của bạn để tải các gói, đặc biệt là cho chế độ hoàn tác cây không? Cảm ơn.
Francisco Dibar

@FranciscoDibar Tôi đã cập nhật bài viết của mình với các ví dụ.
Jordon Biondo

2
Tôi sử dụng chế độ ido ngay lập tức, Cx Cf hoặc Mx cho smex là điều đầu tiên tôi hầu như luôn luôn khi mở emacs và tôi chưa bao giờ nhận thấy vấn đề gì. Ngoài ra nếu bạn muốn hoàn tác một cái gì đó trong vòng một giây khi mở emacs ... Tôi không có gì để nói về điều đó. Nếu bạn thực sự lo lắng, hãy tự mình thử, hoặc chỉ sử dụng bộ đếm thời gian không sử dụng hoặc sau khi hook init.
Jordon Biondo

1
Đề xuất hẹn giờ nhàn rỗi là hữu ích. Cú pháp tải ngắn hơn một chút là (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 lệnh # '`.
Andrew Swann

8

Một cái gì đó gần đây đã xuất hiện trên emacs reddit : giảm số lượng các yêu cầu thu gom rác bằng cách đặt cái này gần đầu tập tin init của bạn:

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

Trong ví dụ trên, GC được gọi mỗi ~ 50 MB (thay vì mặc định ~ 800kb), có vẻ hợp lý trên một hệ thống hiện đại có nhiều RAM.


1
Ngoại trừ giá trị đó là (a) có thể cao hơn mức bạn cần (tôi thấy không có sự khác biệt với một phần mười của điều đó); và (b) rõ ràng không phải là một giá trị mà bạn muốn duy trì sau khi khởi động, bởi vì ngưỡng GC lớn tương đương với độ trễ dài hơn bất cứ khi nào xảy ra. Nếu bạn đặt nó ở mức cao cho init, hãy đặt nó trở lại thấp hơn sau init. Tôi nghĩ rằng đó emacs-startup-hooklà một nơi tốt để làm điều đó.
phils

1
@phils Cảm ơn! (a) Trong thiết lập của tôi, 50Mb cho số lượng GC tối thiểu (và thời gian khởi động tối thiểu). Nếu tôi xuống thấp tới 10Mb, sự khác biệt là đáng chú ý / có thể đo lường được (mặc dù nó không thay đổi nhiều trong thực tế ...) (b) ý tưởng tốt, cảm ơn. Tôi chỉnh sửa bài viết để phản ánh bình luận của bạn.
ffevotte

6

Thời gian bạn dành để tối ưu hóa thời gian khởi động của bạn có thể sẽ lớn hơn tất cả thời gian thêm mà bạn có thể chờ đợi Emacs khởi động.

Hiện tại tôi thực hiện 25 requirecuộc gọi trong tệp init của mình để Flycheck có thể tìm thấy lỗi chính tả trong mã của tôi. Thời gian khởi nghiệp của tôi là ...

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

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

Ngoài ra, trên hệ thống của tôi, time emacs -Q --eval '(save-buffers-kill-terminal)'có một realsố 0m0.404s. Lượng thời gian tối đa theo lý thuyết tôi có thể tiết kiệm là 2,3 giây.

Nói rằng tôi dành một giờ để thực hiện tất cả các vấn đề tối ưu hóa cho tệp init của tôi. (Tôi sẽ không đếm thêm 15-30 phút dành cho một ngày sau đó để cố gắng tìm hiểu lý do tại sao các thay đổi của tôi không có hiệu lực do tệp init của tôi được biên dịch byte.) (Tôi cũng sẽ không đếm thời gian Flycheck sẽ cứu tôi trong trình gỡ lỗi nếu tôi không xóa các requirecuộc gọi.) Có 3600 giây trong một giờ, vì vậy nếu tôi cố gắng lưu toàn bộ 2,3 giây, khoản đầu tư của tôi sẽ chỉ trả hết sau 1565 lần khởi động.

Giả sử tôi đã khởi động lại Emacs 3 lần một ngày, mỗi ngày, sẽ mất một năm rưỡi để khoản đầu tư đó được trả hết. Nếu tôi để cùng một ví dụ Emacs hoạt động nhiều ngày liền (như tôi thường làm), có lẽ tôi chỉ khởi động lại từ 2 đến 5 lần một tuần, trong trường hợp đó, phải mất 6 đến 15 năm để khoản đầu tư đó được thanh toán.

Tôi rất hào phóng, vì bạn có thể dành hơn một giờ để tối ưu hóa khởi nghiệp của mình và có lẽ bạn sẽ không tiết kiệm được số giây lý thuyết tối đa.


12
Nhưng bạn sẽ có khả năng hạnh phúc hơn.
phils

2
Điều đó có thể đúng với một người, nhưng toàn bộ quan điểm của StackExchange là về chia sẻ. Điều gì về một mẹo mất 30 phút để một người tìm thấy, nhưng làm mất đi 1 giây thời gian khởi động của hàng chục người? Bạn vẫn sẽ coi đó là một khoản đầu tư tồi?
ffevotte

@phils Trớ trêu thay, tôi đã cân nhắc việc nói điều tương tự, nhưng ủng hộ quan điểm của riêng tôi! "Trước khi bạn than vãn về thời gian khởi nghiệp của mình, hãy tự suy nghĩ, 'Tôi rất vui vì tôi đã không lãng phí thời gian để tối ưu hóa điều này!'"
Jackson

@Francesco Và bài đăng này là mẹo của tôi giúp tiết kiệm hàng chục thời gian của mọi người.
Jackson

@Jackson Tôi vẫn không đồng ý với bạn về vấn đề đặc biệt này, nhưng ít nhất bây giờ tôi thấy quan điểm của bạn. Cảm ơn :)
ffevotte
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.