สิ่งที่ดีที่สุดสำหรับการเข้ารหัสในสภาพแวดล้อมการรวบรวมช้า


15

ฉันเคยเขียนโค้ดใน C # ในรูปแบบ TDD - เขียน / หรือเปลี่ยนรหัสเล็ก ๆ ของคอมไพล์อีกครั้งใน 10 วินาทีของการแก้ปัญหาทั้งหมดเรียกใช้การทดสอบอีกครั้งและอีกครั้ง ง่าย...

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

ผลผลิตของฉันยังคงโอเคสำหรับโครงการขนาดเล็ก แต่มันแย่ลงเมื่อการเพิ่มขนาดของโครงการและเมื่อรวมเวลาในการรวบรวม 10+ นาทีมันแย่มาก และถ้าฉันพบข้อผิดพลาดฉันต้องเริ่มต้นการรวบรวมอีกครั้ง ฯลฯ นั่นเป็นเพียงการทำลายอย่างหมดจด

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

ด้วย C # และ TDD มันง่ายมากที่จะเขียนโค้ดในรูปแบบของวิวัฒนาการ - หลังจากทำซ้ำหลายสิบครั้งไม่ว่าอะไรก็ตามที่ฉันเริ่มด้วยอึก็จบลงด้วยรหัสที่ดี แต่มันก็ไม่ได้ผลสำหรับฉันอีกต่อไป สภาพแวดล้อม)


stackoverflow.com/questions/5078409/…อาจรวมเข้าด้วยกัน / ในที่เดียว
เบ็น L

ดู laso stackoverflow.com/questions/373142/…สำหรับการเร่งเวลาการคอมไพล์ C ++
Eclipse

2
เริ่มการต่อสู้ด้วยดาบ ; p
Steven Jeuris

ครั้งสุดท้ายที่ฉันใช้ C ++ อย่างจริงจังโดยใช้ส่วนหัวที่รวบรวมไว้ล่วงหน้าลดเวลาในการรวบรวมโดยปัจจัยสี่
gnasher729

คำตอบ:


16

