Làm thế nào tôi có thể cải thiện thời gian khởi động mặc dù có nhiều gói?


19

TL; DR Tôi có một số lượng lớn các gói đến nỗi nó làm tổn thương thời gian khởi động của tôi. Nếu bạn không tin đó có thể là trường hợp, hãy đọc tiếp.


Thời gian khởi động Emacs của tôi khá nhỏ. Tôi không sử dụng use-package, tôi chỉ đặt hàng tấn hook và autoloads để gần như tất cả mã được hoãn lại. Trong thực tế, toàn bộ mọi thứ được tải trong chưa đầy nửa giây, mặc dù nó có vẻ như là một mớ hỗn độn điên rồ.

Tuy nhiên, theo thời gian tôi nhận thấy rằng thời gian khởi động của tôi trở nên chậm hơn một cách khó hiểu, không thể giải thích được. Điều này cuối cùng đã đến thời điểm khởi động là ≥ 1 giây. Cuối cùng tôi đã có đủ và tôi đã đi sâu vào gốc rễ của vấn đề. Cuối cùng tôi đã nhận xét toàn bộ ~/.emacstập tin của mình và thấy rằng thời gian khởi động vẫn là 1 giây. Trên thực tế, nó chỉ cạo được ~ 0.2giây, đôi khi còn ít hơn. Sau đó, tôi đã thử emacs -qvà thấy rằng thời gian khởi động là ~ 0.1giây.

Khi kiểm tra phần này của hướng dẫn Elisp, tôi đã tìm ra lý do tại sao emacs -qviệc giảm thời gian khởi động lại rất nhiều. Rõ ràng emacs -qngăn Emacs làm ba điều khi khởi động:

  1. tải tập tin init của bạn
  2. tải default.eltập tin của bạn
  3. gọi package-initialize

Chúng tôi đã loại trừ tập tin init của tôi, vì nhận xét toàn bộ ~/.emacstôi gần như không có gì. Tôi không sử dụng một default.eltập tin, vì vậy đó cũng bị loại trừ. Mà để lại package-initializelà thủ phạm cho hiệu suất hit.

Tại sao sẽ package-initializechiếm quá nhiều thời gian khởi động? Đó là câu hỏi đầu tiên tôi tự hỏi mình. Tôi không tự động tải mọi thứ à? Vâng, vâng. Nhưng đó chính xác là vấn đề.

Tôi tìm thấy bài đăng này giải thích rằng các gói "kích hoạt" bao gồm đọc các tệp tự động tải và thiết lập đường dẫn tải. Điều này rõ ràng phải chịu một hình phạt I / O khi bạn có nhiều gói vì bạn có nhiều tệp tự động tải để đọc và nhiều đường dẫn để thiết lập. Thật không may, không có điều này, nhiệm vụ quản lý tự động tải rơi vào tay người dùng. Nói cách khác, không cho phép package.elthu thập dữ liệu hệ thống tệp cho các tệp và đường dẫn tự động tải, tôi sẽ phải tự quản lý đó có thể là một quá trình dễ bị lỗi và dễ bị lỗi.

Tôi không muốn đi vào con đường đó. Tôi hiện có 116 gói, với 107 trong số đó là ELPA và 25 trong số đó là các gói phụ thuộc. Tôi chắc chắn rằng con số khổng lồ này là thứ đang làm giảm hiệu suất của tôi rất nhiều. Nhưng tôi rơi vào tình trạng khó khăn vì tôi không muốn xóa bất kỳ gói hàng nào của mình.

Có biện pháp khắc phục nào trong tình huống như vậy để lấy lại thời gian khởi động nhanh như chớp của tôi không?


Cập nhật:

Chúng tôi đã bắt đầu một chủ đề mới trong emacs-develdanh sách gửi thư về một số bản vá của Stefan Monnier (một mô tả về các bản vá này có ở đây ) để giải quyết vấn đề này. Bất cứ ai cũng được chào đón để kiểm tra các bản vá của mình và đưa ra phản hồi.

Một cập nhật khác:

