Hoàn thành mã nhanh hơn với tiếng kêu


108

Tôi đang điều tra tốc độ hoàn thành mã tiềm năng trong khi sử dụng cơ chế hoàn thành mã của clang. Luồng được mô tả bên dưới là những gì tôi tìm thấy trong rtags , của Anders Bakken.

Các đơn vị dịch được phân tích cú pháp bởi tệp giám sát daemon để tìm các thay đổi. Điều này được thực hiện bởi clang_parseTranslationUnitcác hàm được gọi và liên quan ( reparse*, dispose*). Khi người dùng yêu cầu hoàn thành tại một dòng và cột nhất định trong tệp nguồn, daemon sẽ chuyển đơn vị dịch được lưu trong bộ nhớ cache cho phiên bản đã lưu cuối cùng của tệp nguồn và tệp nguồn hiện tại tới clang_codeCompleteAt. ( Tài liệu Clang CodeComplete ).

Các cờ được chuyển đến clang_parseTranslationUnit(từ quá trình hoàn thành ::, dòng 271 ) là CXTranslationUnit_PrecompiledPreamble|CXTranslationUnit_CacheCompletionResults|CXTranslationUnit_SkipFunctionBodes. Các lá cờ được chuyển đến clang_codeCompleteAt(từ quá trình hoàn thành ::, dòng 305 ) là CXCodeComplete_IncludeMacros|CXCodeComplete_IncludeCodePatterns.

Lệnh gọi tới clang_codeCompleteAtrất chậm - mất khoảng 3-5 giây để hoàn thành ngay cả trong trường hợp vị trí hoàn thành là mã truy cập thành viên hợp pháp, một tập hợp con của trường hợp sử dụng dự kiến ​​được đề cập trong tài liệu của clang_codeCompleteAt. Điều này có vẻ quá chậm theo các tiêu chuẩn hoàn thành mã IDE. Có cách nào để tăng tốc độ này không?


8
Tôi rất vui được giúp bạn nhưng chúng tôi cần thêm thông tin chi tiết. Mã ví dụ sẽ là tốt cho một sự khởi đầu
raph.amiard

1
Ping. Có tiến bộ nào về vấn đề này không?
Mehrwolf

4
@Cameron Xin lỗi vì sự chậm trễ trong thời gian dài liên hệ với bạn. Tôi đã thử tất cả 8 kết hợp CXTranslationUnit_SkipFunctionBodies, CXCodeComplete_IncludeMacros, CXCodeComplete_IncludeCodePatternsvà không thấy sự khác biệt đáng kể trên codebase tôi đang làm việc với. Tất cả chúng trung bình khoảng 4 giây mỗi lần hoàn thành. Tôi đoán điều này chỉ là do kích thước của các TU. CXTranslationUnit_PrecompiledPreambleđảm bảo reparseTUlà rất nhanh. Tuy nhiên, ngay cả với CXTranslationUnit_CacheCompletionResults, clang_codeCompleteAtrất chậm đối với trường hợp sử dụng của tôi.
Pradhan

1
@Mehrwolf Ack. Xem bình luận trên.
Pradhan

7
Hmm, thật không may. Bạn có thể tái tạo độ chậm hoàn thành trên một đơn vị dịch có sẵn cho công chúng (ví dụ: mã nguồn mở) không? Sẽ rất hữu ích nếu chúng ta có thể tự tái tạo điều này. Quá trình hoàn thành sẽ nhanh như báo cáo lại, vì đó là những gì nó thực hiện bên trong (nó đưa vào một mã thông báo hoàn thành mã đặc biệt và phân tích cú pháp cho đến thời điểm đó).
Cameron

Câu trả lời:


6

Vấn đề mà clang_parseTranslationUnit gặp phải là phần mở đầu được biên dịch trước không được sử dụng lại lần thứ hai được gọi là hoàn thành mã. Tính toán phần mở đầu biên dịch trước mất hơn 90% thời gian này, vì vậy bạn nên cho phép sử dụng lại phần mở đầu đã biên dịch trước ngay khi có thể.

Theo mặc định, nó được sử dụng lại lần thứ ba được gọi để phân tích cú pháp / phân tích lại đơn vị dịch.

Hãy xem biến 'PreambleRebuildCounter' này trong ASTUnit.cpp.

Vấn đề khác là phần mở đầu này được lưu trong một tệp tạm thời. Bạn có thể giữ phần mở đầu được biên dịch trước trong bộ nhớ thay vì một tệp tạm thời. Nó sẽ nhanh hơn. :)


Tuyệt vời! Điều này có vẻ như nó đi vào vấn đề thực sự. Sẽ xem xét điều này và cho bạn biết. Cảm ơn!
Pradhan

đồng ý! Hãy cho tôi biết nếu nó làm việc cho bạn! và nếu bạn có bất kỳ câu hỏi nào hãy hỏi tôi !!!!
GutiMac

4

Đôi khi sự chậm trễ ở mức độ này là do tài nguyên mạng hết thời gian chờ (NFS hoặc CIFS chia sẻ trên đường dẫn hoặc ổ cắm tìm kiếm tệp). Hãy thử theo dõi thời gian hoàn thành mỗi cuộc gọi hệ thống bằng cách ghi trước quá trình mà bạn chạy strace -Tf -o trace.out. Nhìn vào các số trong dấu ngoặc nhọn trace.outđể biết cuộc gọi hệ thống mất nhiều thời gian để hoàn thành.

Bạn cũng có thể theo dõi thời gian giữa các lần gọi hệ thống để xem quá trình xử lý tệp nào mất quá nhiều thời gian để hoàn thành. Để làm điều này, hãy đặt tiền tố cho quá trình bạn chạy strace -rf -o trace.out. Nhìn vào số trước mỗi cuộc gọi hệ thống để tìm khoảng thời gian dài của cuộc gọi hệ thống. Quay ngược lại từ thời điểm đó, tìm kiếm các opencuộc gọi để xem tệp nào đang được xử lý.

Nếu điều này không hữu ích, bạn có thể lập hồ sơ quy trình của mình để xem nó dành phần lớn thời gian ở đâu.

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.