Câu trả lời ngắn: Số
dài trả lời: Bạn không thực sự cần trong hầu hết các trường hợp. Bạn có thể đưa ra gợi ý bằng cách thay đổi logic trong câu lệnh của bạn. Điều này dễ dàng hơn khi thực hiện với một công cụ hiệu suất, giống như công cụ được tích hợp vào các phiên bản cao hơn (và đắt tiền hơn) của Visual Studio, vì bạn có thể nắm bắt các bộ đếm chi nhánh bị lỗi. Tôi nhận ra điều này là dành cho mục đích học tập, nhưng thật tuyệt khi biết rằng JITer là rất tối ưu hóa mã của bạn cho bạn. Như một ví dụ (lấy khá nhiều nguyên văn từ CLR via C#)
Mã này:
public static void Main() {
Int32[] a = new Int32[5];
for(Int32 index = 0; index < a.Length; index++) {
// Do something with a[index]
}
}
có thể dường như không hiệu quả, vì a.Length
là một tài sản và như chúng ta đã biết trong C#, một tài sản thực sự là một tập hợp hai phương thức (get_Length
và set_Length
trong trường hợp này). Tuy nhiên, JIT biết rằng đó là một thuộc tính và lưu trữ độ dài trong một biến cục bộ cho bạn, hoặc inline phương thức, để ngăn chặn chi phí.
... một số nhà phát triển đã đánh giá thấp khả năng của trình biên dịch JIT và đã cố gắng để viết “mã thông minh” trong một nỗ lực để giúp trình biên dịch JIT . Tuy nhiên, bất kỳ nỗ lực thông minh nào mà bạn nghĩ ra sẽ gần như chắc chắn tác động tiêu cực đến hiệu suất và làm cho mã của bạn khó đọc hơn, giảm khả năng bảo trì của mã.
Trong số những thứ khác, nó thực sự đi xa hơn và không giới hạn kiểm tra một lần ngoài của vòng lặp thay vì bên trong vòng lặp, mà sẽ làm suy giảm hiệu suất.
Tôi nhận thấy nó không liên quan trực tiếp đến câu hỏi của bạn, nhưng tôi đoán điểm mà tôi đang cố gắng thực hiện là tối ưu hóa vi mô như thế này không thực sự giúp bạn nhiều trong C#, vì JIT thường nó tốt hơn, vì nó được thiết kế chính xác cho việc này. (Thực tế thú vị, trình biên dịch JIT x86 thực hiện tối ưu hóa tích cực hơn so với đối tác x64)
This article giải thích một số tối ưu hóa đã được thêm vào trong .NET 3.5 SP1, trong số đó là các cải tiến cho các nhánh thẳng để cải thiện dự đoán và vùng nhớ đệm. Tất cả điều đó được nói, nếu bạn muốn đọc một cuốn sách tuyệt vời mà đi vào những gì trình biên dịch tạo ra và hiệu suất của CLR, tôi khuyên bạn nên cuốn sách mà tôi trích dẫn từ trên, CLR thông qua C#.
EDIT: Tôi nên đề cập rằng nếu điều này hiện có thể có trong .NET, bạn có thể tìm thông tin trong số EMCA-335 standard hoặc working draft. Không có chuẩn hỗ trợ điều này và việc xem siêu dữ liệu trong một cái gì đó như IlDasm hoặc CFF Explorer không có dấu hiệu của bất kỳ siêu dữ liệu đặc biệt nào có thể gợi ý tại các dự đoán nhánh.
Bạn sẽ làm như thế nào, khi C# biên dịch thành IL, một mã byte có thể kết thúc sau đó được biên dịch thành bất kỳ CPU gốc nào? – Oded
Câu trả lời là "không, không thể." Lý do cho điều này không thể được chỉ ra bởi Oded. –
Tôi cho rằng tôi đã hy vọng nó có thể được thực hiện trong IL, vì IL được biên dịch xuống mã nguồn gốc, nơi một hướng dẫn cho gợi ý có thể được sử dụng. Hoặc, bất kỳ kỹ thuật tương tự nào khác, ngay cả khi không ở cấp độ bộ vi xử lý sẽ được quan tâm (mặc dù tôi không chắc chắn điều này là có thể). – ceyko