ทำไมต้อง CIL และ CLR ใน. NET


11

ผมเห็นภาพนี้ดีที่นี่ ฉันได้เรียนรู้ว่าคอมไพเลอร์ทั้งหมดที่สนับสนุน. net language จะแปลงซอร์สโค้ดเป็นCILรูปแบบ ตอนนี้ Microsoft จะไม่นำ.NETระบบปฏิบัติการทั้งหมดมาเขียน CLR สำหรับระบบปฏิบัติการทั้งหมด แล้วทำไมต้องเก็บรูปแบบรหัสกลางและ CLR เพื่อรัน CIL นั้น เป็นเรื่องที่ไม่ปวดหัวที่จะจัดการกับ เหตุใด Microsoft จึงเลือกเป็นเช่นนี้

แก้ไขสถาปัตยกรรมแบบนี้มีราคา มันจะลดประสิทธิภาพลงใช่มั้ย Java ทำเช่นนี้เพื่อรักษาความเป็นอิสระของแพลตฟอร์มด้วยเหตุผลใดที่. NET ทำเช่นนั้น? ทำไมไม่เก็บ C ธรรมดาอย่างคอมไพเลอร์ วิธีใดก็ตามที่จะต้องใช้คอมไพเลอร์ในการแปลงรหัสเป็น CIL หากฉันต้องการเพิ่มภาษาใหม่ใด ๆ ความแตกต่างเพียงอย่างเดียวก็คือภาษาเป้าหมาย ตาดเป็นทั้งหมด


3
เพราะง่ายต่อการเขียนคอมไพเลอร์ไปที่ CIL และการเขียน CIL หนึ่งตัวไปยังคอมไพเลอร์เนทีฟง่ายกว่าคอมไพเลอร์สำหรับแต่ละภาษา
— Oded

9
@ ratchetfreak: นั่นอาจเป็นเหตุผลสำหรับ MS ที่ไม่ได้ย้าย CLR ไปยังแพลตฟอร์มอื่น ๆ แต่ไม่ใช่เหตุผลที่มี CLR ในตอนแรก (ซึ่งจริงๆแล้วทำให้พอร์ตง่ายขึ้นดังนั้นการโต้แย้งของคุณก็เหมือนกับการทุบตี MS ขอโทษ)
— Doc Brown

12
นอกจากนี้ downvote สำหรับ 'M $' นี่คืออะไร 1998
— อลัน B

3
Eric Lippertพูดถึงเรื่องนี้ (เริ่มจากย่อหน้าที่ 3; 2 ย่อหน้าแรกเป็นเรื่องเกี่ยวกับโรสลิน) คำตอบสั้น ๆ ก็คือข้อคิดเห็นของ Oded และคำตอบของ Telastyn นั้นถูกต้อง คุณต้องใช้รหัส <จำนวนระบบปฏิบัติการ> + <จำนวนภาษา> คอมไพเลอร์แทน <จำนวนระบบปฏิบัติการ> * <จำนวนภาษา> คอมไพเลอร์
— Brian

3
@busy_wait: หน้าอ้างอิงอ้างถึงข้อเสียเล็กน้อย ตัวอย่างเช่น "ข้อมูลการกำหนดค่าในสองแอปพลิเคชันอาจส่งผลให้เกิดการตัดสินใจผูกพันที่แตกต่างกันสำหรับแอสเซมบลีที่ขึ้นต่อกันเหมือนกัน" การสร้างทันทีหลีกเลี่ยงปัญหาเหล่านี้ นี่หมายความว่าต้องมีการรวบรวมจริง ๆ หลังจากแอพพลิเคชั่นถูกแจกจ่าย (และในความเป็นจริง NGEN จะต้องทำงานบนเครื่องเป้าหมายแต่ละเครื่องไม่สามารถเรียกใช้โดยผู้จัดจำหน่าย)
— Brian

คำตอบ:


29

เพราะพวกเขาต้องเขียนคอมไพเลอร์เดียวสำหรับ C # ถึง CIL ซึ่งเป็นส่วนที่ยาก การสร้างล่าม (หรือบ่อยกว่านั้น Just-In-Time คอมไพเลอร์) สำหรับ CIL ต่อแพลตฟอร์มนั้นค่อนข้างง่ายเมื่อเทียบกับการเขียนคอมไพเลอร์จากโค้ดที่รันได้ C # ถึง (ต่อแพลตฟอร์ม)