มีหลายสิ่งที่อยู่ในใจของฉัน:

  1. ทำให้การใช้งานของการรวบรวมการกระจาย คุณสามารถทำสิ่งนี้กับ GCC ("distCC"?) หรือ VC ( Xoreax 'IncrediBuildไม่ได้ราคาถูก แต่คุ้มค่าทุก ๆ ร้อยที่ใช้ไป)

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

  3. โปรแกรมต่อต้านโครงการทดสอบขนาดเล็กมากกว่าการสมัครขนาดใหญ่ทั้งหมด

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

  5. การลงทุนในฮาร์ดแวร์ เมล็ดซีพียูมากขึ้น (ในเครื่องของคุณหรือในอื่น ๆ ) จะแปลกใจกับการรวบรวมแบบกระจายและหน่วยความจำจำนวนมากบวกกับดิสก์ที่รวดเร็ว (SSD แทนที่จะเป็น HDD) จะช่วยได้มาก หากคุณมีระบบ 64 บิตและ RAM ที่มีอนาจารการรวบรวมบนดิสก์ RAM อาจให้การเพิ่มความเร็วอย่างไม่น่าเชื่อ


1
แคชคอมไพเลอร์เป็นความคิดที่ดีกว่าการรวบรวมแบบกระจายในประสบการณ์ของฉัน
pqnet

เมื่อพูดถึง RAM disk กับ SSD ฉันรู้สึกประหลาดใจมากที่ไม่ได้เพิ่มความเร็วในการรวบรวมมากนัก โครงการปัจจุบันของฉัน (Java บน Android) คอมไพล์จากสถานะคลีนใน ~ 45 วินาทีจาก SSD และใน ~ 40 วินาทีจากดิสก์ RAM (และ toolchain ทั้งหมดอยู่ในดิสก์ RAM ไม่ใช่แหล่งที่มา) ไม่เพิ่มขึ้นอย่างมากฉันพูด
Haspemulator

10

โซลูชันทางเทคนิคอื่นที่ไม่ได้กล่าวถึงโดยบุคคลอื่นกำลังเปลี่ยนไปใช้โซลิดสเตตไดรฟ์แทนฮาร์ดไดรฟ์ทั่วไป ในโครงการก่อนหน้านี้ที่ฉันทำงานอยู่ SSD ได้ลดเวลาในการสร้างจากช่วง 30 นาทีถึง 3

แน่นอนพวกเขามีราคาแพง สำหรับหัวหน้าของคุณให้คำนวณราคาของเวลานักพัฒนาที่สูญหายกับราคาของการลงทุนครั้งเดียว การลงทุนอาจจ่ายให้ตัวเองในไม่กี่เดือน


6
นั่นดูน่าสนใจ. นั่นบอกว่า 90% ของเวลาบิลด์คือเวลาแฝงดิสก์ I / O
Mike Dunlavey

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

1
นี่เป็นความคิดที่ดี นอกจากนี้การติดตั้งส่วนหนึ่งของ RAM บนระบบไฟล์ของคุณจะทำงานได้อย่างรวดเร็วและราคาถูก
Goran Jovic

2
Ramdisk เร็วยิ่งขึ้น (และถูกกว่า)
SK-logic

1
@ จอห์น: ใช่คอมไพเลอร์ที่เขียนได้ดีควร (IMHO) ต้องเป็น I / O
Mike Dunlavey

3

การวางแผนเพิ่มเติมเขียนโค้ดในกลุ่มที่ใหญ่กว่าเขียนการทดสอบการรวมแทนการทดสอบหน่วยและเรียกใช้ชุดการสร้าง + ทดสอบข้ามคืน


3

เวลาในการรวบรวมที่ยาวนานเป็นปัญหาบางครั้ง แต่การแยกส่วนที่กล่าวมาแล้วสามารถช่วยเอาชนะได้ (ส่วนใหญ่)

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

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

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


1
เด็กชายนั่นเป็นสถานการณ์จากนรก ฉันจำวันเมนเฟรมได้ เราทำการตรวจสอบรหัสจำนวนมาก มันน่าทึ่งมากที่ได้ทำเช่นนั้นเช่นการจำลองการบินที่ไม่มีที่สิ้นสุดสู่ดวงจันทร์
Mike Dunlavey

3

ฉันจำได้ง่ายเมื่องานสร้างใช้เวลานาน วิธีการบรรเทาผลกระทบบางอย่าง:

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

2

10+ นาทีสำหรับการรวบรวม? อย่างจริงจัง?

คุณใช้ IDE ที่สร้างสิ่งปลูกสร้างเพิ่มเติม (เช่น Eclipse) หรือไม่? ถ้าไม่เช่นนั้นคุณควรจะเป็นมันจะทำการคอมไพล์พื้นฐานในไม่กี่วินาทีแทนที่จะเป็นนาที

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


5
10 นาทีมีขนาดเล็ก ฉันทำงานโครงการที่ใช้เวลาหนึ่งชั่วโมงในการรวบรวมและเชื่อมโยงตั้งแต่เริ่มต้นบนเครื่องแกนเดียว PCH และทั้งหมด แน่นอนยกเว้นสำหรับรุ่นอัตโนมัติสร้างไม่มีใครจะสร้างมันบนแกนประมวลผลเพียงตัวเดียว แต่ยัง ... ถ้าคุณต้องเปลี่ยนบางอย่างในส่วนหัวที่รวมทุกที่ (การจัดการสตริงการจัดการข้อผิดพลาด) คุณสามารถไปถั่ว
sbi

2
เคยทำงาน (เมื่อหลายปีก่อน) บนระบบที่ใช้ในการรวบรวม 48 ชั่วโมงเพื่อคอมไพล์ แน่นอนว่างานสร้างเต็มรูปแบบเพิ่งจะเริ่มในคืนวันศุกร์หวังว่าจะเสร็จเมื่อเรากลับมาที่สำนักงานในวันจันทร์ เราสร้างโมดูลขนาดเล็กแทนตามความจำเป็น (พูด DLL เดียว)
jwenting

2
-1 กับความคิดเห็นทั้งหมดข้างต้นหากฉันสามารถ +1 ไปที่ TrueDub ได้ ใช่ถ้าคุณกำลังคอมไพล์ใหม่ทุกอย่างมันอาจใช้เวลานานมาก อย่างไรก็ตามหากความคิดใด ๆ ที่มอบให้แก่การจัดการการพึ่งพาโครงการการคอมไพล์ซ้ำทั้งหมด 10 ชั่วโมงสามารถมีการคอมไพล์ซ้ำเพิ่มขึ้นในเวลาน้อยกว่าหนึ่งนาทีเป็นบรรทัดฐาน คุณทุกคนควรละอายใจที่ต้องเสียเวลารอให้คอมไพล์ของคุณเมื่อใช้สติปัญญาเล็กน้อยจะช่วยประหยัดเวลาได้มาก
Dunk

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

2
@Dunk: มันเป็น บริษัท ขนาดเล็กที่มีนักพัฒนาน้อยกว่าโหลที่ทำงานในโครงการหลาย MLoC นั่นเป็นอย่างมากที่แตกต่างกันจากหลายร้อยของนักพัฒนาทำเช่นนั้นคุณจะไม่สามารถเขียนอะไรจากรอยขีดข่วนเพราะคุณจะต้องปีจะทำเช่นนั้น เท่าที่ฉันเกลียดความคิดการลงทุนในการรวบรวมแบบกระจายนั้นเป็นไปได้ทางเศรษฐกิจการเขียนใหม่ไม่ได้ โอ้และฉันได้รับส่วนต่อประสานเหล่านั้น :-xเมื่อสิบปีก่อนฉันไม่ได้อยู่ที่นั่นเมื่อพวกเขาคิดถึง (ผมเปลี่ยนไปมากของรหัสที่จะจ้าง TMP เพื่อหาข้อผิดพลาดขึ้นในการรวบรวมและน้อยในสนาม.)
เอสบีไอ

2

ข้อแรกทำไมใช้เวลารวบรวมนานตั้งแต่แรก

  • สภาพแวดล้อมของคุณ (IDE, ทำ, อะไรก็ตาม) สนับสนุนการสร้างที่เพิ่มขึ้นหรือไม่? ตรวจสอบให้แน่ใจว่าคุณกำลังคอมไพล์การเปลี่ยนแปลงใหม่เท่านั้นไม่ใช่ทั้งหมด
  • หากคุณมีเครื่องมัลติคอร์ IDE ของคุณอาจรองรับการคอมไพล์แบบขนาน ฉันรู้สำหรับข้อเท็จจริงที่ว่า Visual Studio ทำเช่นนั้น เห็นได้ชัดว่า gcc เพื่อให้ได้เครื่องจักรที่ดีขึ้นและเปิดใช้งานการคอมไพล์แบบขนาน
  • พิจารณาใช้ส่วนหัว precompiled
  • หากคุณลองทั้งหมดและการรวบรวมยังช้าให้ตรวจสอบรหัสของคุณ มองหาการพึ่งพาที่ไม่จำเป็น คุณรวมส่วนหัวที่มีการประกาศล่วงหน้าเพียงพอหรือไม่ พิจารณาใช้สำนวน PIMPL เพื่อลดการพึ่งพาส่วนหัว

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

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

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


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

1
+1 สำหรับ PIMPL ฉันทำงานในโครงการที่เวลาสร้างไม่สามารถควบคุมได้ ในโครงการนั้นฉันไม่สนใจว่ามีส่วนหัวอื่น ๆ รวมอยู่ในส่วนหัวของแต่ละคนอย่างไร ในโครงการต่อไปของฉันฉันทำมันเป็นจุดที่จะลดสิ่งนี้โดยการใช้ PIMPL อย่างกว้างขวาง เวลาในการสร้างยังคงยอดเยี่ยมแม้ว่าโครงการที่สองน่าจะมีขนาดใหญ่เป็นสองเท่าของโครงการแรก
Jason B

1

คุณอาจต้องใช้วิธีการหลายง่าม:

1) ระบบสร้างได้เร็วขึ้น แกน / RAM / ดิสก์จำนวนมากเท่าที่คุณสามารถจ่ายได้ สำหรับโครงการ C ++ ที่มีขนาดใหญ่กว่าคุณจะพบว่าดิสก์นั้นมักจะเป็นตัว จำกัด จำนวน

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

3) บิวด์ส่วนเพิ่ม / กระจายบิลด์ / แคชตามความเหมาะสมกับสภาพแวดล้อมของคุณ ในบางระบบ distcc (อาคารแบบกระจาย) และ ccache (การแคชของสิ่งที่สร้างขึ้นบางส่วน) สามารถประหยัดเวลาในการรวบรวมได้มาก

4) ตรวจสอบให้แน่ใจว่างานสร้างของคุณสามารถขนานได้ดี ในสภาพแวดล้อม makefile โดยเฉพาะอย่างยิ่งมันไม่ยากที่จะเข้าไปในสถานการณ์ที่คุณบังเอิญทำการเซ็ต Makefiles โดยที่คุณไม่สามารถสร้างสิ่งก่อสร้างแบบขนานได้


0

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

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


0

@sbi และ @Michael Kohne พูดว่าอะไร

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

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

นั่นนำเรามาถึงจุดที่คำสั่งการคอมไพล์แต่ละรายการสามารถทำขนานกันอย่างหนาแน่น 'distcc' บนเครื่องที่ช้าให้สร้าง / scons -j8 บนเครื่องที่มัลติคอร์ สิ่งนี้ทำให้งานสร้างเต็มไปจนถึงไม่กี่นาที

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

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