C + + เร็วกว่า C # เร็วเท่าใด


246

หรือตอนนี้เป็นวิธีอื่น ๆ ?

จากสิ่งที่ฉันได้ยินมีบางพื้นที่ที่ C # พิสูจน์ได้ว่าเร็วกว่า C ++ แต่ฉันไม่เคยกล้าพอที่จะทดสอบด้วยตัวเอง

คิดว่าคุณคนใดสามารถอธิบายความแตกต่างในรายละเอียดเหล่านี้หรือชี้ให้ฉันถูกที่สำหรับข้อมูลนี้


7
ได้รับการป้องกันเพื่อป้องกันไม่ให้มีการสุ่มโพสต์เกณฑ์มาตรฐานอีก หากคุณคิดว่าคุณสามารถทำคดีของคุณคุณจะต้องมี 10 ตัวแทนให้ทำเช่นนั้น
Robert Harvey

2
สิ่งนี้ยังไม่ปิดในฐานะความคิดเห็น / เหตุผล? ฉันยังไม่อยู่ใน StackOverflow หรือไม่ (ไม่แนะนำให้ใกล้แค่อยากรู้อยากเห็นฉันรักคำถามที่กระตุ้นข้อโต้แย้งความเห็น)
Bill K

1
เกือบเป็นคำถามที่สงสัยเนื่องจากเราอยู่ในยุคที่ IL สามารถแปลงเป็น CPP และปรับให้เหมาะสมจากที่นั่น: docs.unity3d.com/Manual/IL2CPP.html
pixelpax

ภาษาที่ตรวจสอบการเข้าถึงอาร์เรย์ที่ไม่อยู่ในช่วงจะไม่มีประสิทธิภาพเหนือกว่าภาษาที่ไม่มี
Seva Alekseyev

@SevaAlekseyev ไม่ใช่ภาษาที่ทำสิ่งนี้ แต่เป็นคอมไพเลอร์ เหตุผลหนึ่งที่ทำให้ C ++ นั้นเร็ว (นอกเหนือจากที่เห็นได้ชัด) ก็คือคอมไพเลอร์ C ++ นั้นมีมานานกว่า 35 ปีแล้ว (ถ้าไม่มาก) ไม่มีอะไรที่ป้องกันคอมไพเลอร์ C # เพื่อให้ดีขึ้นเมื่อเวลาผ่านไป สำหรับกรณีที่คุณพูดถึงโปรดอ่านstackoverflow.com/questions/16713076/
กับดัก

คำตอบ:


343

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

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

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

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

โปรดทราบว่ามันค่อนข้างง่ายในการเพิ่มประสิทธิภาพโปรแกรมที่ถูกต้อง แต่ยากมากที่จะแก้ไขโปรแกรมที่ได้รับการปรับปรุงให้ดีที่สุด

การให้เปอร์เซ็นต์ความได้เปรียบความเร็วที่แท้จริงนั้นเป็นไปไม่ได้มันขึ้นอยู่กับโค้ดของคุณเป็นส่วนใหญ่ ในหลายกรณีการใช้ภาษาโปรแกรมไม่ได้เป็นปัญหาคอขวด ใช้เบนช์มาร์กที่http://benchmarksgame.alioth.debian.org/ด้วยความสงสัยอย่างมากเนื่องจากการทดสอบเลขคณิตเหล่านี้ส่วนใหญ่ซึ่งไม่น่าจะคล้ายกับรหัสของคุณเลย


92
โค้ด <quote> ในภาษาที่แปลจะเร็วขึ้นในรันไทม์รุ่นที่ใหม่กว่า </quote> โค้ดที่คอมไพล์แล้วโดยคอมไพเลอร์เวอร์ชั่นที่ดีกว่าก็จะเร็วขึ้นเช่นกัน
Martin York

47
ในความเป็นจริงมีเหตุผลอย่างน้อยหนึ่งข้อ: JIT ต้องรวดเร็วและไม่สามารถใช้เวลากับการปรับแต่งขั้นสูงที่หลากหลายสำหรับคอมไพเลอร์ C ++
Nemanja Trifunovic

63
"แต่โดยทั่วไปจะนำไปสู่ข้อผิดพลาดเนื่องจากการปรับให้เหมาะสมมากเกินไป" [ต้องการการอ้างอิงที่ต้องการอย่างยิ่ง] ฉันทำงานที่ห้องแล็บแห่งชาติและเราปรับนรกให้เหมาะสมกับรหัสของเรา สิ่งนี้ไม่ได้ส่งผลให้เกิดรหัสรถ
ทอดด์ Gamblin

35
“ มันค่อนข้างง่ายในการปรับโปรแกรมที่ถูกต้องให้เหมาะสม แต่ก็ยากกว่ามากในการแก้ไขโปรแกรมที่ได้รับการปรับปรุง
gradbot

20
Inge: ไม่แน่ใจว่าคุณมาถูกทางแล้ว ใช่ C # ถูกนำไปใช้ในภาษาอื่น แต่คอมไพเลอร์ JIT กำลังสร้างรหัสเครื่องดังนั้นจึงไม่ใช่ภาษาที่ตีความ ดังนั้นจึงไม่ถูก จำกัด โดยการใช้ C ++ ฉันไม่แน่ใจว่าทำไมคุณคิดว่าการเพิ่มผู้จัดการให้กับสิ่งที่ทำให้มันเร็วขึ้น
Martin Probst

202

C # อาจไม่เร็วกว่านี้ แต่จะทำให้คุณ / ฉันเร็วขึ้น นั่นเป็นมาตรการที่สำคัญที่สุดสำหรับสิ่งที่ฉันทำ :)


68
ฮ่าฮ่ามีคำพูดที่ดีจาก Larry Wall ในหัวข้อ เขาพูดถึง Perl แต่มันอาจเป็นความคิดสำหรับการอภิปรายทั้งหมดที่เกี่ยวข้องกับภาษาและประสิทธิภาพ: ".. ภาษาคอมพิวเตอร์ก่อนหน้านี้เช่น Fortran และ C ได้รับการออกแบบมาเพื่อให้การใช้ฮาร์ดแวร์คอมพิวเตอร์ที่มีราคาแพงมีประสิทธิภาพตรงกันข้าม Perl ถูกออกแบบมาเพื่อ ใช้ประโยชน์จากโปรแกรมเมอร์คอมพิวเตอร์ราคาแพงอย่างมีประสิทธิภาพ "
Falaina

60
1. "C # เร็วกว่า C ++" 2. "มันไม่จริง" 1. "แน่ใจว่าสามารถทำได้" 2. "โดยเท่าไหร่" 1. "โดยปกติ 3-4 เดือน"
Dmitry S.

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

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

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

87

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


177
คุณมีหลักฐานที่จะสนับสนุนการเรียกร้องห้าส้มที่ชั่วร้ายของคุณหรือไม่? การทดลองของฉันชี้ไปที่ 2 ส้มมากที่สุดโดยมีการปรับปรุง 3 มะม่วงเมื่อทำเทมเพลตการเขียนโปรแกรม
Alex

42
ที่ยีสต์เขาไม่ได้ส่งเสียงร้องเร็วขนาดนี้
Chris

11
จากประสบการณ์ของฉันมันค่อนข้าง 5.2 ส้ม แต่ขึ้นอยู่กับผลไม้ที่คุณใช้
Dio F

4
อัปเดต StackOverflow ทำให้ตัวเองยุ่งและจัดการความคิดเห็นที่ไม่มีประสิทธิภาพจึงทำให้กล้วยน้อยลง (300 กล้วยที่แย่กว่าที่ควรจะเป็น): meta.stackexchange.com/questions/254534/ …
KeksArmee

