เหตุใด C จึงเร็วและทำไมภาษาอื่นไม่เร็วหรือเร็วกว่า [ปิด]


208

ในการฟังพอดคาสต์ StackOverflow การกระทุ้งทำให้เกิดขึ้นว่า "โปรแกรมเมอร์จริง" เขียนใน C และ C เร็วขึ้นเพราะมัน "ใกล้กับเครื่อง" ออกจากการยืนยันเดิมสำหรับโพสต์อื่นอะไรเป็นพิเศษเกี่ยวกับ C ที่ช่วยให้มันเร็วกว่าภาษาอื่น ๆ ? หรือใช้วิธีอื่น: อะไรจะหยุดภาษาอื่นไม่ให้สามารถคอมไพล์ลงไปสู่ไบนารี่ที่ทำงานได้เร็วเท่ากับ C?


6
คุณสามารถแสดงรายการที่ได้พูดคุยเกี่ยวกับเรื่องนี้ ฉันชอบที่จะได้ยินมัน
Giovanni Galbo

2
แปลกใจจริง ๆ ที่คำถามนี้ตอบอย่างไรไม่ดี (คำตอบส่วนใหญ่ไม่สนใจความแตกต่างพื้นฐานระหว่างภาษาที่แปลและตีความ ฯลฯ ฉันรู้เกี่ยวกับ JIT yada yada yada yada) และมีกี่คนที่รับตำแหน่ง 'ปกป้อง' ภาษา fave ของพวกเขา กินยา)
ทิมริง

อย่าลืมภาษาแอสเซมบลี ไม่มีอะไรเร็วกว่าหรือมีขนาดกะทัดรัดกว่า exes ที่ประกอบขึ้น แอสเซมบลีเป็นไบนารีที่เกือบจะบริสุทธิ์
KKZiomek

3
C เร็วที่สุดเพราะความเร็วแสงและสัมพัทธภาพคืออะไร?
พบกับ Taraviya

แน่นอนว่าผิด C คือภาษาโปรแกรมที่เร็วที่สุด ไม่มีภาษาโปรแกรมใด ๆ ใกล้เคียงกับความเร็วของ FORTH FORTH ใช้เพื่อจุดชนวนระเบิดนิวเคลียร์เป็นภาษาโปรแกรมบนดาวเทียมส่วนใหญ่ภาษาโปรแกรมหลักในสถานีอวกาศนานาชาติและใน CERN และที่ ITER ฉันเปรียบเทียบความเร็วระหว่าง Microsoft C (รุ่นต่าง ๆ ) กับ FORTH YAWN ถึง C ...
Scoobeedo Cool

คำตอบ:


200

มีไม่มากที่พิเศษเกี่ยวกับ C. นั่นเป็นเหตุผลหนึ่งที่ทำให้รวดเร็ว

ภาษาที่ใหม่กว่าที่มีการสนับสนุนสำหรับการเก็บขยะ , พิมพ์แบบไดนามิกและสิ่งอำนวยความสะดวกอื่น ๆ ที่ทำให้มันง่ายสำหรับโปรแกรมเมอร์ที่จะเขียนโปรแกรม

การจับคือมีการประมวลผลเพิ่มเติมซึ่งจะลดประสิทธิภาพของแอปพลิเคชัน C ไม่มีสิ่งใด ๆ ซึ่งหมายความว่าไม่มีค่าใช้จ่าย แต่นั่นหมายความว่าโปรแกรมเมอร์ต้องสามารถจัดสรรหน่วยความจำและทำให้หน่วยความจำว่างเพื่อป้องกันการรั่วไหลของหน่วยความจำและต้องจัดการกับการพิมพ์ตัวแปรแบบคงที่

ที่กล่าวว่าหลายภาษาและแพลตฟอร์มเช่น Java (กับJava Virtual Machine ) และ. NET (ด้วย Common Language Runtime) ได้ปรับปรุงประสิทธิภาพการทำงานในช่วงหลายปีที่ผ่านมาด้วยการให้คำแนะนำเช่นการรวบรวมแบบทันเวลาซึ่งสร้างรหัสเครื่องดั้งเดิมจาก bytecode เพื่อให้ได้ประสิทธิภาพที่สูงขึ้น


3
การรวบรวมขยะสามารถทำได้เร็วกว่าการจัดการหน่วยความจำด้วยตนเอง (สำหรับโปรแกรมระยะสั้นและ / หรือหน่วยความจำมากมาย) GC ช่วยให้การจัดสรรง่ายและรวดเร็วและโปรแกรมไม่ใช้เวลาจัดสรรคืนสิ่งต่าง ๆ
Kornel

2
โดยทั่วไปแล้วโปรแกรม C จะจัดสรรและยกเลิกการจัดสรรหน่วยความจำตามความจำเป็น สิ่งนี้ไม่มีประสิทธิภาพ VM ที่ดีจะจัดสรรและยกเลิกการจัดสรรในกลุ่มก้อนขนาดใหญ่ซึ่งให้ประสิทธิภาพที่เพิ่มขึ้นอย่างมากในหลายกรณี
skaffman

60
ไม่มีอะไรที่ป้องกันไม่ให้โปรแกรม C ทำการจัดสรรแบบ chunked และการรวบรวมขยะแบบเดียวกันนอกเหนือจากการ "ยาก"
ephemient

พูดได้ดีมาก แต่ชอบ Rob Allen กล่าวว่า C ยังให้สิ่งที่เป็นนามธรรมน้อยกว่า Java หรือ. NET ทำให้มีการแปลน้อยลง (ซึ่งไม่เป็นความจริงในวันนี้เนื่องจากการคอมไพล์แบบทันเวลาพอดี)
Gab Royer

5
porneL การจัดการด้วยตนเองและการจัดสรรที่เหมาะสมจะมีประสิทธิภาพเหนือกว่าระบบ GC ใด ๆ เมื่อใช้อย่างถูกต้องและให้ความสนใจอย่างมากคุณมีความรู้อย่างสมบูรณ์เกี่ยวกับรูปแบบการใช้งานของคุณ GC ไม่ได้บวกกับระบบ GC เพิ่มค่าใช้จ่าย
Ion Todirel

89

มีการแลกเปลี่ยนกับนักออกแบบ C พวกเขาตัดสินใจที่จะเพิ่มความเร็วเหนือความปลอดภัย C จะไม่

  • ตรวจสอบขอบเขตดัชนีอาร์เรย์
  • ตรวจสอบค่าตัวแปรที่ไม่ได้เตรียมการ
  • ตรวจสอบรอยรั่วหน่วยความจำ
  • ตรวจสอบการอ้างถึงตัวชี้โมฆะ

เมื่อคุณทำดัชนีในอาเรย์ใน Java จะใช้การเรียกเมธอดในเครื่องเสมือนการตรวจสอบที่ถูกผูกไว้และการตรวจสอบสติอื่น ๆ นั่นถูกต้องและไม่เป็นไรเพราะมันเพิ่มความปลอดภัยในที่ที่มันถึงกำหนด แต่ใน C แม้สิ่งเล็กน้อยที่น่ารักก็ไม่ได้อยู่ในความปลอดภัย ตัวอย่างเช่น C ไม่ต้องการ memcpy เพื่อตรวจสอบว่าขอบเขตที่จะคัดลอกทับซ้อนกันหรือไม่ มันไม่ได้ออกแบบมาเป็นภาษาในการเขียนโปรแกรมสำหรับธุรกิจขนาดใหญ่

แต่เหล่านี้ตัดสินใจออกแบบไม่ได้เป็นโรคจิตในภาษา C พวกเขาได้รับการออกแบบเนื่องจากช่วยให้คอมไพเลอร์และนักเขียนห้องสมุดได้รับประสิทธิภาพการใช้งานคอมพิวเตอร์ นี่คือจิตวิญญาณของ C ว่าเอกสารเหตุผล Cอธิบาย:

รหัส C สามารถไม่ใช่พกพาได้ แม้ว่าจะพยายามเปิดโอกาสให้โปรแกรมเมอร์เขียนโปรแกรมแบบพกพาอย่างแท้จริง แต่คณะกรรมการก็ไม่ต้องการบังคับให้โปรแกรมเมอร์เขียนโปรแกรมแบบพกพาเพื่อป้องกันการใช้ C เป็นแอสเซมเบลอร์ระดับสูงในการเขียนโปรแกรม รหัสเป็นหนึ่งในจุดแข็งของซี

รักษาจิตวิญญาณของ C.คณะกรรมการเก็บรักษาไว้เป็นเป้าหมายสำคัญในการรักษาจิตวิญญาณดั้งเดิมของ C มีหลายแง่มุมของวิญญาณของ C แต่สาระสำคัญคือความเชื่อมั่นของชุมชนของหลักการพื้นฐานซึ่งเป็นภาษา C บางแง่มุมของวิญญาณของ C สามารถสรุปในวลีเช่น

  • เชื่อถือโปรแกรมเมอร์
  • อย่าป้องกันโปรแกรมเมอร์จากการทำสิ่งที่ต้องทำ
  • ทำให้ภาษามีขนาดเล็กและเรียบง่าย
  • ให้วิธีเดียวเท่านั้นในการดำเนินการ
  • ทำให้รวดเร็วแม้ว่าจะไม่รับประกันว่าจะพกพาได้ก็ตาม

ภาษิตสุดท้ายต้องการคำอธิบายเล็กน้อย ศักยภาพในการสร้างรหัสที่มีประสิทธิภาพเป็นหนึ่งในจุดแข็งที่สำคัญที่สุดของ C เพื่อช่วยให้แน่ใจว่าไม่มีการระเบิดของรหัสสำหรับสิ่งที่ดูเหมือนจะเป็นการดำเนินการที่ง่ายมากการดำเนินการหลายอย่างถูกกำหนดไว้ว่าฮาร์ดแวร์ของเครื่องเป้าหมายนั้นเป็นอย่างไร กฎนามธรรมทั่วไป ตัวอย่างของความเต็มใจที่จะอยู่กับสิ่งที่เครื่องสามารถเห็นได้ในกฎที่ควบคุมการขยายวัตถุถ่านเพื่อใช้ในการแสดงออกว่าค่าของวัตถุวัตถุกว้างขึ้นเป็นปริมาณลงนามหรือไม่ได้ลงนามขึ้นอยู่กับการดำเนินงานไบต์ ประสิทธิภาพบนเครื่องเป้าหมาย


51
C จะตรวจสอบตัวชี้โมฆะ deref โดย crashing อย่างรุนแรง :-) นอกจากนี้ยังตรวจสอบดัชนีอาร์เรย์ที่ไม่อยู่ในขอบเขตและตัวแปรที่ไม่ได้กำหนดค่าเริ่มต้นด้วยการทำให้เฟรมสแต็กและข้อมูลของคุณแย่ลง น่าเสียดายที่มันตรวจสอบสิ่งเหล่านี้เมื่อรันไทม์
paxdiablo

18
ฉันจะไม่พูดว่า C ไม่ปลอดภัยซึ่งดูเหมือนว่าคุณกำลังพูดถึงอยู่ มันถือว่าคุณไม่ใช่คนงี่เง่า หากคุณเล็งปืนลงและยิงตัวเองที่เท้า C จะมีความสุขและยอมให้คุณทำอย่างนั้นเพราะมันจะถือว่าคุณฉลาดกว่าที่เป็นอยู่ นั่นไม่จำเป็นต้องเป็นสิ่งที่ไม่ดี
46775 Bob Bob

19
@Bob: แน่นอน การบอกว่า C ไม่ปลอดภัยเพราะมันช่วยให้คุณทำสิ่งที่อันตรายเหมือนการบอกว่ารถไม่ปลอดภัยเพราะมันจะช่วยให้คุณขับรถออกจากหน้าผา C ปลอดภัยเหมือนกับคนที่ขับรถ (แต่มีคนขับรถที่ไม่ปลอดภัยอยู่มากมาย)
Robert Gamble

5
บ๊อบการสร้างบั๊กอย่างบัฟเฟอร์ล้นไม่ได้แปลว่าคุณเป็นคนงี่เง่า หมายความว่าคุณยังเป็นมนุษย์อยู่ ฉันรู้ว่า C และ C ++ ไม่เลว (ฉันชอบพวกเขามาก)
Johannes Schaub - litb

4
@ JohannesSchaub-litb C เหมาะสำหรับการเขียนโปรแกรมประยุกต์ขนาดใหญ่ หากพบว่ามันยากที่จะทำโครงการที่ใหญ่กว่าโลกสวัสดีปัญหาก็คือกับโปรแกรมเมอร์ไม่ใช่ภาษา ...

75

