Tại sao CIL và CLR được yêu cầu trong .NET?


11

Tôi thấy hình ảnh đẹp này ở đây . Tôi đã học được rằng tất cả các trình biên dịch hỗ trợ ngôn ngữ .net chuyển đổi mã nguồn thành CILđịnh dạng. Bây giờ Microsoft không bao giờ đưa vào .NETtất cả các hệ điều hành bằng cách viết CLR cho tất cả các hệ điều hành. Vậy thì tại sao phải giữ một định dạng mã trung gian như vậy và CLR để thực thi CIL đó. Đó không phải là một vấn đề đau đầu để giải quyết. Tại sao Microsoft chọn như thế này?

EDIT Kiến trúc kinda này có giá của nó. Nó sẽ làm giảm hiệu suất, phải không? Java làm điều này để duy trì sự độc lập nền tảng, vì lý do gì .NET làm điều đó? Tại sao không giữ một trình biên dịch C đơn giản như trình biên dịch. Bất kỳ cách nào cũng sẽ yêu cầu trình biên dịch chuyển đổi mã thành CIL nếu tôi cần thêm bất kỳ ngôn ngữ mới nào, sự khác biệt duy nhất mà nó sẽ tạo ra là ngôn ngữ đích. Tất cả là tất cả.


3
Bởi vì nó dễ dàng hơn để viết trình biên dịch vào CIL. Và việc viết một CIL sang trình biên dịch gốc sẽ dễ dàng hơn so với trình biên dịch cho mỗi và mọi ngôn ngữ thành tiếng mẹ đẻ.
Oded

9
@ratchetfreak: đó có thể là một lý do khiến MS không chuyển CLR sang các nền tảng khác, nhưng đó không phải là lý do để có CLR ở vị trí đầu tiên (điều này thực sự làm cho một cổng dễ dàng hơn , vì vậy đối số của bạn nghe giống như MS bashing, xin lỗi)
Doc Brown

12
Ngoài ra downvote cho 'M $', đây là gì, 1998?
Alan B

3
Eric Lippert thảo luận về điều này (bắt đầu từ đoạn 3; 2 đoạn đầu là về Roslyn). Câu trả lời ngắn gọn là nhận xét của Oded và câu trả lời của Telastyn là đúng; bạn chỉ cần mã hóa trình biên dịch <Số lượng hệ điều hành> + <Số ngôn ngữ> thay vì <Số lượng hệ điều hành> * <Số ngôn ngữ> trình biên dịch.
Brian

3
@busy_wait: Trang được tham chiếu đề cập đến một vài nhược điểm. Ví dụ: "thông tin cấu hình trong hai ứng dụng có thể dẫn đến các quyết định ràng buộc khác nhau cho cùng một tổ hợp phụ thuộc." Tạo ra trên bay tránh những vấn đề này. Điều này ngụ ý rằng việc biên dịch thực sự cần phải được thực hiện sau khi ứng dụng được phân phối (và trên thực tế, NGEN phải được chạy trên mỗi máy đích; nó không thể được chạy bởi nhà phân phối).
Brian

Câu trả lời:


29

Bởi vì họ chỉ cần viết một trình biên dịch cho C # sang CIL - đây là phần khó. Tạo trình thông dịch (hoặc thường xuyên hơn, trình biên dịch Just-In-Time) cho CIL trên mỗi nền tảng là tương đối dễ dàng so với việc viết trình biên dịch từ mã thực thi C # sang (trên mỗi nền tảng).