87

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

มีเหตุผลมากมายที่รหัส JITted จะทำงานช้ากว่าโปรแกรม C ++ ที่เหมาะสมที่สุด (หรือภาษาอื่น ๆ ที่ไม่มีค่าใช้จ่ายรันไทม์)รวมถึง:

  • คำนวณรอบที่ใช้กับรหัส JIT ที่รันไทม์โดยคำจำกัดความไม่พร้อมใช้งานสำหรับใช้ในการดำเนินการโปรแกรม

  • พา ธ ร้อน ๆ ใน JITter จะแข่งขันกับโค้ดของคุณสำหรับคำสั่งและแคชข้อมูลใน CPU เรารู้ว่าแคชนั้นมีอิทธิพลต่อประสิทธิภาพและภาษาดั้งเดิมอย่าง C ++ ไม่มีการโต้แย้งประเภทนี้ตามนิยาม

  • งบประมาณเวลาของเครื่องมือเพิ่มประสิทธิภาพเวลาทำงานจำเป็นต้องมีข้อ จำกัด มากกว่าของเครื่องมือเพิ่มประสิทธิภาพขณะรวบรวม (ดังที่ผู้วิจารณ์คนอื่นชี้ให้เห็น)

บรรทัดด้านล่าง: ในที่สุดคุณจะเกือบแน่นอนจะสามารถสร้างการดำเนินงานได้เร็วขึ้นใน C ++ กว่าที่คุณสามารถทำได้ใน C #

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

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

-

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

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

แต่ฉันเขียนรหัส C ++ ที่เป็นสำนวนมากกว่าเล็กน้อยและเปรียบเทียบกับรหัส C # @Wiory ที่ให้ไว้ การเปลี่ยนแปลงสำคัญสองประการที่ฉันทำกับรหัส C ++ คือ:

1) vector ใช้ :: Reserve ()

2) ทำให้อาร์เรย์ 2d แบนเป็น 1d เพื่อให้ได้ตำแหน่งแคชที่ดีขึ้น (บล็อกต่อเนื่อง)

C # (.NET 4.6.1)

private static void TestArray()
{
    const int rows = 5000;
    const int columns = 9000;
    DateTime t1 = System.DateTime.Now;
    double[][] arr = new double[rows][];
    for (int i = 0; i < rows; i++)
        arr[i] = new double[columns];
    DateTime t2 = System.DateTime.Now;

    Console.WriteLine(t2 - t1);

    t1 = System.DateTime.Now;
    for (int i = 0; i < rows; i++)
        for (int j = 0; j < columns; j++)
            arr[i][j] = i;
    t2 = System.DateTime.Now;

    Console.WriteLine(t2 - t1);
}

เวลาทำงาน (Release): เริ่ม: 124ms, Fill: 165ms

C ++ 14 (เสียงดังกราว v3.8 / C2)

#include <iostream>
#include <vector>

auto TestSuite::ColMajorArray()
{
    constexpr size_t ROWS = 5000;
    constexpr size_t COLS = 9000;

    auto initStart = std::chrono::steady_clock::now();

    auto arr = std::vector<double>();
    arr.reserve(ROWS * COLS);

    auto initFinish = std::chrono::steady_clock::now();
    auto initTime = std::chrono::duration_cast<std::chrono::microseconds>(initFinish - initStart);

    auto fillStart = std::chrono::steady_clock::now();

    for(auto i = 0, r = 0; r < ROWS; ++r)
    {
        for (auto c = 0; c < COLS; ++c)
        {
            arr[i++] = static_cast<double>(r * c);
        }
    }

    auto fillFinish = std::chrono::steady_clock::now();
    auto fillTime = std::chrono::duration_cast<std::chrono::milliseconds>(fillFinish - fillStart);

    return std::make_pair(initTime, fillTime);
}

เวลาทำงาน (เผยแพร่): เริ่ม: 398µs (ใช่นั่นคือไมโครวินาที) เติม: 152ms

เวลาใช้งานทั้งหมด: C #: 289ms, C ++ 152ms (เร็วขึ้น 90% โดยประมาณ)

ข้อสังเกต

  • การเปลี่ยนการใช้ C # ไปเป็นการใช้งานอาร์เรย์ 1d เดียวกันให้ผลเริ่มต้น: 40ms, เติม: 171ms, รวม: 211ms ( C ++ ยังเร็วกว่าเกือบ 40% )

  • มันยากกว่ามากในการออกแบบและเขียนรหัส "เร็ว" ใน C ++ กว่าจะเขียนรหัส "ปกติ" ในภาษาใดภาษาหนึ่ง

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

  • ประสิทธิภาพของ C # นั้นค่อนข้างน่าทึ่งเมื่อคุณพิจารณาทุกอย่างที่เกิดขึ้นขณะใช้งานจริง และประสิทธิภาพนั้นค่อนข้างง่ายต่อการเข้าถึง

  • ข้อมูลเพิ่มเติมเกี่ยวกับการเปรียบเทียบประสิทธิภาพของ C ++ และ C #: https://benchmarksgame.alioth.debian.org/u64q/compare.php?lang=gpp&lang2=csharpcore

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

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


16
@Quonux ขอบคุณสำหรับความคิดเห็น แน่นอนว่านี่ไม่ใช่ "โปรแกรมจริง" จุดอ้างอิงคือ refactor มาตรฐาน C # ที่นำเสนอที่อื่นในหน้านี้เป็นหลักฐานว่ารหัส JITted เร็วกว่าแบบดั้งเดิม - ไม่ใช่และมาตรฐานอาจทำให้เข้าใจผิดกับคนใหม่
U007D

9
@Quonux ทำไมคุณต้องเขียนแบบนั้น? เป็นคนที่ชอบคุณที่ทำให้ฉันไม่ชอบการไหลเวียน
Markus Knappen Johansson

5
@MarkusKnappenJohansson ฉันมีวันที่แย่;), ฉันก็เป็นเพียงมนุษย์เช่นกันลบ downvote ของฉัน แต่ความคิดเห็นของฉันยังคงใช้ โอ้ได้โปรดอย่าเกลียดดังนั้นเพียงเพราะมีคน "โง่" บางคน :) ขอให้มีความสุข
Quonux

9
BENCHMARK ที่ผิดพลาดโดยสิ้นเชิง ในรุ่น C ++ คุณเพียงแค่สำรองส่วนหนึ่งของหน่วยความจำ (แล้วก็ประหลาดใจว่าการดำเนินการนั้นใช้เวลาไมโครวินาทีในการดำเนินการอย่างไร) ในเวอร์ชั่น C # คุณกำลังสร้าง 5,000 ARRAYS (อินสแตนซ์ของวัตถุในหน่วยความจำ) C ++ เร็วกว่า C # ... แต่ความแตกต่างอยู่ใกล้ 40% ... ตอนนี้มันอยู่ในช่วง <10% ตัวอย่างของคุณแสดงให้เห็นว่าโปรแกรมเมอร์ควรติดกับภาษาที่เลือกไว้ (และจากโปรไฟล์ของคุณคุณเห็นได้ชัดว่าคุณเป็นโปรแกรมเมอร์ C ++) ใน C # คุณสามารถทำอาร์เรย์ 2 มิติint[,]... ติดตามตัวอย่าง
nikib3ro