หากคุณใช้เวลาหนึ่งเดือนในการสร้างบางสิ่งบางอย่างใน C ที่ทำงานใน 0.05 วินาทีและฉันใช้เวลาหนึ่งวันในการเขียนสิ่งเดียวกันใน Java และมันทำงานใน 0.10 วินาทีแล้ว C เร็วขึ้นจริงหรือ

แต่ในการตอบคำถามของคุณรหัส C ที่เขียนดีจะทำงานเร็วกว่าโค้ดที่เขียนดีในภาษาอื่นเพราะส่วนหนึ่งของการเขียนรหัส C "ดี" รวมถึงการปรับแต่งด้วยตนเองในระดับใกล้เครื่อง

ถึงแม้ว่าคอมไพเลอร์จะฉลาดมาก แต่ก็ยังไม่สามารถสร้างโค้ดที่แข่งขันกับอัลกอริทึมที่นวดด้วยมือได้ (สมมติว่า "มือ" เป็นของดีโปรแกรมเมอร์ C )

แก้ไข:

ความคิดเห็นจำนวนมากอยู่ในแนวของ "ฉันเขียนใน C และฉันไม่คิดเกี่ยวกับการปรับให้เหมาะสม"

แต่เพื่อนำตัวอย่างเฉพาะจากโพสต์นี้ :

ใน Delphi ฉันสามารถเขียนสิ่งนี้:

function RemoveAllAFromB(a, b: string): string;
var
  before, after :string;
begin
  Result := b;
  if 0 < Pos(a,b) then begin
    before := Copy(b,1,Pos(a,b)-Length(a));
    after := Copy(b,Pos(a,b)+Length(a),Length(b));
    Result := before + after;
    Result := RemoveAllAFromB(a,Result);  //recursive
  end;
end;

และใน CI เขียนสิ่งนี้:

char *s1, *s2, *result; /* original strings and the result string */
int len1, len2; /* lengths of the strings */
for (i = 0; i < len1; i++) {
   for (j = 0; j < len2; j++) {
     if (s1[i] == s2[j]) {
       break;
     }
   }
   if (j == len2) {  /* s1[i] is not found in s2 */
     *result = s1[i]; 
     result++; /* assuming your result array is long enough */
   }
}

แต่ในรุ่น C มีการปรับแต่งให้เหมาะสมกี่อัน? เราทำการตัดสินใจมากมายเกี่ยวกับการใช้งานที่ฉันไม่ได้คิดถึงในเวอร์ชัน Delphi สตริงใช้งานอย่างไร? ใน Delphi ฉันไม่เห็นมัน ใน C ฉันตัดสินใจแล้วว่ามันจะเป็นตัวชี้ไปยังอาร์เรย์ของจำนวนเต็ม ASCII ซึ่งเราเรียกว่า chars ใน C เราทดสอบการมีอยู่ของตัวละครทีละตัว ใน Delphi ฉันใช้ Pos

และนี่เป็นเพียงตัวอย่างเล็ก ๆ ในโปรแกรมขนาดใหญ่โปรแกรมเมอร์ C ต้องทำการตัดสินใจระดับต่ำเหล่านี้ด้วยโค้ดสองสามบรรทัด มันเพิ่มขึ้นเป็นปฏิบัติการที่สร้างขึ้นด้วยมือและเพิ่มประสิทธิภาพมือ


45
เพื่อความเป็นธรรมแม้ว่าจะมีไม่มากที่จะใช้เวลาหนึ่งเดือนใน C ที่จะใช้เวลาเพียงหนึ่งวันใน Java ที่ใช้เวลาเพียง 0.05 วินาทีในการดำเนินการ (เช่นโปรแกรมขนาดเล็ก)
dreamlax

12
ฉันตั้งโปรแกรมเป็นภาษา C มาหลายปีแล้วและแทบจะไม่ต้องทำอะไรอีกในการเพิ่มประสิทธิภาพที่คุณแนะนำ ฉันได้ย้ายโปรแกรมจำนวนหนึ่งไปยัง C (ส่วนใหญ่มาจาก Perl) และโดยทั่วไปจะเห็นการเพิ่มความเร็ว 10x บวกและการลดการใช้หน่วยความจำอย่างมีนัยสำคัญโดยไม่ต้องใช้การปรับรหัสด้วยมือ
โรเบิร์ต Gamble

1
แน่นอนว่ามีบางสิ่งที่สามารถใช้เวลานานกว่าในการเขียนโปรแกรม C เนื่องจากขาดสิ่งอำนวยความสะดวกที่มีอยู่ดังนั้นมันเป็นการแลกเปลี่ยนระหว่างประสิทธิภาพของคอมพิวเตอร์และประสิทธิภาพของโปรแกรมเมอร์ (เหนือสิ่งอื่นใด) ซึ่งเป็นเหตุผลว่า
โรเบิร์ต Gamble

4
ฉันได้สร้างโปรแกรม C ++ ที่ประมวลผลข้อมูลหลายพันบรรทัดในเวลาที่น้อยลงจากนั้นโปรแกรม Java หรือ. NET สามารถเริ่มต้นได้ มันเป็นหนึ่งในความผิดหวังที่ฉันมีกับภาษาที่ทันสมัยมากขึ้น C เหมาะสำหรับโปรแกรมแบบลีนที่ต้องการความต้องการรันไทม์น้อยที่สุด PowerBasic นั้นยอดเยี่ยมสำหรับสิ่งนั้น
bruceatk

35
คุณกำลังบอกว่าโปรแกรมที่ใช้เวลาหนึ่งเดือนใน C และเร็วกว่าโปรแกรมที่เขียนใน Java ซึ่งใช้เวลาเพียงวันเดียวในการเขียนไม่คุ้มค่าใช่หรือไม่ เกิดอะไรขึ้นถ้าโปรแกรมนั้นต้องการเรียกใช้ 500,000,000+ ครั้งต่อวัน การเป็นสองเท่าของความเร็วนั้นสำคัญมากอย่างไม่น่าเชื่อ หากใช้กับซีพียูหลายพันหรือหลายล้านเครื่องการประหยัดค่าใช้จ่ายในการพัฒนาเดือนพิเศษเพื่อให้ได้ประสิทธิภาพเพิ่มขึ้นเป็นสองเท่า โดยทั่วไปคุณต้องรู้ / เข้าใจขนาดของการปรับใช้ของคุณก่อนที่คุณจะเลือกแพลตฟอร์มการพัฒนา
nicerobot

49

ฉันไม่เห็นมันอยู่แล้วดังนั้นฉันจะบอกว่ามัน: C มีแนวโน้มที่จะได้เร็วขึ้นเพราะเกือบทุกอย่างอื่นจะเขียนใน C

Java สร้างขึ้นบน C, Python สร้างขึ้นบน C (หรือ Java, หรือ. NET ฯลฯ ), Perl คือ, ฯลฯ ระบบปฏิบัติการเขียนใน C, เครื่องเสมือนเขียนด้วย C, คอมไพเลอร์เขียนด้วย C, ล่ามเขียนด้วยภาษาซีบางสิ่งยังคงเขียนในภาษาแอสเซมบลีซึ่งมีแนวโน้มที่จะเร็วยิ่งขึ้น มีการเขียนสิ่งอื่นมากขึ้นเรื่อย ๆ ซึ่งเขียนด้วยภาษาซี

แต่ละคำสั่งที่คุณเขียนในภาษาอื่น (ไม่ใช่แอสเซมบลี) โดยทั่วไปแล้วจะมีการนำไปใช้ภายใต้คำสั่งต่าง ๆ ใน C ซึ่งถูกรวบรวมเป็นรหัสเครื่องดั้งเดิม เนื่องจากภาษาอื่น ๆ เหล่านั้นมีแนวโน้มที่จะมีความเป็นนามธรรมสูงกว่าภาษาซีดังนั้นข้อความพิเศษที่จำเป็นในภาษาซีจึงมุ่งเน้นไปที่การเพิ่มความปลอดภัยเพิ่มความซับซ้อนและการจัดการข้อผิดพลาด เหล่านี้คือสิ่งที่มักจะดี แต่พวกเขามีค่าใช้จ่ายและชื่อที่มีความเร็วและขนาด

โดยส่วนตัวแล้วฉันเขียนเป็นภาษาต่าง ๆ นับสิบภาษาซึ่งครอบคลุมสเปคตรัมส่วนใหญ่ที่มีอยู่และโดยส่วนตัวแล้วฉันได้เสาะหาเวทย์มนตร์ที่คุณพูดถึง:

ฉันจะมีเค้กและกินได้อย่างไร ฉันจะเล่นกับ abstractions ระดับสูงในภาษาที่ฉันโปรดปรานได้อย่างไรจากนั้นดรอปลงไปที่ nitty gritty ของ C เพื่อความเร็ว

หลังจากการวิจัยสองสามปีคำตอบของฉันคือ Python (บน C) คุณอาจต้องการที่จะให้มันดู อย่างไรก็ตามคุณสามารถเลื่อนลงไปที่ Assembly จาก Python ได้เช่นกัน (ด้วยความช่วยเหลือเล็กน้อยจากไลบรารี่พิเศษ)

บนมืออื่น ๆ , รหัสที่ไม่ดีสามารถเขียนในภาษาใดดังนั้นรหัส C (หรือชุดประกอบ) จึงไม่เร็วขึ้นโดยอัตโนมัติ เทคนิคการปรับให้เหมาะสมบางอย่างสามารถนำบางส่วนของรหัสภาษาระดับสูงขึ้นมาใกล้เคียงกับระดับประสิทธิภาพของ C ดิบ แต่สำหรับแอปพลิเคชันส่วนใหญ่โปรแกรมของคุณใช้เวลาส่วนใหญ่ในการรอคนหรือฮาร์ดแวร์ดังนั้นความแตกต่างไม่สำคัญ

สนุก.


10
สิ่งนี้ไม่ได้ใช้กับภาษาที่คอมไพล์ด้วย JIT ไม่ใช่ว่า C # ของฉันจะถูกรวบรวมเป็น IL ซึ่งแปลเป็น C ซึ่งถูกคอมไพล์เป็นรหัสเครื่อง ไม่ได้ IL นั้นรวบรวมโดย JIT และภาษาการใช้งานของ JIT นั้นไม่เกี่ยวข้องในตอนนั้น มันเป็นเพียงการสร้างรหัสเครื่อง
Jon Skeet

3
พระเจ้าห้ามไม่ให้ฉันถามคำถาม Jon Skeet ในตำนาน แต่ดูเหมือนว่าจะเกี่ยวข้องกับรหัสเครื่องที่ผลิตขึ้นสำหรับ C # แทนที่จะเป็น C ดังนั้นจึงเป็น "ระดับที่สูงกว่า" มีฟังก์ชั่นเพิ่มเติมมีการตรวจสอบความปลอดภัย ฯลฯ และจะ ดังนั้นจึงช้ากว่า "ที่เทียบเท่า" C.
Rob Williams

3
@ จอน: ฉันกำลังจะพูดอะไรที่คล้ายกัน แต่จุดนี้ค่อนข้างถูกต้องเพราะส่วนประกอบของไลบรารี. NET จำนวนมากถูกเขียนด้วยภาษา C จริงๆและมีข้อ จำกัด ความเร็วของ C มันจะน่าสนใจที่จะเห็นว่าสิ่งนี้จะเปลี่ยนแปลงในอนาคต
Konrad Rudolph

1
ดูเหมือนว่าวิธีที่ผิด ๆ ตัวแปลภาษา / ตัวแปล / vms อื่น ๆ มักจะเขียนบ่อย แต่ไม่ได้เขียนใน c (หรืออย่างน้อยสำหรับเลเยอร์ต่ำสุด) เพราะ c นั้นค่อนข้างเร็ว (และในหลาย ๆ กรณีนั้นเร็วที่สุด)
Roman A. Taycher