Có vẻ như Stefan Monnier không còn quan tâm đến vấn đề này nữa hoặc anh ta không nhận được tin nhắn của tôi. Tôi có xu hướng tin rằng trước đây, điều đó là tốt, mặc dù tôi sẽ đánh giá cao một số loại phản ứng từ anh ta nếu đó là trường hợp. Dù sao, mã mà ông đã tạo ra cho vấn đề này cho đến nay hoạt động khá tốt. Các bản vá gần đây nhất của anh ta có thể được tìm thấy ở đây (cho Emacs 25.3)ở đây (cho chi nhánh chính của Emacs).Tôi đã thấy những cải thiện tốt về thời gian khởi động của mình nhờ các bản vá của anh ấy và tôi đang ở thời điểm mà tôi cảm thấy thoải mái với thời gian khởi động của mình rằng nó được tối ưu hóa nhất có thể mà không làm mất đi các tính năng tùy chỉnh của tôi. Tôi đã hy vọng rằng những bản vá này sẽ biến nó thành tuyến chính của Emacs vào một lúc nào đó, nhưng tôi đoán rằng tôi (hoặc ai đó) sẽ phải cầm ngọn đuốc cho nó ngay bây giờ, thay vì Stefan. Chúng tôi đã có một chút ít trong danh sách gửi thư về chuyển nhượng và cấp phép bản quyền. Ban đầu tôi không thoải mái với việc đó, nhưng do một số ý kiến ​​từ Richard Stallman và những người khác, việc chuyển nhượng bản quyền có thể không hạn chế như tôi nghĩ ban đầu. Hơn nữa, tôi có thể cam kết các tác phẩm của mình với phạm vi công cộng thay thế cho việc chuyển nhượng bản quyền.

Trong mọi trường hợp, cảm ơn Stefan cho các bản vá cho đến nay! Tôi hy vọng bạn sẽ tiếp tục phát triển những thay đổi này, nhưng nếu không, điều đó không sao và tôi có thể tiếp tục phát triển nó vào một lúc nào đó. Tôi cũng cảm ơn tất cả những người khác đã cung cấp cái nhìn sâu sắc và đóng góp để giải quyết vấn đề này.

Một cập nhật khác:

Wow, có vẻ như tính năng này cuối cùng đã hạ cánh và sẽ có trong Emacs 27. Cảm ơn Stefan Monnier!


Câu hỏi tuyệt vời.
vẽ

use-packagelà cách để đi cho việc này.
Dodgie

Không cố gắng hạ thấp vấn đề (độ trễ khởi động là quan trọng!), Nhưng hãy xem xét việc chạy emacs như một trình nền / máy chủ để bạn chỉ phải trả chi phí khởi động một lần.
GManNickG

1
@GManNickG Tôi chạy Emacs như một máy chủ. Thật không may, cứ thỉnh thoảng tôi lại đẩy Emacs quá mạnh hoặc mày mò với nó quá nhiều và khởi động lại là cách tốt nhất để dọn dẹp mọi thứ. Khi điều đó xảy ra, tôi thích thời gian khởi động của mình là tối ưu.
GDP2

Câu trả lời:


13

Một trong những lựa chọn thiết kế trong pack.el là thử và làm cho mọi thứ trở nên "đơn giản". Một phần của việc này là package-initializetìm kiếm tất cả các gói đã được cài đặt, sau đó cố gắng tìm ra gói nào sẽ được kích hoạt (theo ghim và ghi lại các phiên bản trong trường hợp có sẵn nhiều phiên bản của cùng một gói), sau đó tải mỗi <pkg>-autoloads.eltập tin kích hoạt gói .

Vì vậy, đối với N gói đã cài đặt, điều đó có nghĩa là về cơ bản đọc N <pkg>-pkg.eltệp mô tả gói và N <pkg>-autoloads.eltệp. Đối với Ns lớn, điều đó có thể trở thành một vấn đề nghiêm trọng. Một vấn đề hiệu năng tiềm năng khác là nó sẽ thêm N phần tử vào load-path, vì vậy mỗi khi bạn loadEmacs sẽ tìm kiếm thông qua N thư mục, vì vậy mỗi phần tử đều loadbị chậm lại.

Có nhiều cách khác nhau chúng ta có thể thử và tăng tốc độ này:

  • Cung cấp một số cách để tính toán trước một ~/.emacs.d/elpa/package-initialize.el(c)tệp sẽ là kết quả của việc ghép tất cả các quyền <pkg>-autoloads.eltheo đúng thứ tự. Sau đó package-initializechỉ có thể tải tệp này khi có mặt và bỏ qua mọi thứ khác. Sau đó, bạn cần một số cách để làm mới / xóa package-initialize.el(c)tệp khi các gói được thêm / cập nhật / xóa hoặc khi bạn thay đổi package-pinned-packageshoặc của bạn package-load-list. Tôi nghĩ rằng điều này có thể được thực hiện với khá ít thay đổi đối với hệ thống (điều duy nhất thực sự cần thay đổi tôi nghĩ là package-initializenó có thể được bảo là "chỉ kích hoạt" mà không cần tải siêu dữ liệu về các gói có sẵn).

  • Cung cấp một số cách để xây dựng / thao tác các siêu gói, tức là gói kết hợp nhiều gói thành một (vì vậy chỉ có một yếu tố được thêm vào load-path, một <pkg>-pkg.elvà một được <pkg>-autoloads.eltải). Điều này có thể cung cấp khó thực hiện hơn (vì sau đó bạn không thể kích hoạt chỉ một phần của các gói có trong các gói siêu lớn như vậy, vì vậy phân tích phụ thuộc / phiên bản có thể khó khăn).