3
จากสิ่งที่ฉันสามารถบอกได้รหัสในตัวอย่าง C ++ ของคุณเป็นเพียงการจัดสรรหน่วยความจำล่วงหน้า การใช้งาน PROPER C # เพียงแค่เขียน 'List <double> arrs = new List <double> (ROWS * COLS)' ซึ่งจัดสรรหน่วยความจำที่จำเป็นสำหรับการจัดทำดัชนีอาร์เรย์ 2 มิติในรูปแบบ 1 มิติ (เช่นที่คุณทำใน C ++) ไม่มีเหตุผลใดที่จะจัดสรรอาเรย์ 2 มิติและทำให้แบนด้วยตนเอง - การทำซ้ำจำนวนมากในการทดสอบล่วงหน้าของคุณเป็นสาเหตุของประสิทธิภาพที่น่าเบื่อ ฉันจินตนาการว่าค่าใช้จ่ายจะยังคงอยู่ใน C # มากกว่า แต่จะไม่มากนัก
JDSweetBeat

62

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

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


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

7
@IngeHenriksen: ฉันทราบดีถึงรูปแบบการกำจัด แต่ไม่ได้ช่วยหน่วยความจำที่มีการจัดการเลย
Nemanja Trifunovic

10
@IngeHenriksen การกำจัดมันเพียงทำให้มั่นใจได้ว่าวิธีการกำจัดได้รับการเรียก การกำจัดไม่ทำให้หน่วยความจำที่เก็บรวบรวมขยะว่างเปล่า วิธีการกำจัดมีไว้สำหรับการล้างทรัพยากรที่ไม่มีการจัดการเช่นการจัดการไฟล์และไม่เกี่ยวข้องกับการจัดการหน่วยความจำ
doug65536

1
@NemanjaTrifunovic: "ผู้รวบรวม JIT ไม่สามารถมีเวลามากเกินไปในการเพิ่มประสิทธิภาพขั้นสูง" คุณสามารถอ้างถึงการเพิ่มประสิทธิภาพบางอย่างที่ไม่ได้ทำโดย JIT ได้เพราะจะใช้เวลานานเกินไปหรือไม่
Jon Harrop

5
@ user3800527: แม้ว่าการเพิ่ม RAM จะเป็นไปได้เสมอ (และไม่ใช่ - ลองนึกภาพ Microsoft เพิ่ม RAM ให้กับผู้ใช้ MS Office แต่ละคน) ที่จะไม่แก้ปัญหา หน่วยความจำเป็นแบบลำดับชั้นและโปรแกรม C # จะมีแคชที่หายไปมากกว่า C ++
Nemanja Trifunovic

35

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

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

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

ในกรณีดังกล่าว (และเป็นที่ยอมรับมักจะถูก จำกัด อยู่ในโดเมนปัญหาพิเศษ), C ++ ชนะเทียบกับ C # และภาษาที่เทียบเท่ากัน


6
ที่จริงแล้ว Java VMs (และอาจเป็น. NET) มีความยาวมากเพื่อหลีกเลี่ยงการจัดส่งแบบไดนามิก โดยทั่วไปหากมีวิธีหลีกเลี่ยง polymorphims คุณสามารถมั่นใจได้ว่า VM ของคุณจะทำเช่นนั้น
Martin Probst

3
+1 ฉันมักจะมีปัญหาในการอธิบายสิ่งนี้กับเพื่อนร่วมงาน C # ของฉันที่รู้จัก C ++ เล็กน้อยในแบบที่จะทำให้พวกเขาชื่นชมความสำคัญ คุณอธิบายไว้ค่อนข้างดี
Roman Starkov

9
@crtracy: คุณกำลังเดิมพันโดยไม่มีแอปพลิเคชันการคำนวณประสิทธิภาพสูง พิจารณาการพยากรณ์อากาศชีวสารสนเทศศาสตร์และการจำลองเชิงตัวเลข ความเป็นผู้นำในการปฏิบัติงานของ C ++ ในพื้นที่เหล่านี้จะไม่ลดลงเนื่องจากไม่มีรหัสอื่นใดที่สามารถบรรลุประสิทธิภาพที่เทียบเคียงได้ในระดับเดียวกันของนามธรรมที่สูง
Konrad Rudolph

5
@ จอนแอปเปิ้ลและส้ม การอ้างสิทธิ์เฉพาะของคุณคือ“ C # คือขนาดของคำสั่งเร็วกว่า C ++ ในบริบทของ metaprogramming” ไม่ใช่“ การใช้รหัสที่คอมไพล์แล้วเป็นคำสั่งที่มีขนาดเร็วกว่าการตีความรหัส” ในขณะที่เราอยู่ที่นี่การอ้างสิทธิ์ของคุณว่าการสร้างรหัสรันไทม์นั้น“ กว้างกว่า” มากกว่าการสร้างรหัสเวลาแบบคอมไพล์ก็เป็นสิ่งที่ผิดอย่างชัดเจนด้วย - ทั้งคู่มีจุดแข็งและจุดอ่อน การสร้างรหัสเวลาคอมไพล์ใช้ระบบประเภทเพื่อให้ความปลอดภัยของประเภทคงที่ - การสร้างรหัสรันไทม์ไม่สามารถทำได้ (มันสามารถให้ความปลอดภัยประเภทที่แข็งแกร่ง แต่ไม่ใช่ความปลอดภัยประเภทคงที่ )
Konrad Rudolph

5
@ user3800527 ฉันคิดว่าคุณขาดคำตอบทั้งหมด แน่นอนว่าคุณสามารถหลีกเลี่ยงปัญหานี้ได้ด้วยการทำลาย encapsulation และวางลงในโครงสร้างระดับต่ำ - คุณสามารถเขียนชุดประกอบเป็นภาษาใดก็ได้ สิ่งที่ทำให้ C ++ (เกือบ) เป็นเอกลักษณ์และเหมาะสำหรับการเขียนโปรแกรมประสิทธิภาพสูงคือคุณสามารถสร้างabstractions ระดับสูงที่ไม่มีค่าใช้จ่ายในการใช้งานจริง ดังนั้นคุณไม่จำเป็นต้องเขียนโค้ดเหมือนชุดประกอบใน C ++ เพื่อรับประสิทธิภาพระดับพรีเมียม: การเขียนที่ดีsort(arr, generic_comparer)จะมีประสิทธิภาพเท่ากับลูปที่เขียนด้วยมือใน C ++ มันจะไม่อยู่ใน C #
Konrad Rudolph

20

C ++ (หรือ C สำหรับเรื่องนั้น) ให้คุณควบคุมโครงสร้างข้อมูลของคุณอย่างละเอียด หากคุณต้องการ bit-twiddle คุณมีตัวเลือกนั้น แอป Java หรือ. NET ขนาดใหญ่ที่ได้รับการจัดการ (OWB, Visual Studio 2005 ) ที่ใช้โครงสร้างข้อมูลภายในของไลบรารี Java / .NET มีกระเป๋าสัมภาระติดตัว ฉันได้เห็นเซสชันนักออกแบบ OWB ที่ใช้ RAM และ BIDS มากกว่า 400 MB สำหรับการออกแบบคิวบ์หรือETLเข้าสู่ 100 MB ด้วยเช่นกัน

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

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


19

สำหรับกราฟิกคลาส C # Graphics มาตรฐานจะช้ากว่า GDI ที่เข้าถึงผ่านทาง C / C ++ ฉันรู้ว่านี่ไม่มีส่วนเกี่ยวข้องกับภาษาต่อสิ่งอื่น ๆ อีกมากมายด้วยแพลตฟอร์ม. NET ทั้งหมด แต่กราฟิกเป็นสิ่งที่เสนอให้กับนักพัฒนาเพื่อทดแทน GDI และประสิทธิภาพการทำงานของมันแย่มากฉันไม่กล้าแม้แต่จะทำกราฟิก กับมัน