2
คำตอบนี้ไม่เป็นความจริง ตามที่กล่าวไว้ข้างต้นมันไม่ได้ใช้กับภาษา JIT แต่มันก็ไม่ได้ใช้กับภาษาที่มีคอมไพเลอร์ของตัวเองด้วย (ซึ่งหากใส่ความพยายามพิเศษเข้าไปในภาษาเหล่านั้น ภาษาอื่นที่เหลืออยู่เท่านั้นที่จะถูกตีความภาษาและที่ไม่ช้ากว่า C เพียงเพราะพวกเขาเขียนใน C เอง แต่เนื่องจากค่าใช้จ่ายของการตีความไม่ว่าคุณจะเชือดมันและแม้ว่าล่ามถูกเขียนในการชุมนุม มีขนาดใหญ่มาก
คะแนน _ ต่ำกว่า

38

มีคำถามมากมายในนั้น - คำถามส่วนใหญ่ที่ฉันไม่มีคุณสมบัติที่จะตอบ แต่สำหรับอันสุดท้ายนี้:

สิ่งที่จะหยุดภาษาอื่น ๆ จากการไม่สามารถรวบรวมลงในไบนารีที่ทำงานทุกบิตเร็วเท่า C

ในคำที่เป็นนามธรรม

C อยู่ห่างจากภาษาเครื่องเพียงหนึ่งหรือสองระดับเท่านั้น ภาษา Java และ. Net อยู่ห่างจากแอสเซมเบลอร์อย่างน้อย 3 ระดับ ฉันไม่แน่ใจเกี่ยวกับ Python และ Ruby

โดยทั่วไปของเล่นโปรแกรมเมอร์เพิ่มเติม (ชนิดข้อมูลที่ซับซ้อน ฯลฯ ) ยิ่งคุณมาจากภาษาเครื่องและต้องมีการแปลมากขึ้น

ฉันอยู่ที่นี่และนั่น แต่นั่นคือส่วนสำคัญพื้นฐาน

อัปเดต ------- มีความคิดเห็นดีๆเกี่ยวกับโพสต์นี้พร้อมรายละเอียดเพิ่มเติม


3
ในทางเทคนิคแล้ว Java และ. Net ถูกแยกออกจากภาษาเครื่องของเครื่องที่ทำงาน พวกเขาทำงานใน VMs ถึงแม้จะมี JIT รหัสดั้งเดิมจะต้องได้รับการนวดอย่างหนาแน่นเพื่อให้ได้สิ่งที่คล้ายกับรหัสเครื่องดั้งเดิม
jmucchiello

1
. net รหัสไม่ทำงานใน VM มันทำงานตามคำแนะนำดั้งเดิมบนแพลตฟอร์มตัวประมวลผลใด ๆ ก็ตามที่ทำงานอยู่ (32-bit x86, 64-bit x86 หรือ IA64)
Robert C. Barth

11
@ Robert: .net ไม่ใช้ VM รหัส. net ได้รับการรวบรวมเป็น bytecode ซึ่งดำเนินการโดย VM VM แปลง bytecode เป็นคำสั่งพื้นฐานในขณะใช้งาน
Robert Gamble

3
มันมากสิ่งสำคัญที่จะทราบว่าชวาและนามธรรมภาษา OO อื่น ๆ ที่มีชุดคำสั่งประมวลผลได้รับผลกระทบ โปรเซสเซอร์รุ่นใหม่มีคำแนะนำที่ทำให้ Java ทำงานได้เร็วขึ้นหาก java VM รู้เกี่ยวกับการปรับให้เหมาะสมเหล่านี้และใช้มัน มันไม่ใหญ่มาก แต่ก็มีประโยชน์
Adam Davis

1
อาจจะเป็น ThumbEE en.wikipedia.org/wiki/…
Roman A. Taycher

35

มันไม่ได้มากว่าซีเป็นเร็วที่สุดเท่าที่ราคาทุนของ C มีความโปร่งใส หากโปรแกรม C ช้ามันจะช้าในวิธีที่ชัดเจน: โดยดำเนินการคำสั่งจำนวนมาก เมื่อเทียบกับค่าใช้จ่ายในการดำเนินงานใน C การดำเนินงานระดับสูงบนวัตถุ (โดยเฉพาะอย่างยิ่งการสะท้อน) หรือสตริงสามารถมีค่าใช้จ่ายที่ไม่ชัดเจน

สองภาษาที่มักจะรวบรวมไบนารีซึ่งเป็นเพียงที่เร็วที่สุดเท่าที่ซีมีมาตรฐาน ML (โดยใช้MLtonคอมไพเลอร์) และCaml วัตถุประสงค์ หากคุณตรวจสอบเกมการวัดประสิทธิภาพคุณจะพบว่าสำหรับการวัดประสิทธิภาพบางอย่างเช่นต้นไม้ไบนารีรุ่น OCaml นั้นเร็วกว่า C. (ฉันไม่พบรายการ MLton ใด ๆ ) แต่อย่ายิงอย่างจริงจังเกินไป มันเป็นเกมที่บอกว่าผลลัพธ์มักสะท้อนถึงความพยายามของผู้คนในการปรับแต่งรหัส


เป็นไปได้ที่จะเขียนโค้ดที่ไม่แพงอย่างเห็นได้ชัดในภาษาใด ๆ เป็นเพียงว่าในบางภาษาคุณต้องเขียนตัวแปรภายในของ Lisp หรือ Forth ก่อน ...
Donal Fellows

สนิมยังตรงกับ C ในมาตรฐาน
สิ้นเชิง

18

C ไม่ได้เร็วขึ้นเสมอไป

C ช้ากว่าเช่น Modern Fortran

C มักจะช้ากว่า Java สำหรับบางสิ่ง (โดยเฉพาะอย่างยิ่งหลังจากคอมไพเลอร์ JIT ได้ไปที่รหัสของคุณ)

C อนุญาตให้ใช้นามแฝงตัวชี้เกิดขึ้นซึ่งหมายความว่าการเพิ่มประสิทธิภาพที่ดีบางอย่างไม่สามารถทำได้ โดยเฉพาะอย่างยิ่งเมื่อคุณมีหน่วยดำเนินการหลายหน่วยทำให้ข้อมูลดึงแผงขายออก โอ๊ย.

การสันนิษฐานว่าตัวชี้การคำนวณทางคณิตศาสตร์ทำให้ประสิทธิภาพการทำงานช้าลงอย่างช้าๆในตระกูล CPU บางตัว (PIC โดยเฉพาะ!) มันใช้เพื่อดูดซับค่าขนาดใหญ่ใน x86 ที่แบ่งกลุ่ม

โดยทั่วไปเมื่อคุณได้รับหน่วยเวกเตอร์หรือคอมไพเลอร์แบบขนาน C stinks และ Fortran ที่ทันสมัยทำงานได้เร็วขึ้น

เทคนิคการเขียนโปรแกรม C เช่นการ thunking (การแก้ไขไฟล์เรียกทำงานแบบลอยตัว) ทำให้เกิดการดึงแผง CPU ล่วงหน้า

คุณได้รับการเลื่อน?

และเพื่อนที่ดีของเรา x86 ดำเนินการชุดคำสั่งที่วันนี้มีความสัมพันธ์เล็กน้อยกับสถาปัตยกรรม CPU จริง การลงทะเบียน Shadow, ตัวเพิ่มประสิทธิภาพการจัดเก็บโหลดทั้งหมดใน CPU ดังนั้น C จึงอยู่ใกล้กับโลหะเสมือนจริง โลหะจริง Intel ไม่อนุญาตให้คุณเห็น (ในอดีต VLIW CPU นั้นค่อนข้างจะงงอาจจะไม่แย่นัก)

หากคุณโปรแกรมใน C บน DSP ที่มีประสิทธิภาพสูง (อาจเป็น TI DSP?) คอมไพเลอร์จะต้องทำสิ่งที่ยุ่งยากเพื่อคลี่ C ออกจากหน่วยประมวลผลแบบขนานหลายตัว ดังนั้นในกรณี C ไม่ใกล้เคียงกับโลหะ แต่อยู่ใกล้กับคอมไพเลอร์ซึ่งจะทำการเพิ่มประสิทธิภาพโปรแกรมทั้งหมด แปลก.

และสุดท้ายซีพียูบางตัว (www.ajile.com) ใช้จาวาไบต์ในฮาร์ดแวร์ C จะเป็น PITA เพื่อใช้กับ CPU นั้น


1
เมื่อครั้งล่าสุดที่เขียน thunking ใน C คืออะไร? โมเดิร์น x86 เป็นอินเตอร์เฟซการออกแบบ RISC ส่วนใหญ่ แต่ที่มีน้อยจะทำอย่างไรกับ VLIW ...
Calyth

7
โพสต์ส่วนใหญ่ของคุณเพิกเฉยต่อการมีอยู่ของ C99 นอกจากนี้คอมไพเลอร์ C / C ++ จำนวนมากมีคีย์เวิร์ด C99 ที่ จำกัด (ทำให้แน่ใจว่าไม่มีการกำหนดนามแฝงตัวชี้) เป็นส่วนขยาย
Evan Teran

ฉันคิดว่าทุกคนกำลังติดตาม / เปลี่ยนไปตาม CWE / SANS อันดับสูงสุด 25 และหลีกเลี่ยงการสร้างการออกแบบใหม่ใน C. ดังนั้นจึงไม่มีทุ่งหญ้าสีเขียว C ดังนั้นน้อยถึง C99
ทิม Williscroft

2
คุณสามารถแสดงตัวอย่างเมื่อ c ช้ากว่า Fortenberry ที่ทันสมัยได้หรือไม่
อดัม

ฉันไม่แน่ใจว่ามีช่วงเวลาที่คอมไพเลอร์ C แข่งขันกันได้ดีกับคอมไพเลอร์ Fortran ที่ดีที่สุด แน่นอนว่ามีรหัสจำนวนมากที่คุณไม่ต้องการเขียนใน FORTRAN 77 (นับประสา 66) แต่มาตรฐาน Fortran ที่ผ่านมานั้นน่าพอใจยิ่งขึ้น
tfb

11

สิ่งที่จะหยุดภาษาอื่น ๆ จากการไม่สามารถรวบรวมลงในไบนารีที่ทำงานทุกบิตเร็วเป็น C

ไม่มีอะไร ภาษาสมัยใหม่เช่น Java หรือ. NET langs จะเน้นไปที่ประสิทธิภาพของโปรแกรมเมอร์มากกว่าประสิทธิภาพ ฮาร์ดแวร์ราคาถูกวันนี้ นอกจากนี้การรวบรวมการเป็นตัวแทนระดับกลางจะให้โบนัสมากมายเช่นความปลอดภัยความสะดวกในการพกพาเป็นต้น. NET CLR สามารถใช้ประโยชน์จากฮาร์ดแวร์ที่แตกต่างกัน - ตัวอย่างเช่นคุณไม่จำเป็นต้องปรับโปรแกรม / คอมไพล์ซ้ำด้วยตนเองเพื่อใช้ชุดคำสั่ง SSE


ฉันจะโต้แย้งการพกพาที่นี่ หากคุณต้องการรหัสพกพาจริงๆคุณจะเขียนเป็น C และไม่ใช้ภาษาอื่น เรามีรหัสที่ทำงานบนระบบปฏิบัติการประมาณ 25 ระบบ เริ่มต้นจาก DOS และ threadX และการตกแต่งบน Linux / XP แสดงให้ฉันภาษาที่สามารถทำเช่นนั้น :) อีก
Ilya

1
@Ilya ฉันไม่เห็นด้วย มันง่ายเหมือนการเขียนโค้ดที่ไม่สามารถพกพาได้ในซีลองดูสิว่ามันเจ็บปวดแค่ไหนที่พอร์ทถึง 64 บิต Bytecode langauges สามารถทำงานข้ามแพลตฟอร์มได้หากคุณมีล่าม bytecode ที่ถูกต้อง
Calyth

1
@IIya รหัส C แบบพกพาเป็น exeption มากกว่ากฎฉัน ported รหัส C ระหว่างแพลตฟอร์มฮาร์ดแวร์ / ซอฟต์แวร์ที่แตกต่างกันและรู้ว่ามันเป็นฝันร้าย
aku

แม้สำหรับคำ PC มันไม่ได้เป็นกรณี ดูความเป็นจริงที่สุดของแอพพลิเคชั่นข้ามแพลตฟอร์มที่เขียนด้วย c / c ++, เล็กน้อยใน java สำหรับการพัฒนาในระดับต่ำที่ฝังตัวก็ไม่มีอีกกรณี C เป็นภาษาที่พกพาได้จริงที่สุด
Ilya

@aku -> การเขียนโค้ดไม่ดีอาจเป็นหายนะฉันเห็นด้วย การเขียนโค้ดพกพาใน ADVANCE - C เป็นตัวเลือกที่ดีที่สุด ฉันจะบอกว่า C ++ เป็นตัวเลือก แต่ไปที่แพลตฟอร์มแบบฝังตัวคุณจะพบกับคอมไพเลอร์ C ที่ดีเสมอสำหรับ c ++ คุณอาจพบว่าตัวคุณไม่มีคอมไพเลอร์
Ilya

8

ปัจจัยหลักคือมันเป็นภาษาที่พิมพ์แบบคงที่และที่รวบรวมไปยังรหัสเครื่อง นอกจากนี้เนื่องจากเป็นภาษาระดับต่ำจึงไม่ทำสิ่งใดที่คุณไม่ได้บอก

นี่คือปัจจัยอื่น ๆ ที่อยู่ในใจ

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

