ฉันเพิ่มประสิทธิภาพก่อนเวลาอันควรหรือไม่


9

ขณะนี้ฉันอยู่ในขั้นตอนการออกแบบของสถาปัตยกรรมที่อิงส่วนประกอบใน C ++

การออกแบบปัจจุบันของฉันรวมถึงการใช้งานคุณสมบัติต่างๆเช่น:

  • std::vectors ของstd::shared_ptrs เพื่อเก็บส่วนประกอบ
  • std::dynamic_pointer_cast
  • std::unordered_map<std::string,[yada]>

ส่วนประกอบจะแสดงข้อมูลและตรรกะของรายการต่าง ๆ ที่จำเป็นในซอฟต์แวร์เช่นเกมเช่นกราฟิกฟิสิกส์ AI เสียง ฯลฯ

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

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

เนื่องจากฉันอยู่ในขั้นตอนการออกแบบของสถาปัตยกรรมและสิ่งเหล่านี้จะรวมอยู่ในหลักของการออกแบบฉันควรพยายามหาวิธีที่จะหลีกเลี่ยงพวกเขาตอนนี้เนื่องจากมันจะยากมากที่จะเปลี่ยนในภายหลังหากมีประสิทธิภาพ ปัญหา?

หรือฉันเพิ่งถูกจับในการเพิ่มประสิทธิภาพก่อนวัยอันควร?


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

1
คำตอบของคำถามนี้เกือบจะเป็น "ใช่" !!
Mawg กล่าวว่าคืนสถานะโมนิก้า

2
@Mawg "... แต่เราไม่ควรพลาดโอกาสที่สำคัญ 3%" ตั้งแต่นี้เป็นแกนหลักของการออกแบบฉันจะรู้ได้อย่างไรว่าฉันทำงานกับ 3% นี้หรือไม่
Vaillancourt

1
คะแนน excelelnt, Alexandre (+1) และใช่ฉันรู้ว่าในช่วงครึ่งหลังของคำพูดซึ่งแทบจะไม่เคยพูดถึง :-) แต่เพื่อกลับไปที่ความคิดเห็นของฉันก่อนหน้านั้น (ซึ่งสะท้อนให้เห็นในคำตอบ acecpted) , the answer to this question is almost always a resounding "YES !!". ฉันยังรู้สึกว่ามันจะดีกว่าถ้าให้มันทำงานก่อน & ปรับให้เหมาะสมในภายหลัง แต่ YMMV ทุกคนมีความคิดเห็นของเขาซึ่งทั้งหมดนั้นถูกต้องและมีเพียง OP เท่านั้นที่สามารถตอบคำถามส่วนตัวของเขาได้
Mawg กล่าวว่าคืนสถานะโมนิก้า

1
@AlexandreVaillancourt อ่านต่อเอกสารของ Knuth (PDF ข้อความอ้างอิงมาจากด้านขวาของหน้าชื่อ 268 หน้า 8 ในโปรแกรมอ่าน PDF) "... เขาจะฉลาดที่จะพิจารณาอย่างรอบคอบถึงรหัสวิกฤติ แต่หลังจากรหัสนั้นได้รับการระบุแล้วมันมักจะเป็นความผิดพลาดในการตัดสินใจเกี่ยวกับสิ่งที่ส่วนต่าง ๆ ของโปรแกรมมีความสำคัญอย่างยิ่งเนื่องจากประสบการณ์สากลของ โปรแกรมเมอร์ที่ใช้เครื่องมือวัดนั้นไม่สามารถเดาได้ง่าย " (เน้นเขา)
8bittree

คำตอบ:


26

ไม่ต้องอ่านอะไรนอกจากชื่อเรื่อง: ใช่

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

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

Fwiw: https://xkcd.com/1691/


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

10
ฉันอยากจะชี้ให้เห็นว่าบรรทัดแรกไม่เป็นความจริงเพราะการปรับให้เหมาะสมอยู่เสมอก่อนวัยอันควร แต่เนื่องจากการเพิ่มประสิทธิภาพนั้นไม่ได้เกิดขึ้นก่อนเวลาถ้าคุณรู้ว่าคุณต้องการมันในกรณีนี้คุณจะไม่ถามเกี่ยวกับเรื่องนี้ ดังนั้นบรรทัดแรกนั้นเป็นจริงเพียงเพราะความจริงที่ว่าคุณกำลังถามคำถามเกี่ยวกับการปรับให้เหมาะสมก่อนกำหนดหมายความว่าคุณไม่แน่ใจว่าคุณต้องการการปรับให้เหมาะสมซึ่งตามคำจำกัดความทำให้เกิดก่อนกำหนด วุ้ย.
Jörg W Mittag

@ JörgWMittag: เห็นด้วย
steffen

3

ฉันไม่คุ้นเคยกับ C ++ แต่โดยทั่วไปมันขึ้นอยู่กับ

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

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

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


3

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


1

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

unordered_map<string,[yada]>

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

ฉันสมมติว่าสตริงเป็นคีย์บางชนิดเช่น ID ส่วนประกอบ ถ้าเป็นเช่นนั้นสิ่งนี้ทำให้ราคาถูกลงอย่างมากแล้ว:

unordered_map<int,[yada]>

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

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

vector<[yada]> // the index and key become one and the same

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

เป็นตัวอย่างที่ไร้เดียงสาซอฟต์แวร์ประมวลผลวิดีโอที่จับคู่โค้ดทั้งหมดกับสิ่งนี้:

// Abstract pixel that could be concretely represented by
// RGB, BGR, RGBA, BGRA, 1-bit channels, 8-bit channels, 
// 16-bit channels, 32-bit channels, grayscale, monochrome, 
// etc. pixels.
class IPixel
{
public:
    virtual ~IPixel() {}
    ...
};

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

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

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.