เรามีเกณฑ์มาตรฐานอย่างง่ายที่เราใช้เพื่อดูว่าไลบรารีกราฟิกเร็วแค่ไหนและนั่นเป็นเพียงการวาดเส้นสุ่มในหน้าต่าง C ++ / GDI ยังคงเร็วกับ 10,000 บรรทัดในขณะที่ C # / กราฟิกมีปัญหาในการทำ 1,000 ในเวลาจริง


5
ฉันรู้สึกทึ่งกับคำตอบของคุณ คุณได้ทดสอบเกณฑ์มาตรฐานเดียวกันกับรหัสที่ไม่ปลอดภัยและกุญแจล็อคและวาดเส้นสุ่มด้วยตัวคุณเองหรือไม่? ตอนนี้ว่าจะเป็นสิ่งที่น่าสนใจไปดูที่
Pedery

2
@ ผู้ผลิตไม่ฉันไม่ได้ เพียงแค่ใช้ GDI และ. NET.Graphics ในวิธีพื้นฐานที่สุด คุณหมายถึงอะไรโดย "การวาดเส้นสุ่มด้วยตัวเอง"?
QBziZ

1
จากนั้นคุณควรลองทดสอบสิ่งนี้เพื่อให้ได้ตัวชี้วัดที่สมจริงยิ่งขึ้นสำหรับความรวดเร็วของ C # นี่เป็นภาพรวมที่ดีของเทคนิค: bobpowell.net/lockingbits.htm
Pedery

6
นั่นไม่ใช่สิ่งที่เราต้องการทำโดยวางพิกเซลแยกกันในบัฟเฟอร์เฟรม หากคุณต้องใช้ทุกอย่างด้วยตัวคุณเองแล้วอะไรคือจุดที่มี API / แพลตฟอร์มในการใช้รหัส สำหรับฉันนี่ไม่ใช่ข้อโต้แย้ง เราไม่จำเป็นต้องใส่พิกเซลแยกใน framebuffer ใน GDI สำหรับการวาดเส้นและเราไม่ได้วางแผนที่จะทำเช่นนี้ใน. NET ในมุมมองของฉันเราใช้ตัวชี้วัดที่เหมือนจริงและ. NET กลับกลายเป็นว่าช้า
QBziZ

1
ฉันมีความคิดเพียงเล็กน้อยว่าการตรวจจับหยดน้ำคืออะไร แต่การระบุเพียงครั้งเดียวนั้นค่อนข้างพิสูจน์ได้ว่าไม่มีอะไรเลย คุณเขียนหนึ่งใน C ++ หรือไม่ ใน JavaScript? และเปรียบเทียบกับหนึ่งใน C # หรือไม่ นอกจากนั้นฉันไม่คิดว่าการตรวจจับหยดกำลังใช้กราฟิกพื้นฐานมากมาย แก้ไขให้ถูกต้องหากฉันผิด แต่ฉันเดาว่ามันเป็นอัลกอริธึมเชิงสถิติในการดำเนินการกับพิกเซล
QBziZ

13

การรวบรวมขยะเป็นเหตุผลหลักที่ทำให้ Java # CANNOT ไม่สามารถใช้กับระบบเรียลไทม์

  1. GC จะเกิดขึ้นเมื่อใด

  2. มันจะใช้เวลานานเท่าไหร่?

นี่คือไม่ได้กำหนด


5
ฉันไม่ใช่แฟน Java ตัวยง แต่ไม่มีอะไรที่บอกว่า Java ไม่สามารถใช้ GC แบบเรียลไทม์ได้
Zan Lynx

5
มีการใช้งาน GC แบบเรียลไทม์มากมายหากคุณสนใจที่จะดู (GC เป็นพื้นที่ที่เต็มไปด้วยเอกสารการวิจัย)
Arafangion

FWIW ริชาร์ดโจนส์เพิ่งตีพิมพ์หนังสือรวบรวมขยะฉบับล่าสุดซึ่งครอบคลุมการออกแบบ GC แบบเรียลไทม์ที่ทันสมัยเหนือสิ่งอื่นใด
Jon Harrop

11
นี่เป็นอาร์กิวเมนต์ที่ไร้สาระ Windows (และ Linux) ไม่ใช่ OS แบบเรียลไทม์ คุณสามารถเปลี่ยนรหัส C ++ ของคุณเป็นจำนวน 18 ช่องได้ตลอดเวลาเช่นกัน
Henk Holterman

2
@HenkHolterman True แต่คุณสามารถเขียนบูทโหลดเดอร์ในแอสเซมบลีเสมอให้ผูกมันไว้ในเคอร์เนล bootstrap สำหรับแอปพลิเคชันของคุณและรันแอป C ++ ของคุณโดยตรงกับฮาร์ดแวร์ (ใน RT btw) คุณไม่สามารถทำสิ่งนี้ใน C # และความพยายามใด ๆ ที่ฉันได้เห็นเพียงการเลียนแบบแอสเซมบลีที่คอมไพล์แล้วใน C # และใช้รหัส C จำนวนมากซึ่งทำให้การใช้ C # นั้นน้อยลง การอ่านทั้งหมดนี้เป็นเรื่องตลกเพราะ C # ไร้ประโยชน์อย่างแท้จริงโดยไม่มีกรอบ NET
zackery.fix

11

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


1
ใน C ++ คุณมีตัวเลือกในการใช้วิธีการจัดสรรที่แตกต่างกันดังนั้นขึ้นอยู่กับวิธีการจัดสรรหน่วยความจำ (AOT?) ใน C # ซึ่งสามารถทำได้ในลักษณะเดียวกัน (แต่เร็วกว่ามาก) ใน C ++
zackery.fix

5
@ zackery.fix .NET มีข้อได้เปรียบที่น่าสนใจในการจัดสรรฮีปเนื่องจากต้องย้ายพอยน์เตอร์เพื่อจัดสรรออบเจ็กต์ใหม่เท่านั้น สิ่งนี้เป็นไปได้เพียงอย่างเดียวเนื่องจากตัวเก็บรวบรวมขยะแบบย่อ แน่นอนคุณสามารถทำสิ่งเดียวกันใน C ++ แต่ C ++ ไม่ทำอย่างนั้น เป็นเรื่องตลกที่คุณใช้อาร์กิวเมนต์เดียวกันเพื่อพูดว่า "C # ทำได้ แต่ไม่ทำดังนั้นจึงเป็นขยะ" และ "C ++ ไม่ได้ แต่ทำได้ดังนั้นจึงน่ากลัว" :)
Luaan

9

ตามปกติมันขึ้นอยู่กับแอปพลิเคชัน มีหลายกรณีที่ C # อาจช้ากว่าและกรณีอื่น ๆ ที่ C ++ เร็วกว่า 5 หรือ 10 เท่าโดยเฉพาะอย่างยิ่งในกรณีที่การดำเนินการสามารถ SIMD ได้ง่าย


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

หมายเหตุจากอนาคต: .NET รองรับ SIMD และเพื่อน ๆ ตั้งแต่ประมาณปี 2014 ถึงแม้ว่ามันจะไม่ได้ใช้กันอย่างแพร่หลาย
Luaan

9

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


2
ผมว่ามันเร็วมากที่สุดของเวลา :)
กับดัก

8

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