ภาษาที่พิมพ์คงที่ส่วนใหญ่สามารถรวบรวมได้อย่างรวดเร็วหรือเร็วกว่า C โดยเฉพาะอย่างยิ่งหากพวกเขาสามารถตั้งสมมติฐานว่า C ไม่สามารถทำได้เนื่องจากตัวชี้สมนามเป็นต้น


ระดับต่ำ? ฉันเดาว่ามันเป็นความหมายสัมพัทธ์ตอนนี้เทียบกับ Java ใช่ แต่เทียบกับชุดประกอบไม่มี โพสต์ที่ดีได้ฉันคิด
Mark

คุณพูดถูก สิ่งที่ฉันหมายถึงคือมัน "อยู่ใกล้กับเครื่อง" และไม่ได้ช่วยให้คุณทำสิ่งต่าง ๆ เช่นการจัดการหน่วยความจำหรือการติดตามขนาดอาร์เรย์
Matthew Crumley

2
C เป็นภาษาระดับต่ำ C เป็นภาษาระดับต่ำเสมอ คุณแปลรหัส C ลงในแอสเซมเบลอร์ได้อย่างง่ายดาย
Robert C. Barth

2
@ Robert: C เคยถูกพิจารณาว่าเป็นภาษาระดับสูงเพราะเมื่อเทียบกับชุดประกอบ (ซึ่งเป็นเรื่องธรรมดามาก) ก็เป็นได้ มันถือว่าเป็นภาษาระดับต่ำเมื่อเทียบกับภาษาส่วนใหญ่ที่ใช้ในปัจจุบัน
Robert Gamble

สุจริตนี่เป็นคำตอบที่ลำเอียงมาก ประณามใกล้กับโปรแกรมเมอร์ C ทุกคนทำการตรวจสอบอย่าง จำกัด ฯลฯ แต่ C ก็ยังเร็วกว่า C ++ มาก
MarcusJ

8

ฉันเดาว่าคุณลืมว่าภาษาแอสเซมบลีก็เป็นภาษาเดียวกันด้วย :)

แต่อย่างจริงจังโปรแกรม C จะทำงานได้เร็วขึ้นก็ต่อเมื่อโปรแกรมเมอร์รู้ว่าเขากำลังทำอะไรอยู่ คุณสามารถเขียนโปรแกรม C ที่รันช้ากว่าโปรแกรมที่เขียนในภาษาอื่นที่ทำงานเดียวกันได้อย่างง่ายดาย

เหตุผลที่ C เร็วขึ้นก็เพราะว่ามันถูกออกแบบในลักษณะนี้ มันช่วยให้คุณทำสิ่งที่ "ระดับต่ำกว่า" มากมายที่ช่วยให้คอมไพเลอร์เพื่อเพิ่มประสิทธิภาพรหัส หรือเราจะบอกว่าคุณโปรแกรมเมอร์มีหน้าที่รับผิดชอบในการปรับรหัสให้เหมาะสม แต่บ่อยครั้งมันค่อนข้างยุ่งยากและมีข้อผิดพลาดได้ง่าย

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


3
แม้ว่าคุณจะเขียนโปรแกรมหนึ่งครั้งใน C และอีกครั้งใน Assembly, เวอร์ชั่น C อาจจะเร็วกว่าเพราะคอมไพเลอร์ฉลาดกว่าที่คุณเป็น
mk12

7

ส่วนใหญ่คำสั่ง C ทุกคำสั่งจะสอดคล้องกับคำสั่งแอสเซมเบลอร์น้อยมาก คุณกำลังเขียนรหัสเครื่องระดับสูงขึ้นเป็นหลักดังนั้นคุณสามารถควบคุมเกือบทุกสิ่งที่โปรเซสเซอร์ทำ ภาษาที่รวบรวมอื่น ๆ เช่น C ++ มีคำแนะนำง่ายๆในการค้นหาซึ่งสามารถเปลี่ยนเป็นรหัสได้มากกว่าที่คุณคิด (ฟังก์ชั่นเสมือน, ตัวสร้างสำเนา, ฯลฯ ) และภาษาที่แปลเช่น Java หรือ Ruby มีเลเยอร์อื่นของ คำแนะนำที่คุณไม่เคยเห็น - Virtual Machine หรือ Interpreter


และภาษาระดับสูงเหล่านี้มีความภาคภูมิใจในตัวเองว่าพวกเขาสามารถกำจัด cruft ส่วนใหญ่ที่เพิ่มเข้ามาได้ในตอนแรก สิ่งต่างๆเช่นการคัดลอกการเพิ่มประสิทธิภาพค่าตอบแทนย้ายการก่อสร้าง / การกำหนด ฯลฯ ใน C ++
cmaster - คืนสถานะโมนิก้า

ดังนั้นทุกอย่างจะลงมาที่จำนวนชุดคำสั่งที่สร้างขึ้นจากรหัส มีคำแนะนำในการประกอบเพิ่มเติมต่อบรรทัดของรหัสระดับสูงประสิทธิภาพการทำงานที่ทนทุกข์ทรมานมากขึ้น?
ENDEESA

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


7

c ++ เร็วกว่าโดยเฉลี่ย (เหมือนตอนแรกส่วนใหญ่เป็น superset C แม้ว่าจะมีความแตกต่างกันบ้าง) อย่างไรก็ตามสำหรับการวัดประสิทธิภาพที่เฉพาะเจาะจงมักจะมีภาษาอื่นที่เร็วกว่า

https://benchmarksgame-team.pages.debian.net/benchmarksgame/

fannjuch-redux เร็วที่สุดในสกาล่า

n-bodyและfastaเร็วขึ้นในอาดา

spectral-norm เร็วที่สุดใน Fortran

reverse-complement, mandelbrotและpidigitsเป็นเร็วที่สุดใน ATS

regex-dna เร็วที่สุดใน JavaScript

chameneou-redux เร็วที่สุดคือ Java 7

thread-ring เร็วที่สุดใน Haskell

ส่วนที่เหลือของการวัดประสิทธิภาพนั้นเร็วที่สุดใน C หรือ C ++


"เนื่องจากเป็นชุดสุดยอดของ C" - ไม่ C ++ ไม่ใช่ชุดของ C
PP

1
extern "C"ไม่มีอะไรเกี่ยวข้องกับ C ++ ที่จะเป็นsupersetของ C
PP

2
มันเหมือนกับการพูดว่าใช้system("bash script.sh");งานได้กับสคริปต์ทุบตีใด ๆ และด้วยเหตุนี้ C จึงเป็นชุดของการทุบตี extern "C"ให้การเชื่อมโยง C ใน C ++ เนื่องจากชื่อ mangling ในขณะที่การเรียก X เป็น superset ของ Y หมายถึงสิ่งที่สามารถทำได้ใน Y สามารถทำได้ใน X ซึ่งไม่เป็นความจริงของ C ++ มีโครงสร้างภาษาค่อนข้างน้อยที่ใช้ได้ใน C แต่ไม่ใช่ C ++
PP

1
@PP ไม่มีอะไรในมาตรฐาน C ++ ที่ได้รับคำสั่งว่าbashเป็นโปรแกรมบรรทัดคำสั่งที่มีอยู่ ถ้ามันทำและรวมรุ่น / สเปคของ bash ที่จำเป็นต้องได้รับการสนับสนุนฉันจะถือว่ามันเป็น superset
Peter Lawrey

1
มันง่ายมากที่จะเขียนรหัส C ที่ไม่ใช่รหัส C ++ เช่นstruct foo { int: this; }; typedef float foo;
Jasen

6

คำตอบหลายข้อให้เหตุผลที่ถูกต้องว่าทำไม C ถึงเป็นหรือไม่เร็วกว่า (โดยทั่วไปหรือในบางสถานการณ์) มันปฏิเสธไม่ได้ว่า:

  • ภาษาอื่น ๆ อีกมากมายให้คุณสมบัติอัตโนมัติที่เราได้รับอนุญาต การตรวจสอบขอบเขตการตรวจสอบชนิดรันไทม์และการจัดการหน่วยความจำอัตโนมัติไม่ได้มาฟรี อย่างน้อยก็มีบ้างค่าใช้จ่ายที่เกี่ยวข้องกับคุณสมบัติเหล่านี้ซึ่งเราอาจไม่ได้คิดหรือแม้แต่รู้ - ในขณะที่เขียนโค้ดที่ใช้คุณสมบัติเหล่านี้
  • ขั้นตอนจากแหล่งที่มาไปยังเครื่องมักจะไม่ตรงในภาษาอื่น ๆ เช่นเดียวกับใน C
  • OTOH ที่จะกล่าวว่ารหัส C ที่คอมไพล์แล้วนั้นรันได้เร็วกว่าโค้ดอื่น ๆ ที่เขียนในภาษาอื่น ๆ นั้นเป็นลักษณะทั่วไปที่ไม่เป็นความจริง ตัวอย่างเคาน์เตอร์หาง่าย (หรือโต้แย้ง)

ทั้งหมดนี้อย่างไรก็ตามมีบางสิ่งที่ฉันสังเกตเห็นว่าฉันคิดว่าส่งผลกระทบต่อประสิทธิภาพการเปรียบเทียบของ C กับภาษาอื่น ๆ อีกมากมายมากกว่าปัจจัยอื่น ๆ เพื่อปัญญา:

ภาษาอื่นมักจะทำให้การเขียนโค้ดง่ายขึ้นซึ่งช้าลง บ่อยครั้งที่มันได้รับการสนับสนุนจากปรัชญาการออกแบบของภาษา ผลที่ตามมา: โปรแกรมเมอร์ C มักจะเขียนโค้ดที่ไม่สามารถดำเนินการที่ไม่จำเป็นได้

ยกตัวอย่างเช่นพิจารณาโปรแกรม Windows อย่างง่ายที่สร้างหน้าต่างหลักเดียว รุ่น AC จะเติมWNDCLASS[EX]โครงสร้างที่จะถูกส่งไปRegisterClass[Ex]แล้วโทรCreateWindow[Ex]และเข้าสู่วงข้อความ รหัสที่ง่ายและง่ายมากดังต่อไปนี้:

WNDCLASS wc;
MSG      msg;

wc.style         = 0;
wc.lpfnWndProc   = &WndProc;
wc.cbClsExtra    = 0;
wc.cbWndExtra    = 0;
wc.hInstance     = hInstance;
wc.hIcon         = NULL;
wc.hCursor       = LoadCursor(NULL, IDC_ARROW);
wc.hbrBackground = (HBRUSH)(COLOR_BTNFACE + 1);
wc.lpszMenuName  = NULL;
wc.lpszClassName = "MainWndCls";

RegisterClass(&wc);

CreateWindow("MainWndCls", "", WS_OVERLAPPEDWINDOW | WS_VISIBLE,
             CW_USEDEFAULT, 0, CW_USEDEFAULT, 0, NULL, NULL, hInstance, NULL);

while(GetMessage(&msg, NULL, 0, 0)){
    TranslateMessage(&msg);
    DispatchMessage(&msg);
}

โปรแกรมที่เทียบเท่าใน C # อาจเป็นรหัสเดียว:

Application.Run(new Form());

โค้ดหนึ่งบรรทัดนี้มีฟังก์ชั่นทั้งหมดที่เกือบ 20 บรรทัดของโค้ด C ทำและเพิ่มบางสิ่งที่เราทิ้งไว้เช่นการตรวจสอบข้อผิดพลาด ห้องสมุดที่สมบูรณ์กว่านี้ (เมื่อเทียบกับที่ใช้ในโครงการ C ทั่วไป) ได้ทำงานให้เรามากมายทำให้เรามีเวลามากขึ้นในการเขียนโค้ดเพิ่มเติมอีกมากมายที่ดูสั้น แต่มีหลายขั้นตอนอยู่เบื้องหลัง

แต่ห้องสมุดที่อุดมด้วยการเปิดใช้งานการขยายโค้ดที่ง่ายและรวดเร็วไม่ใช่จุดของฉัน ประเด็นของฉันชัดเจนมากขึ้นเมื่อคุณเริ่มตรวจสอบสิ่งที่เกิดขึ้นจริงเมื่อดำเนินการหนึ่งซับของเราตัวเล็ก เพื่อความสนุกสนานในบางครั้งให้เปิดใช้งาน. NET access accessใน Visual Studio 2008 หรือสูงกว่าและเข้าสู่หนึ่งบรรทัดบรรทัดข้างต้น หนึ่งในอัญมณีเล็ก ๆ ที่สนุกที่คุณจะเจอคือความคิดเห็นในทะเยอทะยานสำหรับControl.CreateParams:

