zsh làm chậm eval với đường dẫn
Tôi đã gặp sự cố về hiệu suất trong một thời gian khá dài khi thực hiện tự động hoàn thành trong một thư mục bằng zsh. Cuối cùng, tôi đã dành một chút thời gian để cố gắng hiểu NGUYÊN NHÂN GÌ gây ra vấn đề và LÀM THẾ NÀO để giải quyết nó. Thật không may, tôi phải dừng lại ở phần CÁI GÌ, CÁCH giải quyết vẫn còn là một dấu hỏi.
Khi chạy zsh trong gỡ lỗi với tính năng theo dõi được bật (và tắt tính năng của tôi .zshrc.local), tôi quản lý để thấy rõ ràng:
Khi nhấn đúp TAB, thực hiện $ cd ~/Documents/<TAB>, tôi nhận được:
....
+_cd:88> eval 'dir=( ~Documents/ )'
+(eval):1> dir=( '~Documents/' )
....
Quá trình chậm nhất mất ~ 3 giây để phản hồi.
Điều này xảy ra trên mọi cấp độ của thư mục tự động hoàn thành ( cd a/<TAB>, cd a/b/<TAB>, ...), không phải với cd <TAB>.
Tôi đã cố gắng thiết lập set -o magicequalsubst.
Trả lời
Dòng 88 của _cdhàm hoàn thành trong các phiên bản hiện tại củazsh nằm trong phần chỉ đạt được khi cdablevarstùy chọn được bật.
Với tùy chọn đó được bật, cd usernamehoặc cd varsẽ cdvào thư mục chính của usernamengười dùng hoặc vào đường dẫn được lưu trữ trong $varnếu người dùng / var đó tồn tại và không có username/ varthư mục trong thư mục hiện tại hoặc $cdpath. Nói cách khác, cd foohoạt động giống như cd ~fooif fookhông tồn tại dưới dạng một thư mục (trong .hoặc $cdpath).
Bây giờ, đó chỉ là thứ được thực hiện cho cd/ pushd. Khi _cdxây dựng danh sách các mục có thể hoàn thành và bạn đã nhập Documents/cho đến nay, nó cần cung cấp cho bạn danh sách các thư mục con của Documentsthư mục, ngoài ra, vì bạn đã bật cdablevars, danh sách các thư mục con của thư mục chính của Documentsngười dùng hoặc của thư mục được lưu trữ trong $Documentsbiến nếu có.
Đó là lý do tại sao nó làm điều đó eval 'dirs=( ~Documents )'.
Bây giờ, tôi tưởng tượng việc mở rộng có thể chậm nếu bạn đang sử dụng hệ thống có cơ sở dữ liệu người dùng được nối mạng lớn mà không có bộ nhớ đệm chẳng hạn (LDAP, NIS + ...). zshViệc tra cứu Documentstrong danh sách các biến sẽ nhanh chóng ngay cả khi bạn có hàng triệu biến vì zsh sử dụng bảng băm và gọi getpwnam("Documents")để truy xuất thư mục chính của Documentsngười dùng, đây là phần có thể chậm trong trường hợp của bạn. Bạn có thể xác nhận bằng cách thử cách id Documentsnào sẽ thực hiện cùng một getpwnam()cuộc gọi.
Cá nhân tôi sẽ không có cdablevarslựa chọn đó vì nó nhất định sẽ mang đến cho bạn những bất ngờ tồi tệ vào ngày này hay ngày khác. Nếu không có nó, bạn luôn có thể thực hiện cd ~userhoặc cd ~varvà tôi thấy tốt hơn nhiều nếu yêu cầu nó một cách rõ ràng khi bạn muốn cdvào một cái gì đó khác với thư mục đã cho làm đối số.
Điều đó cdablevarsđã có trong phiên bản đầu tiên của zshnăm 1990, lấy cảm hứng từ tcshđiều đó theo mặc định. Nó có trước sự mở rộng của ~var. cdablevarsnên được coi là một IMO đồ tạo tác lịch sử.
Về cách khắc phục sự chậm chạp của getpwnam(), bạn có thể xem điều chỉnh cơ sở dữ liệu dịch vụ tên. Ví dụ: nếu sử dụng sssd, bạn có thể tăng entry_negative_timeoutcài đặt xác định thời gian lưu vào bộ đệm thông tin mà Documentsngười dùng không tồn tại trước khi truy vấn lại chương trình phụ trợ. Dù sao thì 3 giây dường như là quá nhiều đối với truy vấn cơ sở dữ liệu người dùng, cho thấy bạn có thể gặp sự cố cấu hình hoặc máy chủ của nhà cung cấp không khả dụng và cơ chế dự phòng nếu có không được định cấu hình theo cách tối ưu.