โบนัสของ C / C ++ เด่นชัดมากที่สุดถ้าคุณติดโดยตรงกับพอยน์เตอร์และหลีกเลี่ยง Boost std::vectorและคอนเทนเนอร์ระดับสูงอื่น ๆ รวมถึงinlineฟังก์ชั่นเล็ก ๆ ใช้อาร์เรย์โรงเรียนเก่าเมื่อใดก็ตามที่เป็นไปได้ ใช่คุณจะต้องมีบรรทัดของรหัสมากขึ้นเพื่อทำสิ่งเดียวกันกับที่คุณทำใน Java หรือ C # เนื่องจากคุณหลีกเลี่ยงคอนเทนเนอร์ระดับสูง หากคุณต้องการอาร์เรย์ที่มีขนาดแบบไดนามิกคุณจะต้องจำไว้ว่าให้จับคู่new T[]กับdelete[]คำสั่งที่เกี่ยวข้อง(หรือใช้std::unique_ptr) - ราคาสำหรับความเร็วพิเศษคือคุณต้องเขียนโค้ดให้ละเอียดมากขึ้น แต่ในการแลกเปลี่ยนคุณจะกำจัดโอเวอร์เฮดของตัวจัดการหน่วยความจำ / ขยะที่มีการจัดการซึ่งอาจเป็น 20% หรือมากกว่าของเวลาดำเนินการของโปรแกรมเชิงวัตถุอย่างหนักทั้งใน Java และ. NET รวมถึงระบบจัดการขนาดใหญ่ ต้นทุนการทำดัชนีอาร์เรย์ของหน่วยความจำ แอพ C ++ ยังสามารถได้รับประโยชน์จากสวิตช์คอมไพเลอร์ที่ดีในบางกรณี

ฉันเป็นโปรแกรมเมอร์ผู้เชี่ยวชาญใน C, C ++, Java และ C # ฉันเพิ่งมีโอกาสน้อยที่จะใช้โปรแกรมอัลกอริทึมเดียวกันใน 3 ภาษาหลัง โปรแกรมมีการดำเนินการทางคณิตศาสตร์และอาเรย์หลายมิติจำนวนมาก ฉันปรับให้เหมาะสมอย่างมากใน 3 ภาษานี้ ผลลัพธ์เป็นแบบอย่างของสิ่งที่ฉันเห็นโดยทั่วไปในการเปรียบเทียบที่เข้มงวดน้อยกว่า: Java เร็วกว่า C # ประมาณ 1.3 เท่า (JVM ส่วนใหญ่มีการปรับให้เหมาะสมกว่า CLR) และรุ่น C ++ raw pointer มาเร็วกว่า 2.1 เท่า โปรดทราบว่าโปรแกรม C # ใช้รหัสที่ปลอดภัยเท่านั้นซึ่งเป็นความเห็นของฉันที่คุณอาจใช้รหัสใน C ++ ก่อนที่จะใช้unsafeคำหลัก

เกรงว่าทุกคนจะคิดว่าฉันมีอะไรบางอย่างกับ C # ฉันจะปิดโดยพูดว่า C # น่าจะเป็นภาษาที่ฉันชอบ มันเป็นภาษาที่ใช้ในการพัฒนาอย่างมีเหตุผลใช้งานง่ายและรวดเร็วที่สุดเท่าที่ฉันเคยพบมา ฉันทำต้นแบบของฉันทั้งหมดใน C # ภาษา C # มีข้อได้เปรียบเล็ก ๆ น้อย ๆ ที่เหนือกว่า Java (ใช่ฉันรู้ว่า Microsoft มีโอกาสที่จะแก้ไขข้อบกพร่องของ Java จำนวนมากโดยการเข้าเกมช้าและคัดลอก Java) ดื่มอวยพรให้กับCalendarชั้นเรียนของ Java หรือไม่? หาก Microsoft ใช้ความพยายามอย่างแท้จริงในการปรับแต่ง CLR และ. NET JITter ให้ดีที่สุด C # ก็อาจเข้าควบคุมอย่างจริงจัง ฉันประหลาดใจอย่างแท้จริงที่พวกเขายังไม่ได้ทำ - พวกเขาทำหลายสิ่งหลายอย่างในภาษา C # ทำไมไม่ติดตามด้วยการเพิ่มประสิทธิภาพคอมไพเลอร์ที่หนักหน่วง? บางทีถ้าเราทุกคนร้องขอ


3
"คุณจะต้องจำไว้ว่าให้จับคู่คุณnew T[]กับdelete[]" - คุณไม่ต้อง นอกจากstd::unique_ptrจะทำเพื่อคุณ
emlai

ดังที่คุณเขียนบางสิ่งในกราฟิกเหตุใดจึงต้องเขียนรหัสที่ปลอดภัยใน c # คุณได้พิจารณาใช้รหัสที่ไม่ปลอดภัยและเปรียบเทียบอีกครั้งหรือไม่
user3800527

7

> จากสิ่งที่ฉันได้ยิน ...

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

คุณจะตัดสินใจอย่างไรว่าสิ่งที่คนพูดที่นี่น่าเชื่อถือมากหรือน้อยกว่าที่คุณเคยได้ยินมาก่อน

วิธีการหนึ่งที่จะขอหลักฐาน

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

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

  • "ใช้มาตรฐานที่http://shootout.alioth.debian.org/ ด้วยความสงสัยอย่างมากเนื่องจากการทดสอบเลขคณิตเหล่านี้ส่วนใหญ่ซึ่งน่าจะไม่คล้ายกับรหัสของคุณเลย"

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

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

    ถามตัวคุณเองว่าผู้แต่งแสดงให้คุณเห็นหรือไม่ว่าเขาสามารถ "เร่งบางอย่างได้ 4-6 ครั้งขึ้นไป" - มันเป็นเรื่องง่ายที่จะทำ!


ฉันไม่เห็นด้วยกับคุณมากขึ้นและนั่นคือเหตุผลที่ฉันถามในฟอรัมนี้ ... หลังจากนี้คำตอบต้องอยู่ที่ใดที่หนึ่งใช่ไหม? :)
กับดัก

1
ใช่. คำตอบคือ "ขึ้นอยู่กับ"
user49117

6

สำหรับปัญหา 'ขนานที่น่าอับอาย' เมื่อใช้ Intel TBB และ OpenMP บน C ++ ฉันพบว่าประสิทธิภาพเพิ่มขึ้นประมาณ 10 เท่าเมื่อเทียบกับปัญหาที่คล้ายกัน (คณิตศาสตร์บริสุทธิ์) ที่ทำด้วย C # และ TPL SIMD เป็นพื้นที่หนึ่งที่ C # ไม่สามารถแข่งขันได้ แต่ฉันก็รู้สึกว่า TPL มีค่าใช้จ่ายที่ใหญ่มาก

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


5

มันเป็นคำถามที่คลุมเครืออย่างยิ่งโดยไม่มีคำตอบที่ชัดเจน

ตัวอย่างเช่น; ฉันอยากเล่นเกม 3D ที่สร้างขึ้นใน C ++ มากกว่าใน C # เพราะประสิทธิภาพดีขึ้นกว่าเดิมมาก (และฉันรู้ XNA ฯลฯ แต่มันไม่มีทางใกล้กับของจริง)

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


4
คุณช่วยบอกชื่อตัวอย่างได้ไหม? เกมที่เขียนใน C # สิ่งที่คุณพบช้า
Karl

1
แม้แต่แอปพลิเคชันตัวอย่างที่มาพร้อมกับการติดตั้งก็รู้สึกช้า
David The Man