// In a typical control this is accessed ten times to create and show a control.
// It is a net memory savings, then, to maintain a copy on control.
// 
if (createParams == null) {
    createParams = new CreateParams(); 
} 

ครั้งที่สิบ ข้อมูลใกล้เคียงกับผลรวมของสิ่งที่เก็บไว้ในส่วนWNDCLASSEXโครงสร้างและสิ่งที่ผ่านไปCreateWindowExจะถูกดึงจากControlครั้งระดับสิบก่อนที่มันจะถูกเก็บไว้ในWNDCLASSEXโครงสร้างและการส่งผ่านไปยังและRegisterClassExCreateWindowEx

โดยรวมแล้วจำนวนคำสั่งที่ดำเนินการเพื่อดำเนินงานขั้นพื้นฐานนี้คือลำดับที่ 2-3 ของขนาดใน C # มากกว่าใน C ส่วนหนึ่งเป็นเพราะการใช้ไลบรารี่ที่มีคุณลักษณะหลากหลายซึ่งจำเป็นต้องมีการเปรียบเทียบกับทั่วไป รหัส C อย่างง่ายของเราซึ่งทำสิ่งที่เราต้องการอย่างแน่นอนและไม่มีอะไรเพิ่มเติม แต่ส่วนหนึ่งเป็นเพราะความจริงที่ว่าลักษณะเชิงวัตถุที่เป็นโมดูลของกรอบงาน. NET ทำให้เกิดการซ้ำซ้อนของการดำเนินการซึ่งมักจะหลีกเลี่ยงได้ด้วยวิธีการตามขั้นตอน

ฉันไม่ได้พยายามเลือก C # หรือ. NET Framework ไม่ฉันบอกว่าคุณสมบัติ modularization ลักษณะทั่วไปห้องสมุด / ภาษา OOP ฯลฯ เป็นสิ่งที่ไม่ดี ฉันเคยพัฒนาส่วนใหญ่ใน C ต่อมาใน C ++ และเมื่อเร็ว ๆ นี้ใน C # ในทำนองเดียวกันก่อน C ฉันใช้การชุมนุมเป็นส่วนใหญ่ และด้วยขั้นตอน "สูง" ในแต่ละภาษาของฉันฉันเขียนได้ดีขึ้นบำรุงรักษาได้ดีขึ้นและมีประสิทธิภาพมากขึ้นในเวลาที่น้อยลง อย่างไรก็ตามพวกเขามีแนวโน้มที่จะดำเนินการช้ากว่าเล็กน้อย


2
นั่นคือปัญหา API ไม่ใช่ปัญหาด้านภาษา
Arafangion

1
@Arafangion: ฉันเข้าใจสิ่งที่คุณพูด แต่มันก็พลาดจุด ไลบรารีที่มีคุณลักษณะหลากหลายเปิดใช้งาน (และเรียกร้องตาม) โดยภาษาที่มีคุณลักษณะหลากหลาย และไม่ใช่แค่ห้องสมุด ห้องสมุดเป็นเพียงตัวอย่างของการใช้งานทั่วไปของภาษา รหัสแอปพลิเคชันทั่วไปในภาษาใด ๆ โดยทั่วไปจะมีความคล้ายคลึงกับไลบรารีที่มักใช้ในภาษานั้น มันเป็นความคิดที่ส่งเสริมภาษา ตัวอย่างเช่นโดยทั่วไปภาษา OO จะใช้เวลาในการจัดสรรการสร้างทำลายและการจัดสรรคืนวัตถุมากกว่าภาษาที่มีการสนับสนุน OOP น้อยกว่า
Paddy

ฉันจะยอมรับว่าตัวเลือกภาษาที่กำหนดโดยทั่วไปหมายถึงแพลตฟอร์มและไลบรารีเฉพาะซึ่งเป็นเหตุผลที่ฉันทำความคิดเห็นนั้น (เพื่อให้ผู้อ่านจะได้รับการเตือนมากขึ้น) แต่ที่กล่าวว่าการใช้ (ตัวอย่าง) C ++ บน windows คือ เดรัจฉานแตกต่างกันมากในการพูด C ++ บน linux และแตกต่างอีกครั้งด้วย C ++ บน Android อีกตัวอย่างหนึ่งคือ Python เรามี CPython, Jython, PyPy และ IronPython ซึ่งทั้งหมดนี้ใช้ไลบรารีที่แตกต่างกันมาก
Arafangion

แต่การใช้ Pythons เหล่านี้นักพัฒนามักจะเขียนแอปพลิเคชันด้วยวิธีใดวิธีหนึ่ง ตัวอย่างเช่นพวกเขาอาจอ่านและเขียนจากไฟล์ข้อความสร้างวัตถุใหม่ด้วยข้อมูลที่พวกเขาอ่าน ใน C ในทางกลับกันนักพัฒนามีแนวโน้มที่จะทำการจัดสรรอาร์เรย์ของโครงสร้างหนึ่งครั้งและอ่านและเขียน struct เหล่านั้นจากไบนารีไฟล์ นี้เป็นของหลักสูตรเพียงตัวอย่างที่วางแผนไว้ว่าความพยายามที่จะแสดงให้เห็นถึงจุดฉันพยายามที่จะทำเกี่ยวกับความคิด
Paddy

6

ฉันไม่คิดว่าจะมีใครพูดถึงความจริงที่ว่ามีความพยายามมากมายในคอมไพเลอร์ C มากกว่าคอมไพเลอร์อื่น ๆ โดยอาจยกเว้น Java

C สามารถปรับให้เหมาะสมอย่างมากด้วยเหตุผลหลายประการที่กล่าวไว้แล้ว - มากกว่าภาษาอื่นเกือบทั้งหมด ดังนั้นหากมีการใส่ความพยายามลงในตัวแปลภาษาอื่นจำนวนเท่ากัน C อาจจะยังคงอยู่ในอันดับต้น ๆ

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

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

สิ่งสำคัญคือ (อย่างน้อยสำหรับฉัน) ว่ารหัสกรณีที่เลวร้ายที่สุดมีแนวโน้มที่จะรวดเร็ว มี "บทพิสูจน์" มากมายบนเว็บที่ Java เร็วหรือเร็วกว่า C แต่มีพื้นฐานมาจากตัวอย่างการเก็บเชอร์รี่ ฉันไม่ใช่แฟนตัวยงของ C แต่ฉันรู้ว่าสิ่งใดที่ฉันเขียนใน C จะทำงานได้ดี ด้วย Java มันจะ "ทำงาน" ได้ภายใน 15% ของความเร็วโดยปกติจะอยู่ภายใน 25% แต่ในบางกรณีมันอาจแย่กว่านั้น กรณีใด ๆ ที่เป็นไปอย่างรวดเร็วหรือภายในสองสามเปอร์เซ็นต์มักจะเกิดจากการใช้เวลาส่วนใหญ่ในรหัสห้องสมุดซึ่งปรับให้เหมาะสมอย่างมาก C อยู่ดี


5

อันที่จริงนี่เป็นบิตของความเท็จที่ชุลมุน แม้ว่ามันจะเป็นความจริงว่าโปรแกรม C มักจะเร็วกว่า แต่ก็ไม่ได้เป็นเช่นนั้นเสมอไปโดยเฉพาะอย่างยิ่งหากโปรแกรมเมอร์ C ไม่เก่ง

หลุมจ้องมองขนาดใหญ่ที่คนมักจะลืมคือเมื่อโปรแกรมต้องปิดกั้นการเรียงลำดับของ IO บางอย่างเช่นการป้อนข้อมูลผู้ใช้ในโปรแกรม GUI ใด ๆ ในกรณีเหล่านี้มันไม่สำคัญว่าภาษาใดที่คุณใช้เนื่องจากคุณถูก จำกัด ด้วยอัตราที่ข้อมูลสามารถเข้ามาแทนที่ความเร็วที่คุณสามารถดำเนินการได้ ในกรณีนี้มันไม่สำคัญมากถ้าคุณใช้ C, Java, C # หรือแม้แต่ Perl; คุณไม่สามารถไปได้เร็วกว่าที่ข้อมูลจะเข้ามา

อีกสิ่งที่สำคัญคือการใช้การรวบรวมขยะและการไม่ใช้พอยน์เตอร์ที่เหมาะสมช่วยให้เครื่องเสมือนทำการเพิ่มประสิทธิภาพจำนวนมากที่ไม่มีในภาษาอื่น ตัวอย่างเช่น JVM มีความสามารถในการเคลื่อนย้ายวัตถุรอบ ๆ บนกองเพื่อจัดระเบียบมัน สิ่งนี้ทำให้การจัดสรรในอนาคตเร็วขึ้นมากเนื่องจากสามารถใช้ดัชนีถัดไปได้แทนที่จะค้นหาในตาราง JVM สมัยใหม่ไม่จำเป็นต้องยกเลิกการจัดสรรหน่วยความจำ แต่พวกเขาเพียงแค่ย้ายวัตถุที่มีชีวิตไปรอบ ๆ เมื่อพวกเขา GC และหน่วยความจำที่ใช้ไปจากวัตถุที่ตายแล้วจะถูกกู้คืนได้ฟรีเป็นหลัก

สิ่งนี้ยังนำมาซึ่งประเด็นที่น่าสนใจเกี่ยวกับ C และอื่น ๆ อีกมากมายใน C ++ มีปรัชญาการออกแบบบางอย่างของ "ถ้าคุณไม่ต้องการคุณไม่ต้องจ่ายเงิน" ปัญหาคือว่าถ้าคุณต้องการคุณจะจ่ายเงินผ่านทางจมูกสำหรับมัน ตัวอย่างเช่นการใช้ vtable ใน Java มีแนวโน้มที่จะดีกว่าการใช้งาน C ++ มากดังนั้นการเรียกใช้ฟังก์ชันเสมือนจึงเร็วกว่ามาก ในทางตรงกันข้ามคุณไม่มีทางเลือกนอกจากใช้งานฟังก์ชั่นเสมือนจริงใน Java และพวกเขายังคงมีค่าใช้จ่ายบางอย่าง แต่ในโปรแกรมที่ใช้ฟังก์ชั่นเสมือนจำนวนมากค่าใช้จ่ายลดลงจะเพิ่มขึ้น


1
"การใช้งาน vtable ใน Java มีแนวโน้มที่จะดีกว่าการใช้ C ++ มากดังนั้นการเรียกฟังก์ชั่นเสมือนจะเร็วกว่ามาก" คุณจะไปได้เร็วแค่ไหนใน MOV EAX, [ECX] โทร [EAX + someindex]; ? เว้นแต่ว่าคุณจะสามารถเรียกใช้ฟังก์ชั่นได้โดยไม่ต้องมองหามันจะดูดีที่สุด
Frans-Willem

@Frans - คอมไพเลอร์ JIT (เช่น Java HotSpot) สามารถอินไลน์การค้นหา vtable หากพิจารณาว่าวัตถุที่กำหนดเป็นประเภทที่กำหนดไว้เสมอ C ++ จะทำเช่นนี้หากรู้ข้อมูลเดียวกันในเวลาคอมไพล์ แต่การเพิ่มประสิทธิภาพด้วย Java bytecode ง่ายกว่าการใช้คำสั่งเครื่อง x86
Tom

6
@James - การโต้เถียง "I / O ทำให้ประสิทธิภาพการทำงานลดลง" ไม่ทำให้คำสั่ง "C เร็วกว่าภาษาอื่น" นั่นไม่ใช่หลุมจ้องมองนั่นเป็นอาร์กิวเมนต์ชาวฟาง
Tom

มันคงจะดีกว่าถ้าได้ใช้การจัดการสตริงของ C (และไลบรารีมาตรฐาน C) เป็นตัวอย่างเนื่องจากเป็นพื้นที่ที่ C แย่ ภาษาอื่นส่วนใหญ่ทำได้ดีกว่าแม้ว่าจะเป็นรหัสเริ่มต้นที่ง่าย
Donal Fellows

@ DonalFellows ฟังก์ชั่น mem * สามารถเร็วกว่าฟังก์ชั่น str * ในบางงาน แต่การจัดการสตริงจะมีประสิทธิภาพถ้าใช้ความระมัดระวัง คุณมีเกณฑ์มาตรฐานเฉพาะในใจหรือไม่
Jasen

4

มันไม่ได้เกี่ยวกับภาษาเป็นเครื่องมือและไลบรารีมากนัก ไลบรารีและคอมไพเลอร์สำหรับ C ที่พร้อมใช้งานนั้นเก่ากว่าภาษาที่ใหม่กว่ามาก คุณอาจคิดว่าสิ่งนี้จะทำให้พวกเขาช้าลง แต่ au ตรงกันข้าม