Tùy chọn đầu tiên ở trên sẽ khá dễ thực hiện và sẽ nhanh hơn package-initialize nhiều khi bạn cài đặt nhiều gói. Nếu bạn quan tâm đến việc thử này, vui lòng yêu cầu tôi giúp đỡ.

FWIW, tôi vừa thử xây dựng một tệp tự động tải lớn như vậy "bằng tay" trên thiết lập thử nghiệm của mình. Kết quả: trong khi package-initializemất khoảng 0,9 giây, tải mega-autoloads.eltệp mất 0,3 giây mà tôi có thể giảm xuống 0,2 giây bằng cách liên kết load-source-file-functionvới nil và đến 0,1 giây bằng cách biên dịch tệp. Tôi mong đợi tốc độ tốt hơn, thành thật mà nói, nhưng nó vẫn còn giá trị.

[EDIT] Cách tiếp cận "tải tự động cực lớn" này hiện có sẵn trong nhánh chính của Emacs (để trở thành Emacs-27 trong một tương lai xa). Nó được điều khiển bởi package-quickstartbiến mới .


Đó là một số ý tưởng rất thú vị. Cái đầu tiên nghe có vẻ thực tế hơn và ít thách thức hơn. Cái thứ hai khá thú vị, nhưng nghe có vẻ như là một công việc cho các package.elnhà phát triển. Bạn có lời khuyên nào khi bắt đầu với lựa chọn đầu tiên đó? Tôi muốn xem những gì tôi có thể giải quyết nó, vì nó có vẻ khả thi hơn nhiều.
GDP2

el-get sử dụng cách tiếp cận tập tin tự động tải đơn, về cơ bản nó hoạt động hầu hết thời gian. Có vấn đề với một số gói có tải tự động phụ thuộc vào vị trí trong hệ thống tệp mà chúng được đánh giá. Tôi không làm theo ý của bạn bằng cách "theo đúng thứ tự" mặc dù vậy, tại sao thứ tự tải tự động lại trở nên quan trọng nghĩ rằng nó thậm chí còn mang tính quyết định cho gói hiện tại.el)?
npostavs

@Stefan vui lòng chia sẻ giải pháp tại đây, nếu có thể.
Manuel Uberti

1
@npostavs: Hầu hết <pkg>-autoloads.elcác tệp chỉ thiết lập tự động tải và thực sự không quan tâm đến việc đặt hàng, nhưng không có gì ngăn cản họ làm những việc khác ngẫu nhiên, và pack.el đảm bảo rằng gói <pkg>phụ thuộc sẽ được kích hoạt trước <pkg>chính nó.
Stefan

1
Một cập nhật khác về vấn đề này: chúng tôi đã bắt đầu một chủ đề mới trong danh sách gửi thư ở đây và bất kỳ ai cũng có thể tự do nhận xét hoặc kiểm tra các thay đổi của Stefan.
GDP2

6

Vấn đề bạn mô tả về package-initializeviệc mất quá nhiều thời gian để tải là một vấn đề nổi tiếng. Đây cũng là một trong những vấn đề mà một số khung emacs cố gắng giải quyết bằng cách tải tự động tải bằng tay.

Tôi thấy hai giải pháp cho vấn đề của bạn.

  1. Viết (hoặc trích xuất từ ​​khung) chức năng để đặt đường dẫn và tải tự động tải các gói bạn quan tâm.
  2. Sử dụng một khung rõ ràng nhắm mục tiêu tốc độ. Cá nhân tôi khuyên bạn nên DOOM emacs . Với khung này, tôi đang tải hơn 200 gói trong khoảng 1 giây.

Một trong những lợi ích chính để khuyến nghị các emacs DOOM là khung này đặt quản lý gói bên ngoài các emacs. Đừng hiểu sai ý tôi, vẫn còn đó là quản lý gói, chỉ là việc quản lý các gói được thực hiện bên ngoài phiên người dùng chuẩn. Triết lý ở đây là: khi bình thường bắt đầu emacs, chúng ta sẽ có thể giả định rằng tất cả các gói đều có mặt và đã có thể được tải. Điều này tiết kiệm rất nhiều thời gian. DOOM emacs cung cấp loại tương đương apt-gethoặc pacmancho emacs. Khi một gói được cài đặt, bất cứ khi nào emacs bắt đầu, nó được coi là đã được cài đặt; không có câu hỏi nào


Phew, vui mừng khi biết rằng vấn đề này không chỉ ảnh hưởng đến tôi. Cảm ơn bạn đã chỉ cho tôi đến DOOM Emacs. Tôi sẽ phải xem xét kỹ hơn về nó và xem những gì tôi có thể thích nghi với thiết lập của riêng tôi.
GDP2

Tôi đã chơi xung quanh với emacs DOOM (và đóng góp khi tôi có thể) một thời gian. Nếu bạn đang gặp vấn đề, hãy liên hệ với tôi.
UndeadKernel
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.