9
ตัวเก็บขยะเป็นความรับผิดชอบอย่างมากในการสร้างเกมด้วย C # เนื่องจากสามารถเตะได้ทุกเวลาทำให้หยุดชั่วคราว การจัดการหน่วยความจำอย่างชัดเจนกลายเป็นเรื่องง่ายสำหรับการพัฒนาเกม
postfuturist

3
เกมที่ทันสมัยส่วนใหญ่มี GPU จำกัด สำหรับเกมดังกล่าวไม่สำคัญว่าตรรกะ (ดำเนินการบน CPU) ช้ากว่า 10% พวกเขายังคงถูก จำกัด โดย GPU ไม่ใช่ CPU ตัวรวบรวมขยะเป็นปัญหาจริงทำให้เกิดการค้างสั้น ๆ แบบสุ่มหากการจัดสรรหน่วยความจำไม่ได้รับการปรับอย่างดี
Michael Entin

2
@postfuturist: นั่นไม่เป็นความจริงบนพีซี ตัวเก็บขยะทำหน้าที่ได้ดีในการเข้าและออกฉันไม่เคยเจอปัญหาใด ๆ เลย อย่างไรก็ตามเมื่อวันที่ Xbox 360 และ Zune / Windows-7-โทรศัพท์, เก็บขยะไม่ได้เกือบเป็นสมาร์ทบนเครื่องคอมพิวเตอร์ ฉันไม่เคยเขียนเลย แต่คนที่บอกฉันว่าตัวเก็บขยะเป็นปัญหาใหญ่
BlueRaja - Danny Pflughoeft

5

ภาษา NET สามารถเร็วเท่ากับรหัส C ++ หรือเร็วกว่าแต่รหัส C ++ จะมีปริมาณงานคงที่มากขึ้นเนื่องจาก. NET runtime ต้องหยุดชั่วคราวสำหรับGCแม้ว่าจะฉลาดมากเกี่ยวกับการหยุดชั่วคราว

ดังนั้นหากคุณมีรหัสที่ต้องทำงานอย่างรวดเร็วอย่างต่อเนื่องโดยไม่หยุดชั่วคราว. NET จะแนะนำเวลาแฝงในบางจุดแม้ว่าคุณจะระมัดระวังเกี่ยวกับ runtime GC ก็ตาม


6
-1: นี่คือตำนานจริง ประการแรกเวลาแฝงของ idiomatic C ++ นั้นแย่มากและมักจะแย่กว่า .NET มากเพราะ RAII ทำให้เกิดการทำลายล้างเมื่อโครงสร้างข้อมูลขนาดใหญ่หลุดออกจากขอบเขตในขณะที่ GCs สมัยใหม่นั้นเพิ่มขึ้นและ NET ก็พร้อมกัน ประการที่สองคุณสามารถลบ GC หยุดชั่วคราวใน. NET โดยไม่จัดสรร
Jon Harrop

2
หากคุณทำสิ่งนี้คุณต้องยกเลิกการใช้ BCL เนื่องจากวิธีการส่วนใหญ่สร้างวัตถุชั่วคราว
Florian Doyon

5
นี่เป็นความจริงทีเดียวมันไม่ได้จนกว่า. net 4 ที่ GC ทำเพิ่มขึ้น เรามีแอพ C # ขนาดใหญ่ที่หยุดเป็นเวลาวินาทีสำหรับ GC สำหรับแอพที่มีประสิทธิภาพที่สำคัญนี่คือนักฆ่า
Justin

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

4
หากคุณไม่สามารถจัดการพฤติกรรมแคชคุณไม่สามารถเอาชนะรหัส c ++ ที่ปรับให้เหมาะสม แคชที่พลาดจาก L1 ไปยังหน่วยความจำหลักอาจทำให้การทำงานของคุณช้าลง 100 เท่า
DAG

4

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

ฉันสงสัยว่ามันทำโดย. NET หรือของ JREs ใด ๆ แต่มันถูกวิจัยกลับเมื่อฉันอยู่ในมหาวิทยาลัยดังนั้นจึงไม่มีเหตุผลที่จะคิดว่าสิ่งเหล่านี้อาจหาทางสู่โลกแห่งความจริงในไม่ช้า .


4

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


4

ฉันได้ทดสอบvectorใน C ++ และ C # ที่เทียบเท่า - Listและ 2d arrays ง่ายๆ

ฉันใช้รุ่น Visual Express C # / C ++ 2010 Express ทั้งสองโปรเจ็กต์เป็นแอปพลิเคชั่นคอนโซลที่เรียบง่ายฉันได้ทดสอบพวกมันในโหมดมาตรฐาน (ไม่มีการตั้งค่าแบบกำหนดเอง) และโหมดดีบัก รายการ C # ทำงานได้เร็วขึ้นบนพีซีของฉันการเริ่มต้นอาร์เรย์ก็เร็วขึ้นใน C # การดำเนินการทางคณิตศาสตร์จะช้าลง

ฉันใช้ Intel Core2Duo P8600@2.4GHz, C # - .NET 4.0

ฉันรู้ว่าการใช้เวกเตอร์นั้นแตกต่างจากรายการ C # แต่ฉันแค่ต้องการทดสอบคอลเลกชันที่ฉันจะใช้เพื่อเก็บวัตถุของฉัน (และความสามารถในการใช้ตัวเข้าถึงดัชนี)

แน่นอนคุณต้องล้างหน่วยความจำ (สมมติว่าสำหรับการใช้งานทุกครั้งnew) แต่ฉันต้องการที่จะทำให้รหัสง่าย

การทดสอบเวกเตอร์ C ++ :

static void TestVector()
{
    clock_t start,finish;
    start=clock();
    vector<vector<double>> myList=vector<vector<double>>();
    int i=0;
    for( i=0; i<500; i++)
    {
        myList.push_back(vector<double>());
        for(int j=0;j<50000;j++)
            myList[i].push_back(j+i);
    }
    finish=clock();
    cout<<(finish-start)<<endl;
    cout<<(double(finish - start)/CLOCKS_PER_SEC);
}

การทดสอบรายการ C #:

private static void TestVector()
{

    DateTime t1 = System.DateTime.Now;
    List<List<double>> myList = new List<List<double>>();
    int i = 0;
    for (i = 0; i < 500; i++)
    {
        myList.Add(new List<double>());
        for (int j = 0; j < 50000; j++)
            myList[i].Add(j *i);
    }
    DateTime t2 = System.DateTime.Now;
    Console.WriteLine(t2 - t1);
}

C ++ - อาร์เรย์:

static void TestArray()
{
    cout << "Normal array test:" << endl;
    const int rows = 5000;
    const int columns = 9000;
    clock_t start, finish;

    start = clock();
    double** arr = new double*[rows];
    for (int i = 0; i < rows; i++)
        arr[i] = new double[columns];
    finish = clock();

    cout << (finish - start) << endl;

    start = clock();
    for (int i = 0; i < rows; i++)
        for (int j = 0; j < columns; j++)
            arr[i][j] = i * j;
    finish = clock();

    cout << (finish - start) << endl;
}

C # - อาร์เรย์:

private static void TestArray()
{
    const int rows = 5000;
    const int columns = 9000;
    DateTime t1 = System.DateTime.Now;
    double[][] arr = new double[rows][];
    for (int i = 0; i < rows; i++)
        arr[i] = new double[columns];
    DateTime t2 = System.DateTime.Now;

    Console.WriteLine(t2 - t1);

    t1 = System.DateTime.Now;
    for (int i = 0; i < rows; i++)
        for (int j = 0; j < columns; j++)
            arr[i][j] = i * j;
    t2 = System.DateTime.Now;

    Console.WriteLine(t2 - t1);

}