ไลบรารีเหล่านี้ถูกเขียนขึ้นในเวลาที่กำลังประมวลผลและหน่วยความจำอยู่ในระดับพรีเมี่ยม พวกเขาจะต้องเขียนอย่างมีประสิทธิภาพเพื่อให้สามารถทำงานได้ทั้งหมด นักพัฒนาคอมไพเลอร์ C ยังมีเวลานานในการเพิ่มประสิทธิภาพที่ชาญฉลาดสำหรับโปรเซสเซอร์ที่แตกต่างกันทุกประเภท วุฒิภาวะของ C และการยอมรับอย่างกว้างขวางทำให้เกิดความได้เปรียบอย่างมีนัยสำคัญเหนือภาษาอื่นที่มีอายุเท่ากัน นอกจากนี้ยังช่วยให้ C มีความได้เปรียบด้านความเร็วมากกว่าเครื่องมือรุ่นใหม่ที่ไม่เน้นประสิทธิภาพที่ดิบเท่าที่ C ต้องทำ


4

การขาดนามธรรมเป็นสิ่งที่ทำให้ C เร็วขึ้น หากคุณเขียนคำสั่งเอาต์พุตคุณจะรู้ว่าเกิดอะไรขึ้น หากคุณเขียนคำสั่งเอาต์พุตใน java มันจะถูกรวบรวมไปยังไฟล์คลาสซึ่งจะถูกเรียกใช้บนเครื่องเสมือนที่แนะนำเลเยอร์ของสิ่งที่เป็นนามธรรม การขาดคุณสมบัติเชิงวัตถุเป็นส่วนหนึ่งของภาษายังเพิ่มความเร็วในการสร้างโค้ดให้น้อยลง หากคุณใช้ภาษา C เป็นภาษาเชิงวัตถุคุณกำลังทำการเขียนโค้ดทั้งหมดสำหรับสิ่งต่าง ๆ เช่นคลาส, การไม่อยู่ร่วมกันเป็นต้นซึ่งหมายความว่าให้ทำบางสิ่งที่เป็นมาตรฐานสำหรับทุกคนด้วยจำนวนโค้ดและประสิทธิภาพของปากกาที่คุณต้องเขียนเท่านั้น สิ่งที่คุณต้องทำให้งานสำเร็จ


4

น่าทึ่งที่ได้เห็น "C / C ++ เก่า ๆ นั้นต้องเร็วกว่า Java เพราะ Java ถูกตีความว่า" ตำนานยังคงมีชีวิตและเตะได้ มีบทความที่จะย้อนกลับไปเมื่อไม่กี่ปีที่ผ่านมารวมถึงบทความล่าสุดที่อธิบายด้วยแนวคิดหรือการวัดว่าทำไมมันถึงไม่เป็นเช่นนั้นเสมอไปไป

การใช้งานเครื่องเสมือนในปัจจุบัน (และไม่ใช่แค่ JVM โดยวิธีการ) สามารถใช้ประโยชน์จากข้อมูลที่รวบรวมระหว่างการทำงานของโปรแกรมเพื่อปรับแต่งโค้ดแบบไดนามิกในขณะที่ทำงานโดยใช้เทคนิคที่หลากหลาย:

  • การแสดงวิธีการที่ใช้บ่อยๆกับรหัสเครื่อง
  • การฝังวิธีการขนาดเล็ก
  • การปรับล็อค

และการปรับแต่งอื่น ๆ ที่หลากหลายโดยขึ้นอยู่กับการรู้ว่ารหัสกำลังทำอะไรอยู่และลักษณะที่แท้จริงของสภาพแวดล้อมที่ใช้งานอยู่


ผมยอมรับว่า Java ได้ทำการปรับปรุงประสิทธิภาพการทำงานอย่างมีนัยสำคัญในช่วงไม่กี่ปีที่ผ่านมาที่ทำให้มันมีความใกล้ชิดกับ C ในแง่ของประสิทธิภาพดิบ แต่มันจะใช้ในขณะที่มีชีวิตอยู่สภาพความเป็นจริงที่ว่ามันเป็นเช่นนั้นช้าดังนั้นยาว แต่ใครกำลังพูดถึง Java อยู่ดี
โรเบิร์ต Gamble

Java เป็น "ภาษาอื่น" ที่อ้างอิงโดย OP ใช่หรือไม่
Robert C. Barth

@Robert: "ภาษาอื่น ๆ ", พหูพจน์, ไม่เอ่ยถึงภาษาใด ๆ ที่นอกเหนือจาก C. คุณจะอ่าน "Java" ได้อย่างไร?
โรเบิร์ต Gamble

@Roberd: หลายคำตอบที่โพสต์ก่อนที่ฉันจะพบคำถามกำลังพูดถึง Java (หรือภาษาอื่น ๆ ที่มีการใช้งานบ่อยผ่านล่ามหรือ VM)
joel.neely

3
@Joel - หากคุณรู้จักฮาร์ดแวร์เป้าหมายการปรับแต่งส่วนใหญ่ที่ JVM สามารถทำได้ที่รันไทม์สามารถทำได้โดยใช้การปรับให้เหมาะสมกับโปรไฟล์ด้วย C หรือ C ++ สิ่งนี้สร้างความแตกต่างอย่างมากและโดยทั่วไปจะผลักให้ C และ C ++ กลับมาเป็นผู้นำเพราะพวกเขาไม่จำเป็นต้อง "เรียนรู้" ในขณะดำเนินการ
Tom

4

รหัสที่ทำงานเร็วที่สุดจะเป็นรหัสเครื่องที่ออกแบบอย่างระมัดระวังด้วยมือ ผู้ประกอบจะเกือบดี ทั้งสองอยู่ในระดับต่ำมากและต้องใช้รหัสในการทำสิ่งต่าง ๆ มากมาย C อยู่เหนือแอสเซมเบลอร์เล็กน้อย คุณยังคงมีความสามารถในการควบคุมสิ่งต่าง ๆ ในระดับต่ำมากในเครื่องจริง แต่มีสิ่งที่เป็นนามธรรมมากพอที่จะทำให้การเขียนมันเร็วขึ้นและง่ายขึ้นจากนั้นผู้ประกอบ ภาษาอื่นเช่น C # และ JAVA นั้นมีความเป็นนามธรรมมากกว่า ในขณะที่ Assembler และรหัสเครื่องเรียกว่าภาษาระดับต่ำ C # และ JAVA (และอีกหลายภาษา) เรียกว่าภาษาระดับสูง C บางครั้งเรียกว่าภาษาระดับกลาง


ในขณะที่อ่านคำตอบของคุณมีเพียงสองคำในย่อหน้าทั้งหมดที่ดึงสายตาของฉันไปหาพวกเขาเหมือนแม่เหล็กดึงโลหะ คำว่า JAVA สองครั้งในวรรค ไม่เคยเห็นมาก่อนเขียนด้วยตัวพิมพ์ใหญ่ทั้งหมดและมันก็ดูดี :-)
Sнаđошƒаӽ

3

อย่าใช้คำพูดสักคำให้ดูที่ตัวแยกส่วนสำหรับทั้ง C และภาษาที่คุณเลือกในส่วนที่มีความสำคัญต่อประสิทธิภาพของโค้ดของคุณ ฉันคิดว่าคุณสามารถดูในหน้าต่างถอดแยกชิ้นส่วนที่รันไทม์ใน Visual Studio เพื่อดู. NET ถอดชิ้นส่วน ควรเป็นไปได้หากหากใช้ Java กับ windbg หากคุณใช้. Net หลาย ๆ ปัญหาจะเหมือนกัน

ฉันไม่ชอบที่จะเขียนใน C หากฉันไม่ต้องการ แต่ฉันคิดว่าคำกล่าวอ้างหลายคำตอบที่ทำให้ความเร็วของภาษาอื่น ๆ นอกเหนือจาก C สามารถทำได้โดยการแยกส่วนที่เหมือนกันใน C และ ในภาษาระดับสูงที่คุณเลือกโดยเฉพาะอย่างยิ่งหากมีข้อมูลจำนวนมากที่เกี่ยวข้องเช่นเดียวกับในแอปพลิเคชันที่สำคัญด้านประสิทธิภาพ Fortran อาจเป็นข้อยกเว้นในเรื่องของความเชี่ยวชาญไม่ทราบ มันสูงกว่าระดับ C หรือไม่?

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


2

1) ตามที่คนอื่นพูด C ทำเพื่อคุณน้อยลง ไม่มีตัวแปรการเตรียมใช้งานไม่มีการตรวจสอบขอบเขตของอาเรย์ไม่มีการจัดการหน่วยความจำ ฯลฯ คุณลักษณะเหล่านั้นในภาษาอื่น ๆ มีค่าใช้จ่ายหน่วยความจำและรอบ CPU ที่ C ไม่ได้ใช้

2) คำตอบที่บอกว่า C นั้นเป็นนามธรรมน้อยกว่าและเร็วกว่านั้นถูกต้องเพียงครึ่งเดียวที่ฉันคิด เทคนิคการพูดหากคุณมี "คอมไพเลอร์ขั้นสูงอย่างเพียงพอ" สำหรับภาษา X ดังนั้นภาษา X สามารถเข้าใกล้หรือเท่ากับความเร็วของ C ความแตกต่างกับ C คือเนื่องจากมันแผนที่ชัดเจนดังนั้น (ถ้าคุณทำหลักสูตรสถาปัตยกรรม) และ โดยตรงไปยังภาษาแอสเซมบลีที่แม้แต่คอมไพเลอร์ไร้เดียงสาสามารถทำงานได้ดี สำหรับบางอย่างเช่น Python คุณต้องการคอมไพเลอร์ขั้นสูงมากในการทำนายประเภทของวัตถุที่เป็นไปได้และสร้างรหัสเครื่องในทันทีความหมายของ C นั้นง่ายพอที่คอมไพเลอร์ธรรมดาสามารถทำได้ดี


2

ย้อนกลับไปในช่วงวันที่ดีมีเพียงสองประเภทของภาษาคือรวบรวมและตีความ

ภาษาที่คอมไพล์ใช้ "คอมไพเลอร์" เพื่ออ่านไวยากรณ์ภาษาและแปลงเป็นรหัสภาษาแอสเซมบลีที่เหมือนกันซึ่งอาจทำได้มากกว่าซีพียูโดยตรง ภาษาตีความใช้สองรูปแบบที่แตกต่างกัน แต่เป็นหลักไวยากรณ์ภาษาถูกแปลงเป็นรูปแบบกลางและจากนั้นทำงานใน "ล่าม" สภาพแวดล้อมสำหรับการดำเนินการรหัส

ดังนั้นในแง่หนึ่งจึงมี "เลเยอร์" อีกตัวหนึ่ง - ล่าม - ระหว่างรหัสและเครื่อง และในกรณีที่เกิดขึ้นกับคอมพิวเตอร์บ่อยครั้งทรัพยากรก็มีมากขึ้นเช่นกัน ล่ามก็ช้าลงเพราะพวกเขาต้องดำเนินการเพิ่มเติม

เมื่อเร็ว ๆ นี้เราได้เห็นภาษาไฮบริดมากขึ้นเช่น Java ซึ่งใช้ทั้งคอมไพเลอร์และล่ามเพื่อให้ทำงานได้ มันซับซ้อน แต่ JVM นั้นเร็วกว่าซับซ้อนกว่าและมีวิธีที่ปรับให้เหมาะสมที่สุดกว่าล่ามเก่าดังนั้นมันจึงเปลี่ยนการแสดงที่ดีขึ้นมาก (เมื่อเวลาผ่านไป) ใกล้กับโค้ดที่เรียบเรียงโดยตรง แน่นอนว่าคอมไพเลอร์รุ่นใหม่นั้นมีเทคนิคการปรับให้เหมาะสมที่สุดเพื่อให้พวกเขามีแนวโน้มที่จะสร้างโค้ดที่ดีกว่าที่เคยเป็นมา แต่การเพิ่มประสิทธิภาพส่วนใหญ่มักจะ (แม้ว่าจะไม่เสมอ) ทำให้เกิดการแลกเปลี่ยนบางประเภทเช่นที่พวกเขาไม่ได้เร็วขึ้นเสมอในทุกสถานการณ์ เช่นเดียวกับทุกอย่างอื่นไม่มีสิ่งใดมาให้ฟรีดังนั้นเครื่องมือเพิ่มประสิทธิภาพจะต้องได้รับการโอ้อวดจากที่ใดที่หนึ่ง

