2010-07-31 9 views
6

Tôi muốn biết - .NET JITter đệ quy nội tuyến các chức năng nhỏ được gọi là từ các chức năng nhỏ khác?.NET JIT có phải là một hàm nhỏ gọi một hàm nhỏ khác không?

Chỉ cần ví dụ:

public static float Square(float value) 
{ 
    return value * value; 
} 

public static float Cube(float value) 
{ 
    return Square(value) * value; 
} 

Nếu tôi gọi Cube từ đâu đó, nó sẽ inline tất cả các cách, hoặc tôi sẽ kết thúc với một cuộc gọi chức năng để Square?

Và, nếu có, làm cách nào nó sẽ tái chế để làm nội tuyến? (Giả sử tôi đủ điên khùng để thực hiện một hàm Quartic hoặc Quintic theo cách tương tự.)

Trả lời

10

Thật không may là bạn đã chọn một ví dụ xấu. Trình biên dịch JIT x86 không phải là các phương thức inline trả về float. Không chắc chắn 100% lý do tại sao, tôi nghĩ rằng nó để tránh những vấn đề nhất quán khi phao được chuyển đổi thành một giá trị dấu phẩy động 80 bit trong FPU. Độ chính xác nội bộ là 80 bit nhưng các bit phụ này bị cắt bớt khi giá trị 80 bit bị cắt ngắn trở lại giá trị 32 bit khi nó được xóa trở lại bộ nhớ. Việc giữ giá trị trong FPU quá lâu sẽ ngăn chặn việc cắt ngắn này xảy ra và thay đổi kết quả tính toán.

Nếu bạn thay thế phao bằng cách double và biên dịch mã này:

static void Main(string[] args) { 
    Console.WriteLine(Cube(2.0)); 
} 

Sau đó, mã máy tính này được tạo ra khi tôi ưu JIT được kích hoạt:

00000000 push  ebp        ; setup stack frame 
00000001 mov   ebp,esp 
00000003 call  6DA2BEF0      ; Console.get_Out() 
00000008 fld   qword ptr ds:[010914B0h]  ; ST0 = 8.0 
0000000e sub   esp,8       ; setup argument for WriteLine 
00000011 fstp  qword ptr [esp] 
00000014 mov   ecx,eax       ; call Console.Out.WriteLine 
00000016 mov   eax,dword ptr [ecx] 
00000018 call  dword ptr [eax+000000D0h] 
0000001e pop   ebp        ; done 
0000001f ret 

không chỉ nó nội tuyến chức năng, nó đã có thể đánh giá các biểu thức tại thời gian biên dịch. Và trực tiếp vượt qua kết quả bằng cách gọi Console.WriteLine (8.0). Khá tốt huh?

Sử dụng kép, không nổi.

+1

Thú vị ... vì tôi đang làm việc ở XNA nơi * mọi thứ * là một phao! Hơi liên quan đến ... –

+0

* "Trình biên dịch JIT x86 không phải là các phương thức inline trả về float." * - Bạn có chắc chắn về điều này không? Tôi đã tìm kiếm cao và thấp và không thể tìm thấy bất kỳ tài liệu tham khảo để trở lại này lên. Điều tốt nhất tôi thấy là trang này trên Connect: https://connect.microsoft.com/VisualStudio/feedback/details/536781/unexpected-jit-inlining-behavior mà dường như ngụ ý rằng các hàm trả về float * do *, trên thực tế, nội tuyến. Và bài báo (cũ) này ngụ ý rằng các quy tắc ép buộc (có thể khác nhau trong thực tế) là giống nhau đối với phao và đôi: http://blogs.msdn.com/b/davidnotario/archive/2005/08/08/449092. aspx –

+1

@Andrew: các quy tắc nội tuyến không được ghi lại, chỉ được đề cập trong một số bài đăng trên blog. Quan trọng, bởi vì họ cần để có thể thay đổi điều này để cải thiện jitter mà không vi phạm các giả định được thực hiện từ hành vi tài liệu. Tôi chỉ có thể ghi lại những gì tôi thấy jitter x86 của tôi làm. Và nó chắc chắn không inline phiên bản float của những phương thức này. Bạn có thấy hành vi khác nhau không? –