เวลา: (การเปิดตัว / การดีบัก)

C ++

  • เริ่มต้นอาร์เรย์ 600/606 ms
  • เติมอาร์เรย์ 200/270 ms
  • 1sec / 13sec เริ่มต้น & เติมเวกเตอร์

(ใช่ 13 วินาทีฉันมักจะมีปัญหากับรายการ / เวกเตอร์ในโหมดแก้ไขข้อบกพร่อง)

ค#:

  • เริ่มต้นอาร์เรย์ 20/20 ms
  • เติมอาร์เรย์ 403/440 ms
  • เริ่มต้น & เติมรายการ 710/742 ms

1
ฉันชอบที่จะเห็นการเข้าถึงดัชนีในรายการมาตรฐาน :: อย่างไรก็ตามจะใช้เวลา 37 วินาทีกับรายการโหมดการเปิดตัว ปล่อยโดยไม่มีการดีบัก: รายการ 3s, เวกเตอร์ 0,3 วินาที อาจเป็นปัญหา dereferencing หรือ sth ตัวอย่าง: nopaste.pl/12fb
Wiory

2
สำหรับการวัดที่แม่นยำยิ่งขึ้นคุณไม่ควรใช้System.DateTime.Nowแต่เป็นคลาสนาฬิกาจับเวลา
แซม

4
ส่วนหนึ่งของเหตุผลที่คุณได้รับเวลาเติมช้าเช่นสำหรับเวกเตอร์ใน C ++ คือคุณกำลังใช้ push_back สิ่งนี้แสดงให้เห็นในโพสต์จำนวนมากว่าช้ากว่าการใช้เมธอด at หรือ operator [] ในการใช้วิธีใดวิธีหนึ่งเหล่านี้คุณต้องใช้วิธีการปรับขนาดหรือสำรอง นอกจากนี้สาเหตุที่การเริ่มต้นของคุณใช้เวลานานมากสำหรับ c ++ vector case คือคุณกำลังบังคับให้ผู้ดำเนินการคัดลอกหรือมอบหมาย [ไม่แน่ใจว่าในกรณีนี้คืออะไร) เพื่อเริ่มต้น c ++ เวกเตอร์ของคุณ สำหรับอาเรย์ใน c ++ มีอัลกอริทึมที่ใช้ 2 การโทรใหม่มากกว่า 5001 และการวนซ้ำเร็วขึ้นเช่นกัน
Zachary Kraus

5
ฉันคิดว่าคุณไม่ได้ทำ c ++ ในวิธีที่เหมาะสม เพียงแค่เหลือบมองและพบปัญหามากมาย เช่น vector <vector <double>> myList = vector <vector <double>>> ()
DAG

2
ว้าว. ไม่แน่ใจว่าสิ่งใดที่สามารถสรุปได้จากการเปรียบเทียบรายการกับอาร์เรย์ที่ปรับขนาดได้ แต่ถ้าคุณจะใช้เวกเตอร์แบบนี้คุณจะต้องเรียนรู้เกี่ยวกับการจอง () เพื่อนของฉันการจอง ()
U007D

3

มันขึ้นอยู่กับ ถ้ารหัสไบต์ถูกแปลเป็นรหัสเครื่อง (และไม่ใช่แค่ JIT) (ฉันหมายถึงถ้าคุณรันโปรแกรม) และถ้าโปรแกรมของคุณใช้การจัดสรร / การจัดสรรคืนจำนวนมากมันอาจเร็วกว่าเพราะอัลกอริทึมGCต้องการเพียงหนึ่งรอบ (ในทางทฤษฎี) ผ่านหน่วยความจำทั้งหมดหนึ่งครั้ง แต่การเรียกใช้ malloc / realloc / free C / C ++ ปกติทำให้เกิดโอเวอร์เฮดสำหรับการโทรทุกครั้ง (การโทรโอเวอร์เฮดโอเวอร์เฮดโครงสร้างข้อมูล

ดังนั้นจึงเป็นไปได้ในทางทฤษฎี (สำหรับภาษา GC อื่น ๆ ด้วย)

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

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


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

1
สำหรับความรักของพระเจ้านี่คือ 8 ปี OMFGz
Quonux


2

ฉันคิดว่ามีแอปพลิเคชันที่เขียนใน C # ทำงานเร็วและมีแอปเขียน C ++ ที่ทำงานเร็วกว่าเดิม (เช่น C ++ เก่ากว่า ... และใช้ UNIX ด้วย ... )
- คำถามคือ - ผู้ใช้คืออะไร และนักพัฒนาบ่นเกี่ยวกับ ... เอา
ล่ะ IMHO ในกรณีของ C # เรามี UI ที่สะดวกสบายเป็นอย่างดีลำดับชั้นของไลบรารีที่ดีมากและระบบอินเตอร์เฟสทั้งหมดของ CLI ในกรณีของ C ++ เรามีเทมเพลต, ATL, COM, MFC และ Shebang ทั้งหมดของ alreadyc ที่เขียนและเรียกใช้โค้ดเช่น OpenGL, DirectX และอื่น ๆ ... นักพัฒนาบ่นว่าการเรียก GC เพิ่มขึ้นอย่างไม่ จำกัด ในกรณีของ C # (หมายถึงโปรแกรมทำงานรวดเร็ว ในหนึ่งวินาที - ปัง! มันติดอยู่)
ในการเขียนโค้ดใน C # นั้นง่ายและรวดเร็ว (อย่าลืมว่ายังเพิ่มโอกาสในการเกิดข้อผิดพลาดในกรณีของ C ++ ผู้พัฒนาบ่นว่าหน่วยความจำรั่ว - หมายถึงทับเรียกระหว่าง DLLs และ DLL DLL - ปัญหากับ การสนับสนุนและการเปลี่ยนไลบรารี่ใหม่โดย ...
ฉันคิดว่าทักษะที่คุณมีในภาษาการเขียนโปรแกรมยิ่งคุณภาพ (และความเร็ว) มากขึ้นจะทำให้ซอฟต์แวร์ของคุณมีลักษณะเฉพาะ


2

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


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

2

ถ้าฉันไม่เข้าใจผิดเทมเพลต C # จะถูกกำหนดที่รันไทม์ สิ่งนี้จะต้องช้ากว่าเทมเพลตเวลาคอมไพล์ของ C ++

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

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

คำตัดสิน:

  • C #: การพัฒนาที่รวดเร็วขึ้นทำงานช้าลง

  • C ++: การพัฒนาที่ช้าวิ่งเร็วกว่า


1

มันขึ้นอยู่กับสิ่งที่คุณพยายามทำให้สำเร็จในรหัสของคุณ ฉันได้ยินมาว่ามันเป็นเพียงเรื่องราวของตำนานเมืองที่มีความแตกต่างของประสิทธิภาพระหว่าง VB.NET, C # และ C ++ ที่ได้รับการจัดการ อย่างไรก็ตามฉันได้พบอย่างน้อยที่สุดในการเปรียบเทียบสตริงที่มีการจัดการ C ++ เต้นกางเกงออกจาก C # ซึ่งจะตีกางเกงออกจาก VB.NET

ฉันไม่เคยทำการเปรียบเทียบที่ละเอียดถี่ถ้วนในความซับซ้อนของอัลกอริทึมระหว่างภาษา ฉันแค่ใช้การตั้งค่าเริ่มต้นในแต่ละภาษา ใน VB.NET ฉันใช้การตั้งค่าเพื่อต้องการประกาศตัวแปร ฯลฯ นี่คือรหัสที่ฉันใช้สำหรับ C ++ ที่ได้รับการจัดการ: (อย่างที่คุณเห็นรหัสนี้ค่อนข้างง่าย) ฉันใช้ภาษาเดียวกันใน Visual Studio 2013 ด้วย. NET 4.6.2

#include "stdafx.h"

using namespace System;
using namespace System::Diagnostics;

bool EqualMe(String^ first, String^ second)
{
    return first->Equals(second);
}
int main(array<String ^> ^args)
{
    Stopwatch^ sw = gcnew Stopwatch();
    sw->Start();
    for (int i = 0; i < 100000; i++)
    {
        EqualMe(L"one", L"two");
    }
    sw->Stop();
    Console::WriteLine(sw->ElapsedTicks);
    return 0;
}

1

มีความแตกต่างที่สำคัญระหว่าง C # และ C ++ ในด้านประสิทธิภาพ:

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

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


0

> หลังจากทั้งหมดคำตอบจะต้องอยู่ที่ไหนสักแห่งใช่ไหม? :)