กลับไปที่ C เป็นภาษาง่าย ๆ ที่สามารถคอมไพล์ในแอสเซมบลีที่ปรับให้เหมาะสมแล้วเรียกใช้โดยตรงบนเครื่องเป้าหมาย ใน C หากคุณเพิ่มจำนวนเต็มเป็นไปได้ว่าเป็นเพียงขั้นตอนแอสเซมเบลอร์หนึ่งในซีพียูใน Java อย่างไรก็ตามมันอาจจบลงด้วยการเป็นจำนวนมากมากกว่านั้น (และอาจรวมถึงการรวบรวมขยะเล็กน้อยด้วย: -) C ให้สิ่งที่เป็นนามธรรมแก่คุณซึ่งอยู่ใกล้กับเครื่องมากขึ้น (แอสเซมเบลอร์เป็นสิ่งที่ใกล้เคียงที่สุด) แต่คุณต้องทำงานมากขึ้นเพื่อให้มันทำงานได้และไม่ได้รับการป้องกันใช้งานง่ายหรือเป็นมิตรกับข้อผิดพลาด ภาษาอื่น ๆ ส่วนใหญ่จะให้สิ่งที่เป็นนามธรรมที่สูงขึ้นและดูแลรายละเอียดพื้นฐานให้คุณมากขึ้น แต่เพื่อแลกกับการทำงานขั้นสูงของพวกเขาพวกเขาต้องการทรัพยากรเพิ่มเติมเพื่อที่จะทำงาน เมื่อคุณพูดคุยเกี่ยวกับโซลูชันทั่วไปคุณจะต้องจัดการกับคอมพิวเตอร์ในวงกว้างมากขึ้น

พอล


"ใน C หากคุณเพิ่มจำนวนเต็มมีโอกาสมากกว่าที่จะเป็นเพียงหนึ่งขั้นตอนแอสเซมเบลอร์ในซีพียู" ไม่เป็นความจริง หากจำนวนเต็มนี้ไม่ได้อยู่ในการลงทะเบียน CPU คุณจะต้องมีรหัสเครื่องเพื่อดึงจากหน่วยความจำเพิ่มขึ้นเขียนลงในหน่วยความจำ เกี่ยวกับหนึ่งเดียวกันคาดว่าจะเกิดขึ้นเมื่อใช้รหัส Java และฉันก็ไม่เข้าใจว่าทำไม "++ i" จะกระตุ้นรอบ GC ด้วยตัวเอง
quant_dev

@quant_dev: "คุณ .. มี ... ในการดึงข้อมูลจากหน่วยความจำเพิ่มขึ้นเขียนมันกลับมา ... " อาจจะอาจจะไม่. ตัวอย่างเช่น x86 มีคำแนะนำที่ทำงานกับข้อมูลในหน่วยความจำ ++iอาจรวบรวมเพื่อ "เพิ่ม [ebp - 8], 1" ไม่ต้องบอกว่าการดึงข้อมูลการเพิ่มขึ้นการจัดเก็บยังไม่เกิดขึ้น แต่สิ่งนี้ได้รับการดูแลโดย CPU และเป็นเพียงคำสั่งเดียวตามที่ Paul กล่าว
P พ่อ

... ซึ่งยังไม่เกี่ยวข้องกับ POV ของประสิทธิภาพเนื่องจากอาจเป็นเพียงคำสั่งเดียว แต่ยังเกี่ยวข้องกับการรอให้ข้อมูลมาถึง CPU Cache คิดถึงและทั้งหมดนั้น
quant_dev

ไม่ฉันไม่อยากพูดว่ามันไม่เกี่ยวข้อง คำสั่ง CPU หนึ่งคำสั่งมักใช้จำนวนไบต์ของรหัสน้อยกว่าคำสั่ง CPU หลายตัวทำให้ได้ประสิทธิภาพแคชที่ดีขึ้นในส่วนของรหัส คำสั่ง CPU หนึ่งคำสั่งยังใช้พื้นที่น้อยกว่าบนไปป์ไลน์ของ CPU และสามารถจัดการได้หลายขั้นตอน (ดึงข้อมูลเพิ่มขึ้นจัดเก็บ) - อาจขนานกัน - โดยขั้นตอนไปป์ไลน์แยกต่างหาก ในความเป็นจริงแล้วบางส่วนของการดำเนินการอาจถูกข้ามไปหากสามารถรวมเข้ากับการดำเนินการอื่น ๆ ได้ ตัวอย่างเช่นการจัดเก็บค่าสามารถหลอมรวมกับการโหลดตามมาของค่าเดียวกัน
P พ่อ

2

การตั้งค่าเทคนิคการเพิ่มประสิทธิภาพขั้นสูงกันเช่นการเพิ่มประสิทธิภาพจุดร้อน , ก่อนรวบรวมอภิขั้นตอนวิธีการและรูปแบบต่างๆของขนานความเร็วพื้นฐานของความสัมพันธ์ภาษาอย่างมากกับนัยเบื้องหลังฉากซับซ้อนที่จำเป็นในการสนับสนุนการดำเนินงานที่จะทั่วไป ระบุภายในลูปภายใน

บางทีสิ่งที่ชัดเจนที่สุดคือการตรวจสอบความถูกต้องของการอ้างอิงหน่วยความจำทางอ้อมเช่นการตรวจสอบพอยน์เตอร์nullและการตรวจสอบดัชนีเทียบกับขอบเขตของอาร์เรย์ ภาษาระดับสูงส่วนใหญ่ดำเนินการตรวจสอบเหล่านี้โดยปริยาย แต่ C ไม่ได้ อย่างไรก็ตามนี่ไม่จำเป็นต้องเป็นข้อ จำกัด พื้นฐานของภาษาอื่น ๆ เหล่านี้ - คอมไพเลอร์ที่ฉลาดพออาจสามารถลบการตรวจสอบเหล่านี้ออกจากลูปด้านในของอัลกอริทึมผ่านรูปแบบการเคลื่อนที่ของรหัสวนรอบไม่เปลี่ยนแปลงวงคงเคลื่อนไหวรหัส

ข้อได้เปรียบพื้นฐานของ C (และขอบเขตที่คล้ายกันคือ C ++ ที่เกี่ยวข้องอย่างใกล้ชิด) คือการพึ่งพาอย่างหนักในการจัดสรรหน่วยความจำแบบสแต็กซึ่งใช้ความเร็วสูงในการจัดสรรจัดสรรคืนและเข้าถึง ใน C (และ C ++) สแต็กการโทรหลักสามารถใช้สำหรับการจัดสรร primitives, arrays และ aggregates ( struct/ class)

ในขณะที่ C ให้ความสามารถในการจัดสรรหน่วยความจำแบบไดนามิกตามขนาดและอายุการใช้งานแบบไดนามิก (ใช้ชื่อที่เรียกว่า 'ฮีป') การหลีกเลี่ยงการทำเช่นนี้จะเป็นไปตามค่าเริ่มต้น (ใช้สแต็กแทน)

ยั่วเย้าบางครั้งเป็นไปได้ที่จะทำซ้ำกลยุทธ์การจัดสรรหน่วยความจำ C ภายในสภาพแวดล้อมรันไทม์ของภาษาการเขียนโปรแกรมอื่น ๆ สิ่งนี้แสดงให้เห็นโดยasm.jsซึ่งอนุญาตให้แปลโค้ดใน C หรือ C ++ เป็นส่วนย่อยของ JavaScript และทำงานอย่างปลอดภัยในสภาพแวดล้อมของเว็บเบราว์เซอร์ - ด้วยความเร็วใกล้เคียง


นอกเหนือจากภาษาอื่นแล้วพื้นที่อื่นที่ภาษา C และ C ++ มีความโดดเด่นกว่าภาษาอื่นสำหรับความเร็วคือความสามารถในการรวมเข้ากับชุดคำสั่งภาษาดั้งเดิมได้อย่างลงตัว ตัวอย่างที่โดดเด่นของเรื่องนี้คือความพร้อมใช้งาน (ขึ้นอยู่กับคอมไพเลอร์และแพลตฟอร์ม) ของSIMD ภายในซึ่งสนับสนุนการสร้างอัลกอริทึมแบบกำหนดเองที่ใช้ประโยชน์จากฮาร์ดแวร์ประมวลผลแบบขนานที่แพร่หลายเกือบทุกขณะ - ในขณะที่ยังคงใช้ - ระดับการลงทะเบียนถูกจัดการโดยคอมไพเลอร์)


1
ข้อได้เปรียบในการจัดสรรหน่วยความจำบางส่วนของ C สามารถทำซ้ำได้ในภาษาอื่นโดยคอมไพเลอร์ที่ฉลาด (ดูที่นี่ ) แม้ว่าฉันจะได้รับความประทับใจว่านี่เป็นโครงสร้างที่ยากมากที่จะทำ - โดยเฉพาะอย่างยิ่งสำหรับชนิดข้อมูลที่ไม่ใช่แบบดั้งเดิม โพสต์นี้กล่าวถึงแนวคิดของวัตถุที่ไม่หนีซึ่งสามารถจัดสรรสแต็กเป็นการเพิ่มประสิทธิภาพใน Java
ดี

2

ฉันพบลิงก์คำตอบเกี่ยวกับสาเหตุที่บางภาษาเร็วขึ้นและบางช้าฉันหวังว่าสิ่งนี้จะชัดเจนมากขึ้นเกี่ยวกับสาเหตุที่ C หรือ C ++ เร็วกว่าภาษาอื่น ๆ มีภาษาอื่น ๆ อีกด้วยที่เร็วกว่า C แต่เราไม่สามารถทำได้ ใช้ทั้งหมดของพวกเขา คำอธิบายบางอย่าง -

หนึ่งในเหตุผลสำคัญที่ฟอร์แทรนยังคงมีความสำคัญก็คือเพราะมันรวดเร็ว: รูทีนการบีบอัดจำนวนที่เขียนในฟอร์แทรนมักจะเร็วกว่ารูทีนเทียบเท่าที่เขียนในภาษาอื่น ๆ ส่วนใหญ่ ภาษาที่แข่งขันกับ Fortran ในพื้นที่นี้ - C และ C ++ - ถูกนำมาใช้เพราะพวกเขาแข่งขันกับประสิทธิภาพนี้

นี่ทำให้เกิดคำถาม: ทำไม มันเกี่ยวกับ C ++ และ Fortran ที่ทำให้พวกมันเร็วและทำไมพวกมันถึงมีประสิทธิภาพเหนือกว่าภาษายอดนิยมอื่น ๆ เช่น Java หรือ Python?

การตีความเมื่อเทียบกับการรวบรวมมีหลายวิธีในการจัดหมวดหมู่และกำหนดภาษาการเขียนโปรแกรมตามรูปแบบของการเขียนโปรแกรมที่พวกเขาสนับสนุนและคุณสมบัติที่พวกเขาเสนอ เมื่อพิจารณาถึงประสิทธิภาพความแตกต่างที่ใหญ่ที่สุดเพียงอย่างเดียวคือระหว่างภาษาที่ถูกตีความและภาษาที่รวบรวม

การแบ่งไม่ยาก ค่อนข้างมีสเปกตรัม ในตอนท้ายเรามีภาษาที่รวบรวมแบบดั้งเดิมกลุ่มที่มี Fortran, C และ C ++ ในภาษาเหล่านี้มีขั้นตอนการคอมไพล์แบบแยกซึ่งแปลซอร์สโค้ดของโปรแกรมเป็นรูปแบบการปฏิบัติการที่โปรเซสเซอร์สามารถใช้

กระบวนการรวบรวมนี้มีหลายขั้นตอน ซอร์สโค้ดวิเคราะห์และแยกวิเคราะห์ ข้อผิดพลาดการเขียนโค้ดพื้นฐานเช่นข้อผิดพลาดการพิมพ์ผิดและการสะกดคำสามารถตรวจพบได้ในจุดนี้ รหัส parsed ถูกใช้เพื่อสร้างการแสดงในหน่วยความจำซึ่งก็สามารถใช้ในการตรวจสอบข้อผิดพลาด - ในเวลานี้ความผิดพลาดทางความหมายเช่นฟังก์ชั่นการโทรที่ไม่มีอยู่หรือพยายามดำเนินการทางคณิตศาสตร์กับสตริงข้อความ

การเป็นตัวแทนในหน่วยความจำนี้จะถูกใช้เพื่อขับเคลื่อนตัวสร้างโค้ดซึ่งเป็นส่วนที่สร้างโค้ดที่เรียกใช้งานได้ การปรับให้เหมาะสมของรหัสเพื่อปรับปรุงประสิทธิภาพของรหัสที่สร้างขึ้นจะดำเนินการในหลาย ๆ ครั้งภายในกระบวนการนี้: การปรับให้เหมาะสมระดับสูงสามารถดำเนินการแทนรหัสได้และใช้การปรับปรุงระดับต่ำสุดในผลลัพธ์ของตัวสร้างรหัส