Ngoài ra, bộ thực thi có thể xử lý mọi thứ biên dịch thành CIL. Nếu bạn muốn có một ngôn ngữ mới (như F #), bạn chỉ phải viết một trình biên dịch cho nó và bạn tự động nhận được tất cả các hỗ trợ nền tảng cho những thứ .NET hỗ trợ.

Ồ, và tôi có thể lấy một dll .NET và chạy nó trên windows hoặc trên linux thông qua Mono mà không cần biên dịch lại (giả sử tất cả các phụ thuộc của tôi đều được thỏa mãn).

Về hiệu suất, nó gây tranh cãi. Có những "trình biên dịch trước" về cơ bản lấy CIL và tạo các nhị phân riêng. Những người khác cho rằng trình biên dịch đúng lúc có thể tối ưu hóa mà trình biên dịch tĩnh đơn giản là không thể. Theo kinh nghiệm của tôi, nó phụ thuộc rất nhiều vào ứng dụng của bạn đang hoạt động và nền tảng bạn đang chạy trên nền tảng nào (chủ yếu là JITer hoạt động tốt như thế nào trên nền tảng đó). Rất hiếm khi tôi gặp phải một kịch bản mà .NET không đủ tốt .


"thông dịch viên" `? Tôi nghĩ rằng MS luôn chỉ cung cấp một JITter?
Doc Brown

1
@DocBrown - eh, vâng - tôi hiểu sai về phần tôi. Sửa chữa.
Telastyn

+1, bạn có thể thêm một chút giải thích cho chỉnh sửa của mình để tôi có thể chấp nhận câu trả lời này không
vikkyhacks

Thời gian chạy hiệu suất cao thường kết hợp trình thông dịch và trình biên dịch JIT (thực thi chế độ hỗn hợp). Tôi không chắc chắn về .NET, nhưng nhiều máy ảo Java sử dụng phương pháp này.
Cá Cyanfish

2
@busy_wait: Tất cả các loại. Phương pháp nội tuyến, sao chép lan truyền, loại bỏ mã không cần thiết, chuyển đổi phép nhân / chia thành ca, các phép toán số học khác bằng cách sử dụng readonlycác trường. Trình biên dịch truyền thống có thể thực hiện một số tối ưu hóa này nhưng chỉ khi chúng có thể được phát hiện bằng phân tích tĩnh. Ngược lại, một jitter có thể tìm ra trong thời gian chạy rằng (ví dụ) một phần mã không thực hiện bất kỳ công việc hữu ích nào vì các đối tượng hoặc biến mà nó sửa đổi không được tham chiếu ở bất kỳ nơi nào khác. Tôi không phải là chuyên gia về jitter nhưng về cơ bản nó là một câu hỏi về sức mạnh của phân tích động so với tĩnh.
Aaronaught

14

.NET có ngôn ngữ trung gian (CIL / MSIL) và các triển khai dành riêng cho nền tảng của thời gian chạy độc lập với nền tảng (CLR) với cùng lý do Java thực hiện. Microsoft dự định C # sẽ cạnh tranh trực tiếp với Java và trên các hệ điều hành mà Microsoft nhắm đến (trên chính nó).

Những ưu điểm, mặc dù .NET chỉ được hỗ trợ trên các nền tảng Windows (hoặc các HĐH khác có .NET giống như Mono / Linux), tương tự như Java:

  • Thời gian chạy bộ nhớ được quản lý - Không giống như C / C ++ không được quản lý, các nhà phát triển C # / VB.NET không phải lo lắng về việc kiểm soát chặt chẽ tuổi thọ của đối tượng. Giống như Java, CLR có trình thu gom rác tự động giải phóng các đối tượng trong vùng heap để lại phạm vi. Mặc dù điều này có vẻ nhỏ đối với ai đó đã từng sử dụng thời gian chạy không được quản lý, nhưng nó có lợi thế thứ yếu là không khuyến khích "ma thuật đen" của số học con trỏ rất phổ biến trong C / C ++.
  • Độc lập nền tảng - Windows Vista và Windows 7 hoạt động khác với Windows XP. Windows 8 hoạt động vẫn khác. Các phiên bản Windows Mobile bao gồm Windows 8 Mobile hoạt động lại khác nhau. Phần cứng khác nhau, kiến ​​trúc khác nhau, khả năng khác nhau. Mặc dù môi trường đích vẫn không quan trọng đối với nhà phát triển .NET, nhưng lượng kiến ​​thức chuyên ngành giảm đi rất nhiều so với những gì phải biết để xây dựng chương trình C / C ++ tương thích cho tất cả các HĐH này. AC # dev nhận được nhiều hơn miễn phí.
  • Hỗ trợ ứng dụng web - Tôi chưa thấy một ứng dụng web có mã máy chủ, đối diện với máy khách được viết từ đầu trong C ++. Máy chủ web , chắc chắn, Apache, ISS, tất cả chúng thường chạy với thời gian chạy không được quản lý vì lý do tốc độ / hiệu quả. Tuy nhiên, C ++ không phải là ngôn ngữ được sử dụng để xây dựng các ứng dụng web. C # là (như Java). Nó được thiết kế từ đầu để hỗ trợ cho mô hình ASP thế hệ tiếp theo của Microsoft. Đây là mã được thiết kế để chạy trong hộp cát; hộp cát nào (plugin ASP.NET cho ISS hoặc CLR "máy tính để bàn") tương đối không quan trọng.
  • Độc lập ngôn ngữ / thời gian chạy - Trình biên dịch C ++ lấy mã nguồn C ++ và tạo mã lắp ráp cho một kiến ​​trúc bộ xử lý bằng một ngôn ngữ máy. Để hỗ trợ một kiến ​​trúc và / hoặc ngôn ngữ máy khác, một trình biên dịch hoàn toàn mới phải được viết (và một bộ thư viện thời gian chạy hoàn toàn mới phải được biên dịch). Trình biên dịch AC # lấy mã nguồn C # và tạo CIL, mà JITer dành riêng cho phần cứng chuyển thành mã máy. Cùng một JITer có thể dịch bất kỳ chương trình CIL nào, bất kể ngôn ngữ nguồn nào (và có một số; C #, VB.NET, F # và một loạt các cổng ngôn ngữ "Iron" như IronHaskell, IronRuby, IronLisp, v.v.). Trình biên dịch tương tự có thể biến một ngôn ngữ thành CIL mà bất kỳ JITer nào cũng có thể chạy, bất kể phần cứng.
  • Tập trung vào mã "chính xác" - Đối với các nhà phát triển C ++, có rất nhiều cách "đúng" để làm điều gì đó, tùy thuộc vào điều quan trọng nhất; hiệu quả bộ nhớ, hiệu quả CPU, độc lập phần cứng, độc lập hệ điều hành, vv Mã có thể trông khác nhau đáng kể khi mỗi trong số này là ưu tiên. C # được thiết kế bởi một nhóm đã tập trung vào các bài học khái niệm của Fowler và các đồng nghiệp của anh ta (những người đang làm việc để cải cách thiết kế mã trong cộng đồng C ++ bằng cách dạy các nguyên tắc hướng đối tượng cho cộng đồng mà phần lớn chuyển từ C), như cũng như những bài học thực tế được học bởi các ngôn ngữ đi trước (bao gồm cả Java và sự phục tùng gần như cuồng tín của nó đối với Toàn năng, khi một con trỏ hàm kiểu C ++ cũ sẽ làm công việc sạch sẽ hơn và không phải là đối tượng ít hơn định hướng).

Vì lý do chống độc quyền, MS cẩn thận không bị "can thiệp" quá nhiều vào các nền tảng chính khác như Android, Mac OSX / iOS và Linux; tuy nhiên, thực sự có các nhóm phát triển cho cả ba nền tảng này. Có phiên bản Office dành cho OSX do MS phát triển, có rất nhiều ứng dụng bao gồm ứng dụng Office interop cho iOS và Android, Skype (hiện là sản phẩm của Microsoft) chạy trên Linux và Microsoft thậm chí còn được xem là đóng góp cho nhân Linux (chủ yếu trong một tư duy ảo hóa).


1
"Tôi chưa thấy một ứng dụng web có mã máy chủ, đối diện với máy khách được viết từ đầu trong C ++." - nơi nào bạn đặt CGI của ngày cũ? Các ứng dụng web đầu tiên của tôi (tầm thường như chúng) là 100% C. Trước đó (giữa những năm 90), việc viết một .c và .h để thực hiện công việc chuẩn trong cgi (ngôn ngữ 'scripting' chỉ là dễ dàng hơn nổi lên trên hiện trường quá).

hm ... CGI, CGI ... Tôi nghĩ rằng tôi đã nghe nói về nó, nhưng tôi với KeithS, tôi vẫn chưa thực sự nhìn thấy nó :)
DXM

@DXM mô hình cũ của nội dung động dành cho máy chủ web phân tách một quy trình và đặt mọi thứ vào vị trí tiêu chuẩn (tham số truy vấn và tương tự đã đi vào các biến môi trường cụ thể) - Giao diện cổng chung. Đầu ra của quá trình đó sau đó được gửi lại dưới dạng nội dung. Vào thời xưa, việc tìm một lập trình viên biết C hoặc C ++ dễ dàng hơn là perl hoặc python (và sh rất cồng kềnh cho công việc như vậy).

1
Đừng đánh giá thấp tầm quan trọng của sự tương đồng với Java. Sun vừa kiện MS về cảng JVM của họ và giành được một số điểm hợp pháp (ngu ngốc, IMHO). CIL và CLR được truyền cảm hứng từ đó và bạn sẽ nhận thấy rằng J # gần giống với Java mà không cần kích hoạt các hành động pháp lý tiếp theo. Một sự khác biệt rất lớn là CLR là bất khả tri ngôn ngữ. Bạn thực sự có thể viết một chương trình trong hỗn hợp C #, F # và J # nếu đó là những gì cần thiết. Chỉ cần cố gắng trộn Java với các thư viện trong các ngôn ngữ khác và có được một chương trình ổn định.
RBerteig

1
Nhưng interop giữa MSIL và mã gốc đều được xác định hợp lý và chỉ hoạt động. Và rõ ràng đã được dự kiến ​​sẽ chỉ làm việc theo thiết kế, và bởi thái độ của cộng đồng người dùng.
RBerteig

12

HĐH Windows có sẵn cho các loại CPU khác nhau, ngày nay chủ yếu là x64, x86, Intel, ARM.

CIL / CLR độc lập với nền tảng phần cứng đó - những khác biệt này được "trừu tượng hóa" bởi môi trường thực thi IL. Ví dụ, một tập hợp .NET được biên dịch cho "bất kỳ CPU" nào thường có thể được thực thi trên Win64 dưới dạng quy trình 64 bit và Win32 là quy trình 32 bit mà không cần cung cấp các tệp thực thi khác nhau.

Hơn nữa, CIL cho phép siêu dữ liệu được lưu trữ trong các hội đồng không dễ dàng với các DLL gốc (tất nhiên, có thể MS đã làm điều này trước đây với các thành phần COM, nhưng công nghệ đó chưa bao giờ dễ xử lý như các thành phần .NET). Điều đó làm cho việc tạo các thành phần phần mềm trở nên đơn giản hơn rất nhiều và là nền tảng của sự phản chiếu / hướng nội trong tất cả các ngôn ngữ .NET.


Chỉ cần thêm một chút vào điều này, họ không chỉ cho phép các loại CPU khác nhau mà thậm chí cả phiên bản khác nhau (Core i3 / i5 / i7) và nhà cung cấp (Intel so với AMD) trong cùng loại CPU (ví dụ tất cả x64) có thể khác nhau bộ hướng dẫn lắp ráp mà trình biên dịch JIT có thể tận dụng
DXM

2
@DXM: và bạn có biết JIT thực sự không? Hay đây là một điều giả thuyết?
Doc Brown

Ít nhất một blog MSDN tuyên bố trình biên dịch JIT thực hiện điều đó (hoặc đã làm, 8 năm trước).

@DocBrown: Rõ ràng là tôi không có tài liệu tham khảo nào trong tay, nhưng tôi nghĩ rằng tôi nhớ đã đọc một cái gì đó về điều này từ lâu. Cảm ơn delnan, vì đã tìm thấy liên kết. Sẽ có ý nghĩa vì chúng ta biết các nhà sản xuất chip muốn thêm các hướng dẫn của riêng họ lên trên tiêu chuẩn x86-x64, vậy nếu máy có thể tận dụng thì tại sao lại không?
DXM
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.