อืมมม

ตามที่ระบุไว้ในการตอบหลายคำถามนั้นมีการระบุไว้ไม่เกินในรูปแบบที่เชิญคำถามมาตอบไม่ใช่คำตอบ วิธีหนึ่ง:

แล้วโปรแกรมอะไร เครื่องไหน? ระบบปฏิบัติการใด? ชุดข้อมูลใด


ฉันเห็นด้วยอย่างยิ่ง. ฉันสงสัยว่าทำไมคนคาดหวังคำตอบที่แม่นยำ (63.5%) เมื่อพวกเขาถามคำถามทั่วไป ฉันไม่คิดว่าจะไม่มีคำตอบทั่วไปสำหรับคำถามประเภทนี้
โทรหาฉัน Steve

@ callmesteve: ฉันรู้ว่าสิ่งที่คุณหมายถึง แต่ประโยคสุดท้ายของคุณควรจะดูเหมือนว่าเล็บมากกว่ากระดานชอล์กกับโปรแกรมเมอร์ใด ๆ
Wouter van Nifterick

1
สิ่งนี้ดูเหมือนจะไม่ตอบคำถามและอ่านเพิ่มเติมเป็นความคิดเห็นหรือโวยวาย
Tas

-13

โดยได้แรงบันดาลใจจากสิ่งนี้ฉันทำการทดสอบอย่างรวดเร็วโดยมีคำสั่งทั่วไป 60 เปอร์เซ็นต์ที่จำเป็นสำหรับโปรแกรมส่วนใหญ่

นี่คือรหัส C #:

for (int i=0; i<1000; i++)
{
    StreamReader str = new StreamReader("file.csv");
    StreamWriter stw = new StreamWriter("examp.csv");
    string strL = "";
    while((strL = str.ReadLine()) != null)
    {
        ArrayList al = new ArrayList();
        string[] strline = strL.Split(',');
        al.AddRange(strline);
        foreach(string str1 in strline)
        {
            stw.Write(str1 + ",");
        }
        stw.Write("\n");
    }
    str.Close();
    stw.Close();
}

อาเรย์สตริงและรายการอาร์เรย์ที่ใช้โดยเจตนาเพื่อรวมคำแนะนำ

นี่คือรหัส c ++:

for (int i = 0; i<1000; i++)
{
    std::fstream file("file.csv", ios::in);
    if (!file.is_open())
    {
        std::cout << "File not found!\n";
        return 1;
    }

    ofstream myfile;
    myfile.open ("example.txt");
    std::string csvLine;

    while (std::getline(file, csvLine))
    {
        std::istringstream csvStream(csvLine);
        std::vector csvColumn;
        std::string csvElement;

        while( std::getline(csvStream, csvElement, ‘,’) )
        {
            csvColumn.push_back(csvElement);
        }

        for (std::vector::iterator j = csvColumn.begin(); j != csvColumn.end(); ++j)
        {
            myfile << *j << ", ";
        }

        csvColumn.clear();
        csvElement.clear();
        csvLine.clear();
        myfile << "\n";
    }
    myfile.close();
    file.close();
}

ขนาดอินพุตไฟล์ที่ฉันใช้คือ 40 KB

และนี่คือผลลัพธ์ -

  • รหัส C ++ ทำงานใน 9 วินาที
  • รหัส C #: 4 วินาที !!!

โอ้ แต่นี่เป็นลินุกซ์ ... ด้วย C # ทำงานบนMono ... และ C ++ กับ g ++

ตกลงนี่คือสิ่งที่ฉันได้รับบน Windows - Visual Studio 2003 :

  • รหัส C # ทำงานใน 9 วินาที
  • รหัส C ++ - น่ากลัว 370 วินาที !!!

7
คุณกำลังใช้โครงสร้างข้อมูลที่แตกต่างกันและรหัสห้องสมุดที่นั่นถึงแม้ว่า "370 วินาที" จะบ่งบอกถึงสิ่งที่น่ากลัว แต่คุณไม่ได้เรียกใช้มันในโปรแกรมดีบั๊กโดยคุณมีโอกาสใดบ้าง ฉันสงสัยว่าประสิทธิภาพของห้องสมุด CSV ที่คุณใช้นั้นน่าสนใจกว่าประสิทธิภาพของภาษาที่คุณใช้ ฉันจะถามถึงการใช้เวกเตอร์ในบริบทนั้นและการเพิ่มประสิทธิภาพแบบใดที่คุณใช้ นอกจากนี้ยังเป็นที่รู้จักกันอย่างกว้างขวางว่า iostreams (โดยเฉพาะอย่างยิ่ง "myfile << * j <<", ";") นั้นช้ากว่าวิธีอื่น ๆ ในการเขียนไฟล์เป็นอย่างน้อยการปรับใช้ทั่วไปบางอย่าง
Arafangion

6
สุดท้ายคุณก็ทำงานได้มากขึ้นในเวอร์ชัน C ++ (เพราะเหตุใดคุณจึงล้าง csvColumn, csvElement และ csvLines?)
Arafangion

2
การวนซ้ำของ while loop จะเป็นการทำลายและสร้าง std :: istream และ std :: vector และ std :: string ร่างกายในขณะที่ออกจากขอบเขตทุกการทำซ้ำตัวแปรทั้งหมดเหล่านั้นภายในขอบเขตในขณะที่จะทำลายและสร้างในทุกการทำซ้ำ
doug65536

1
จากลักษณะการอ่านรหัส c ++ ของคุณคุณกำลังพยายามคัดลอกจากไฟล์หนึ่งไปยังไฟล์อื่น แทนที่จะใช้การโต้ตอบที่ซับซ้อนระหว่างสตรีมไฟล์สตริงเวกเตอร์และสตรีมสตริงคุณสามารถคัดลอกสตรีมไฟล์อินพุตไปยังสตรีมไฟล์เอาต์พุต สิ่งนี้จะช่วยประหยัดเวลาและหน่วยความจำได้มาก
Zachary Kraus

2
เพื่อทำการทดสอบความเร็วทดสอบสิ่งต่าง ๆ ใน memmory ไม่ต้องไปถึงดิสก์ IO ยกเว้นว่าคุณจะทำการทดสอบกับ SSD รุ่นล่าสุดและเฉพาะสำหรับแอปประสิทธิภาพของคุณ ในขณะที่คอมพิวเตอร์เขียนลงดิสก์อย่างต่อเนื่องแม้ว่าคุณจะไม่ได้แตะแป้นพิมพ์ก็ตาม
user3800527
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.