การรันโค้ดจริงเกิดขึ้นในภายหลัง กระบวนการรวบรวมทั้งหมดนั้นใช้เพื่อสร้างสิ่งที่สามารถดำเนินการได้

ในตอนท้ายเรามีล่าม ล่ามจะมีขั้นตอนการแยกวิเคราะห์คล้ายกับของคอมไพเลอร์ แต่จะใช้ในการผลักดันการดำเนินการโดยตรงกับโปรแกรมที่กำลังทำงานทันที

ล่ามที่ง่ายที่สุดมีโค้ดที่สามารถใช้งานได้ซึ่งตรงกับคุณสมบัติต่าง ๆ ที่ภาษารองรับ - ดังนั้นมันจะมีฟังก์ชั่นสำหรับการเพิ่มตัวเลข, การรวมสตริง, ไม่ว่าภาษาอื่นจะมีอะไรก็ตาม ขณะที่วิเคราะห์คำมันจะค้นหาฟังก์ชั่นที่เกี่ยวข้องและดำเนินการมัน ตัวแปรที่สร้างในโปรแกรมจะถูกเก็บไว้ในตารางการค้นหาบางอย่างที่แมปชื่อของพวกเขากับข้อมูลของพวกเขา

ตัวอย่างสุดขีดของสไตล์ล่ามคือบางอย่างเช่นแบตช์ไฟล์หรือเชลล์สคริปต์ ในภาษาเหล่านี้รหัสที่ใช้งานได้มักจะไม่ได้สร้างไว้ในตัวแปลภาษาเอง แต่แยกต่างหากโปรแกรมแบบสแตนด์อโลน

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

หากคุณต้องการทราบข้อมูลเพิ่มเติมโปรดตรวจสอบที่มา


1

อัลกอริทึม C ++ บางอันเร็วกว่า C และการใช้อัลกอริธึมบางอย่างหรือรูปแบบการออกแบบในภาษาอื่นอาจเร็วกว่า C

เมื่อผู้คนพูดว่า C เร็วและจากนั้นไปพูดคุยเกี่ยวกับภาษาอื่นพวกเขามักใช้การทำงานของ C เป็นเกณฑ์มาตรฐาน


2
"อัลกอริทึม C ++ บางตัวเร็วกว่า C" ไม่สมเหตุสมผล "อัลกอริทึม C ++" ใด ๆ สามารถเขียนใน C และในทางกลับกัน อัลกอริทึมเป็นผู้ไม่เชื่อเรื่องภาษา C ++ เป็นหลักเพิ่มคุณสมบัติให้กับ C - และไม่มีคุณสมบัติใหม่เหล่านี้นำไปสู่อัลกอริทึมที่เร็วขึ้น (แม้ว่าพวกเขาอาจจะง่ายต่อการเขียน)
โจเซฟ Garvin

1
rebuke คลาสสิคคือ std :: sort algorithm .. std :: sort เร็วกว่าอัลกอริธึมการเรียงใน C - วิธีเดียวที่จะได้ประสิทธิภาพที่เหมือนกันใน C คือการเขียนโค้ดให้ยากทุกที่ที่คุณต้องการหรือใช้มาโคร - และแม้กระทั่งตอนนั้น คอมไพเลอร์มีข้อมูลน้อยลงเพื่อปรับให้เหมาะสม
Arafangion

1

ด้วยคอมไพเลอร์การปรับให้เหมาะสมที่ทันสมัยมันไม่น่าเป็นไปได้อย่างยิ่งที่โปรแกรม C บริสุทธิ์จะเป็นไปได้ทั้งหมดที่เร็วกว่าการคอมไพล์โค้ด. net หากทั้งหมด กับการเพิ่มประสิทธิภาพการผลิตที่กรอบเช่น .net ให้นักพัฒนาที่คุณสามารถทำสิ่งนี้ในวันที่ใช้ในการใช้เวลาหลายสัปดาห์หรือหลายเดือนใน C. ปกติควบคู่ไปกับค่าใช้จ่ายราคาถูกของฮาร์ดแวร์เมื่อเทียบกับเงินเดือนของนักพัฒนาก็เป็นเพียงวิธีการที่ถูกกว่าการเขียน เนื้อหาในภาษาระดับสูงและโยนฮาร์ดแวร์ที่ความเชื่องช้า

เหตุผลที่เจฟกับโจเอลพูดถึง C ว่าเป็น "นักเขียนโปรแกรมตัวจริง" เพราะไม่มีมือจับในซีคุณต้องจัดสรรหน่วยความจำของคุณเอง, จัดสรรคืนหน่วยความจำ, ทำการตรวจสอบขอบเขตของคุณเอง ฯลฯ ไม่มีสิ่งนั้น เป็นวัตถุใหม่ (); ไม่มีการรวบรวมขยะคลาส OOP กรอบงานเอนทิตี LINQ คุณสมบัติแอตทริบิวต์เขตข้อมูลหรืออะไรทำนองนั้น คุณต้องรู้สิ่งต่าง ๆ เช่นเลขคณิตของตัวชี้และวิธีการอ้างอิงตัวชี้ และสำหรับเรื่องนั้นให้รู้และเข้าใจว่าตัวชี้คืออะไร คุณต้องรู้ว่า stack frame คืออะไรและตัวชี้คำสั่งคืออะไร คุณต้องรู้รูปแบบหน่วยความจำของสถาปัตยกรรม CPU ที่คุณกำลังทำงานอยู่ มีความเข้าใจโดยปริยายมากมายเกี่ยวกับสถาปัตยกรรมของไมโครคอมพิวเตอร์ไมโครคอมพิวเตอร์ที่คุณกำลังทำงาน) เมื่อเขียนโปรแกรมใน C ที่ไม่มีอยู่หรือไม่จำเป็นเมื่อเขียนโปรแกรมในภาษา C # หรือ Java ข้อมูลทั้งหมดนั้นถูกโหลดไปที่โปรแกรมเมอร์คอมไพเลอร์ (หรือ VM)


"เพิ่มฮาร์ดแวร์ที่มีปัญหา" ใช้งานได้ในสภาพแวดล้อมที่เป็นไปได้จริงเท่านั้น ตลาดแบบฝังเป็นตัวอย่างที่สมบูรณ์แบบ (และนั่นเป็นตลาดขนาดใหญ่ )
บ๊อบซอมเมอร์

Jeff และ Joel บล็อกเกี่ยวกับระบบธุรกิจเท่านั้นไม่ใช่ระบบฝังตัวดังนั้นจึงมีเหตุผลที่จะสมมติว่าเป็นบริบทที่ถามคำถามนี้
Robert C. Barth

1). รหัสเน็ตทำงานเร็วเท่ากับรหัส C หรือไม่ คุณเคยเขียนโปรแกรม C หรือไม่? 2) ความคิด "ทิ้งฮาร์ดแวร์ที่มีปัญหามากขึ้น" คือเหตุผลที่เครื่อง 1.3GHz ดูอัลคอร์ 2GB ของฉันแทบไม่ทันกับ Windows XP ในขณะที่เครื่อง 800MHz 512MB ของฉันบินกับ Ubuntu เวอร์ชันล่าสุด
Robert Gamble

ใช่ฉันเขียน C. มันไม่รุ่งโรจน์เท่าที่ผู้คนทำออกมาได้ และค่าใช้จ่ายโครงการมากเกินไป มันเป็นกรณีเศรษฐศาสตร์แบบง่าย ๆ ฉันใช้ Win2k กับ Pentium Pro 180MHz พร้อม RAM 768MB เป็นเวลาหลายปีเช่นเดียวกับอีเมลและเว็บเซิร์ฟเวอร์ มันวิ่งได้ดี หลักฐานเล็ก ๆ น้อย ๆ ไม่มีความหมาย
Robert C. Barth

C ไม่ใช่ "รุ่งโรจน์" แต่เร็วฉันเขียนรหัส C และ C # มากพอที่จะรู้ว่า C เร็วกว่า C # เกือบทุกครั้งในขณะที่ทำงานเดียวกัน สำหรับงานบางอย่างใช้เวลาในการพัฒนานานกว่าภาษาระดับสูงกว่า แต่ทั้งหมดเกี่ยวกับการใช้เครื่องมือที่เหมาะสมสำหรับงานและบางครั้ง C คือ
Robert Gamble

1

ความแตกต่างระหว่างภาษาอัตโนมัติและแมนนวลภาษาระดับที่สูงขึ้นจึงเป็นนามธรรมโดยอัตโนมัติ C / C ++ ถูกควบคุมและจัดการด้วยตนเองแม้ในบางครั้งรหัสตรวจสอบข้อผิดพลาดก็เป็นงานที่ต้องทำด้วยมือ

C และ C ++ เป็นภาษาที่รวบรวมซึ่งหมายความว่าไม่มีการดำเนินการใด ๆ ในทุกธุรกิจภาษาเหล่านี้ต้องได้รับการปรับแต่งสำหรับฮาร์ดแวร์ที่คุณทำงานด้วยซึ่งจะเป็นการเพิ่มชั้นพิเศษของ gotcha ถึงแม้ว่าสิ่งนี้จะดูเล็กน้อยในขณะนี้เนื่องจากคอมไพเลอร์ C / C ++ กำลังกลายเป็นเรื่องธรรมดาไปทั่วทุกแพลตฟอร์ม คุณสามารถทำการคอมไพล์ข้ามระหว่างแพลตฟอร์มได้ มันยังไม่ได้ทำงานทุกสถานการณ์โดยพื้นฐานแล้วคอมไพเลอร์ A ของคุณเพื่อคอมไพล์กับคอมไพเลอร์ B สถาปัตยกรรมรหัสที่ต่างกัน

ภาษา C บรรทัดล่างไม่ได้มีไว้เพื่อให้ง่ายต่อการเข้าใจหรือมีเหตุผลนี่เป็นสาเหตุที่ภาษาเหล่านั้นถูกเรียกว่าเป็นภาษาของระบบ พวกเขาออกมาก่อนเรื่องไร้สาระระดับสูงทั้งหมดนี้ นี่คือสาเหตุที่ไม่ได้ใช้สำหรับการเขียนโปรแกรมเว็บส่วนหน้า พวกเขาไม่เหมาะกับงานพวกเขาหมายถึงการแก้ปัญหาที่ซับซ้อนซึ่งไม่สามารถแก้ไขได้ด้วยเครื่องมือทางภาษาทั่วไป

นี่คือเหตุผลที่คุณได้รับสิ่งที่บ้าเช่น (ไมโครสถาปัตยกรรมไดรฟ์เวอร์ควอนตัมฟิสิกส์เกม AAA ระบบปฏิบัติการ) มีสิ่งที่ C และ C ++ เหมาะสำหรับ ความเร็วและจำนวนกระทืบเป็นพื้นที่หลัก



1

มีสาเหตุหลายประการ ได้แก่ :

  • มันรวบรวมเป็นภาษาแอสเซมบลี
  • มันถูกพิมพ์แบบคงที่
  • ไม่มีการเก็บขยะ
  • ไม่มีการจัดการข้อผิดพลาด
  • ภาษาการเขียนโปรแกรมจำนวนมากเพิ่มคุณสมบัติใหม่ ส่วนหนึ่งของปรัชญาของ C คือการทำให้สิ่งต่าง ๆ ง่ายขึ้นแทนที่จะเพิ่มคุณสมบัติเพิ่มเติม

ทำไมมันถึงเร็วกว่าเพราะมันไม่ได้เป็นวัตถุ
sb27

A) การเขียนโปรแกรมเชิงวัตถุสร้างความต้องการในการรวบรวมขยะ B) คุณสมบัติขนาดใหญ่เช่นการเขียนโปรแกรมเชิงวัตถุเพิ่มความซับซ้อนให้กับคอมไพเลอร์
Sapphire_Brick

A) ไม่ ดู C ++ หรือ Rust B) ใช่ แต่มันยังให้โอกาสผู้รวบรวมสำหรับการปรับแต่งใหม่
sb27

A) Rust มีการรวบรวมขยะในเวลารวบรวมและ c ++ มีการรวบรวมขยะสำหรับชั้นเรียนนั่นเป็นสาเหตุว่าทำไมมันถึงมี destructors ,, B) ความซับซ้อนที่ปรับให้เหมาะสมยังคงมีความซับซ้อน
Sapphire_Brick

A) ไม่ใช่การรวบรวมขยะการจัดการหน่วยความจำจะต้องทำแม้ว่าคุณจะสร้างโปรแกรมของคุณในการประกอบ B) Nope More Abstraction ช่วยให้เครื่องมือเพิ่มประสิทธิภาพสร้างสมมติฐานที่ดีขึ้น
sb27
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.