นอกเหนือจากนั้นรันไทม์สามารถจัดการสิ่งที่รวบรวมไปยัง CIL หากคุณต้องการภาษาใหม่ (เช่น F #) คุณจะต้องเขียนเพียงหนึ่งคอมไพเลอร์สำหรับมันและคุณจะได้รับการสนับสนุนแพลตฟอร์มทั้งหมดโดยอัตโนมัติสำหรับสิ่งที่. NET รองรับ

โอ้และฉันสามารถใช้. dll dll และเรียกใช้บน Windows หรือบน linux ผ่าน Mono โดยไม่ต้องคอมไพล์ใหม่ (สมมติว่าการพึ่งพาทั้งหมดของฉันมีความพึงพอใจ)

สำหรับประสิทธิภาพมันเป็นที่ถกเถียงกัน มี "คอมไพเลอร์ก่อน" เป็นหลักที่ใช้ CIL และสร้างไบนารีพื้นเมือง คนอื่น ๆ อ้างว่าคอมไพเลอร์ทันเวลาสามารถทำการปรับแต่งที่คอมไพเลอร์สแตติกไม่สามารถทำได้ จากประสบการณ์ของฉันมันขึ้นอยู่กับสิ่งที่แอปพลิเคชันของคุณกำลังทำอยู่และแพลตฟอร์มใดที่คุณใช้งานอยู่ (ส่วนใหญ่ดีแค่ไหนที่ JITer ใช้งานบนแพลตฟอร์มนั้น) มันหายากมากสำหรับผมที่จะวิ่งเข้ามาในสถานการณ์ที่ .NET ก็ไม่ดีพอ


"ล่าม" `? ฉันคิดว่า MS มอบ JITter ให้เสมอหรือไม่
— Doc Brown

1
@DocBrown - เอ๊ะใช่ - เรียกชื่อผิดในส่วนของฉัน แก้ไข
— Telastyn

+1 คุณสามารถเพิ่มคำอธิบายเล็กน้อยสำหรับการแก้ไขของฉันเพื่อที่ฉันจะได้ตอบคำถามนี้ได้
— ไหม

runtimes ประสิทธิภาพสูงมักจะรวมล่ามและคอมไพเลอร์ JIT (การดำเนินการแบบผสม) ฉันไม่แน่ใจเกี่ยวกับ. NET แต่ Java VMs จำนวนมากใช้วิธีการนี้
— Cyanfish

2
@busy_wait: ทุกสิ่ง วิธีการ inline, คัดลอกการแพร่กระจาย, ลบโค้ดที่ไม่จำเป็น, แปลง multiplications / หารไปเป็นกะ, การดำเนินการทางคณิตศาสตร์อื่น ๆ โดยใช้readonlyฟิลด์ คอมไพเลอร์แบบดั้งเดิมสามารถทำการเพิ่มประสิทธิภาพบางอย่างได้ แต่เมื่อสามารถตรวจพบได้โดยการวิเคราะห์แบบสแตติก ในทางตรงกันข้ามผู้กระวนกระวายใจสามารถหาคำตอบได้ในขณะทำงาน (ตัวอย่าง) ส่วนของรหัสไม่ทำงานที่มีประโยชน์เพราะวัตถุหรือตัวแปรที่ดัดแปลงไม่ได้ถูกอ้างอิงถึงที่อื่น ฉันไม่มีความเชี่ยวชาญในเรื่องกระวนกระวายใจ แต่โดยทั่วไปแล้วคำถามเกี่ยวกับพลังของการวิเคราะห์แบบไดนามิกและแบบคงที่
— Aaronaught

14

.NET มีภาษากลาง (CIL / MSIL) และการใช้งานเฉพาะแพลตฟอร์มของ runtime-platform อิสระ (CLR) ด้วยเหตุผลเดียวกับที่ Java ทำ Microsoft ตั้งใจ C # เพื่อแข่งขันกับ Java โดยตรงและบน OS ที่ Microsoft กำหนดเป้าหมาย (ของตนเอง)

ข้อดีแม้ว่า. NET จะรองรับเฉพาะบนแพลตฟอร์ม Windows (หรือ OS อื่น ๆ ที่มี. NET workalike เช่น Mono / Linux) จะคล้ายกับ Java:

  • Managed Memory Runtime - ซึ่งแตกต่างจาก C / C ++ ที่ไม่มีการจัดการนักพัฒนา C # / VB.NET ไม่ต้องกังวลเกี่ยวกับการควบคุมอายุการใช้งานของวัตถุอย่างเคร่งครัด เช่นเดียวกับ Java CLR มีตัวรวบรวมขยะที่ปล่อยวัตถุในฮีปที่ออกจากขอบเขตโดยอัตโนมัติ ในขณะที่สิ่งนี้อาจดูเล็กน้อยสำหรับบางคนที่เคยใช้งาน runtimes มาก่อน แต่ก็มีข้อได้เปรียบที่สองรองจากการลดทอน "มนต์ดำ" ของตัวชี้ทางคณิตศาสตร์ที่พบได้ทั่วไปใน C / C ++
  • Platform Independence - Windows Vista และ Windows 7 ทำงานแตกต่างจาก Windows XP Windows 8 ยังคงทำงานแตกต่างกัน รุ่น Windows Mobile รวมถึง Windows 8 Mobile ทำงานแตกต่างกันอีกครั้ง ฮาร์ดแวร์ที่แตกต่างสถาปัตยกรรมที่แตกต่างความสามารถที่แตกต่างกัน ในขณะที่สภาพแวดล้อมเป้าหมายยังคงมีความสำคัญต่อผู้พัฒนา. NET จำนวนความรู้เฉพาะทางนั้นลดลงอย่างมากเมื่อเทียบกับสิ่งที่ต้องรู้ในการสร้างโปรแกรม C / C ++ ที่เข้ากันได้สำหรับระบบปฏิบัติการเหล่านี้ทั้งหมด AC # dev ได้รับมากขึ้นฟรี
  • การสนับสนุนเว็บแอปพลิเคชัน - ฉันยังไม่เคยเห็นแอปพลิเคชันเว็บที่เขียนโดยไคลเอนต์บนเซิร์ฟเวอร์ซึ่งเขียนด้วยภาษา C ++ เว็บเซิร์ฟเวอร์แน่นอน Apache และ ISS พวกเขามักจะทำงานกับรันไทม์ที่ไม่มีการจัดการด้วยเหตุผลด้านความเร็ว / ประสิทธิภาพ อย่างไรก็ตาม C ++ ไม่ใช่ภาษาที่ใช้สำหรับการสร้างเว็บแอปพลิเคชัน C # คือ (เช่นเดียวกับ Java) มันถูกออกแบบมาตั้งแต่แรกเริ่มเพื่อรองรับกระบวนทัศน์ ASP ของ Microsoft รุ่นต่อไป นี่คือรหัสที่ออกแบบมาเพื่อทำงานในแซนด์บ็อกซ์ แซนด์บ็อกซ์ใด (ปลั๊กอิน ASP.NET ไปยัง ISS หรือ CLR "เดสก์ท็อป") นั้นไม่สำคัญ
  • ความเป็นอิสระด้านภาษา / รันไทม์ - คอมไพเลอร์ C ++ ใช้ซอร์สโค้ด C ++ และสร้างรหัสประกอบสำหรับสถาปัตยกรรมตัวประมวลผลเดียวโดยใช้ภาษาเครื่องหนึ่งภาษา เพื่อสนับสนุนสถาปัตยกรรมที่แตกต่างกันและ / หรือภาษาเครื่องคอมไพเลอร์ใหม่ทั้งหมดจะต้องถูกเขียน (และชุดใหม่ของไลบรารีรันไทม์ใหม่จะต้องรวบรวม) AC # compiler รับซอร์สโค้ด C # และสร้าง CIL ซึ่ง JITer เฉพาะสำหรับฮาร์ดแวร์แปลเป็นรหัสเครื่อง JITer เดียวกันสามารถแปลโปรแกรม CIL ใด ๆ ไม่ว่าภาษาต้นฉบับ (และมีหลายภาษาคือ C #, VB.NET, F # และโฮสต์ของพอร์ตภาษา "Iron" เช่น IronHaskell, IronRuby, IronLisp, ฯลฯ ) คอมไพเลอร์เดียวกันสามารถเปลี่ยนหนึ่งภาษาเป็น CIL ที่ JITer ใด ๆ สามารถรันได้ไม่ว่าจะเป็นฮาร์ดแวร์ใดก็ตาม
  • มุ่งเน้นไปที่รหัส "ถูกต้อง" - สำหรับ C ++ devs มีวิธี "สิทธิ" มากมายในการทำบางสิ่งทั้งนี้ขึ้นอยู่กับสิ่งที่สำคัญที่สุด ประสิทธิภาพหน่วยความจำ, ประสิทธิภาพของ CPU, ความเป็นอิสระของฮาร์ดแวร์, ความเป็นอิสระของระบบปฏิบัติการ, ฯลฯ รหัสสามารถดูแตกต่างกันอย่างมากเมื่อแต่ละสิ่งเหล่านี้มีความสำคัญ C # ได้รับการออกแบบโดยกลุ่มที่คำนึงถึงบทเรียนแนวคิดของ Fowler และเพื่อนร่วมงานของเขา (ผู้ที่ทำงานเพื่อปฏิรูปการออกแบบรหัสภายในชุมชน C ++ โดยการสอนหลักการเชิงวัตถุให้กับชุมชนที่ย้ายมาจาก C) เช่นเดียวกับบทเรียนภาคปฏิบัติที่เรียนรู้จากภาษาที่มีมาก่อน (รวมถึง Java และการเชื่อฟังอย่างใกล้ชิดต่อวัตถุยิ่งใหญ่เมื่อ C ++ เก่าที่ดี - ตัวชี้ฟังก์ชั่นสไตล์จะทำงานได้อย่างหมดจดมากขึ้น oriented)

สำหรับเหตุผลในการต่อต้านการผูกขาด MS ระวังไม่ให้ "รบกวน" อย่างหนักเกินไปในแพลตฟอร์มหลักอื่น ๆ เช่น Android, Mac OSX / iOS และ Linux; อย่างไรก็ตามมีการพัฒนาทีมสำหรับทั้งสามแพลตฟอร์มเหล่านี้ มี Office รุ่นที่พัฒนาโดย MS สำหรับ OSX มีแอพพลิเคชั่นมากมายรวมถึง Office interop apps สำหรับ iOS และ Android, Skype (ปัจจุบันเป็นผลิตภัณฑ์ของ Microsoft) ที่ทำงานบน Linux และ Microsoft ก็เห็นได้ว่ามีส่วนร่วมในเคอร์เนล Linux ชุดความคิดเสมือนจริง)


1
"ฉันยังไม่เห็นแอปพลิเคชันบนเว็บที่เขียนสคริปต์โดยใช้เซิร์ฟเวอร์ซึ่งเขียนขึ้นตั้งแต่ต้นใน C ++" - คุณใส่ CGIs ของวันเก่าที่ไหน เว็บแอปพลิเคชั่นแรกของฉัน (ไม่สำคัญเหมือนพวกเขา) คือ 100% C. ย้อนกลับไป (กลางปี ​​90) มันง่ายกว่าในการเขียน. c และ. h สำหรับการทำงานมาตรฐานในภาษา cgi (ภาษา 'สคริปต์' เป็นเพียง เกิดขึ้นในที่เกิดเหตุด้วย)

อืม ... CGI, CGI ... ฉันคิดว่าฉันได้ยินเรื่องนี้ แต่ฉันอยู่กับ KeithS ฉันยังไม่เห็นจริง ๆ :)
— DXM

@DXM รูปแบบเก่าของเนื้อหาแบบไดนามิกสำหรับเว็บเซิร์ฟเวอร์แยกกระบวนการและวางสิ่งต่าง ๆ ในสถานที่มาตรฐาน (params แบบสอบถามและสิ่งที่คล้ายกันในตัวแปรสภาพแวดล้อมที่เฉพาะเจาะจง) - Common Gateway Interface ผลลัพธ์ของกระบวนการนั้นถูกส่งกลับเป็นเนื้อหา ในสมัยก่อนมันง่ายกว่าที่จะหาโปรแกรมเมอร์ที่รู้จัก C หรือ C ++ มากกว่า perl หรือ python (และ sh เป็นคนที่ชอบทำอะไรแบบนั้น)

1
อย่าดูเบาความสำคัญของความคล้ายคลึงกันกับ Java ซุนเพิ่งฟ้อง MS สำหรับพอร์ต JVM ของพวกเขาและได้รับคะแนนทางกฎหมายบางอย่าง (อย่างโง่เขลา IMHO) CIL และ CLR ได้รับแรงบันดาลใจจากสิ่งนั้นและคุณจะสังเกตเห็นว่า J # ใกล้เคียงกับ Java มากที่สุดโดยไม่ต้องดำเนินการทางกฎหมายเพิ่มเติม ความแตกต่างอย่างมากคือ CLR เป็นภาษาที่ไม่เชื่อเรื่องพระเจ้า คุณสามารถเขียนโปรแกรมในรูปแบบผสมของ C #, F # และ J # หากนั่นคือสิ่งที่จำเป็น เพียงลองผสม Java กับไลบรารีในภาษาอื่นและรับโปรแกรมที่เสถียร
— RBerteig

1
แต่การทำงานร่วมกันระหว่าง MSIL กับรหัสเนทีฟนั้นมีการกำหนดไว้อย่างดีและใช้งานได้ดี และเห็นได้ชัดว่าคาดว่าจะทำงานโดยการออกแบบและทัศนคติของชุมชนผู้ใช้
— RBerteig

12

Windows OS สามารถใช้งานได้กับซีพียูที่แตกต่างกันในปัจจุบันส่วนใหญ่เป็น x64, x86, Intel, ARM

CIL / CLR เป็นอิสระจากแพลตฟอร์มฮาร์ดแวร์นั้น - ความแตกต่างเหล่านี้ "แยกออกไป" โดยสภาพแวดล้อมการดำเนินการ IL ตัวอย่างเช่นแอสเซมบลี. NET ที่คอมไพล์แล้วสำหรับ "CPU ใด ๆ " โดยทั่วไปสามารถดำเนินการบน Win64 เป็นกระบวนการ 64 บิตและ Win32 เป็นกระบวนการ 32 บิตโดยไม่จำเป็นต้องมีไฟล์ปฏิบัติการที่แตกต่างกัน

ยิ่งไปกว่านั้น CIL ยังอนุญาตให้จัดเก็บข้อมูลเมตาในแอสเซมบลีซึ่งไม่สามารถทำได้อย่างง่ายดายด้วย Native DLLs (เป็นไปได้แน่นอนว่า MS ทำได้ก่อนหน้านี้ด้วยคอมโพเนนต์ COM ทำให้การสร้างส่วนประกอบซอฟต์แวร์นั้นง่ายขึ้นและเป็นรากฐานของการไตร่ตรอง / วิปัสสนาในภาษา. NET ทั้งหมด


เพียงเพิ่มบิตนี้ไม่เพียง แต่อนุญาตประเภท CPU ที่แตกต่างกัน แต่ยังมีรุ่นที่แตกต่างกัน (Core i3 / i5 / i7) และผู้ขาย (Intel vs. AMD) ภายในประเภท CPU เดียวกัน (เช่น x64 ทั้งหมด) อาจมีความแตกต่างกัน ชุดคำสั่งแอสเซมบลีซึ่ง JIT คอมไพเลอร์จะสามารถใช้ประโยชน์ได้
— DXM

2
@DXM: และคุณรู้ว่า JIT ทำจริงหรือ หรือนี่เป็นเรื่องสมมุติมากกว่านี้หรือ
— Doc Brown

อย่างน้อยบล็อก MSDN อ้างว่าคอมไพเลอร์ JIT ทำเช่นนั้น (หรือเมื่อ 8 ปีที่แล้ว)

@DocBrown: เห็นได้ชัดว่าฉันไม่มีเอกสารอ้างอิงใด ๆ อยู่ในมือ แต่ฉันคิดว่าฉันจำได้ว่าอ่านอะไรบางอย่างเกี่ยวกับเรื่องนี้มานานแล้ว ขอบคุณ delnan สำหรับการค้นหาลิงก์ มันจะสมเหตุสมผลเพราะเรารู้ว่าผู้ผลิตชิปต้องการเพิ่มคำแนะนำของตัวเองบนมาตรฐาน x86-x64 ดังนั้นหากเครื่องสามารถใช้ประโยชน์ได้ทำไมจะไม่ได้?
— DXM
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.