ตัวอย่างเช่นเครื่องมือSysInternals "FileMon" จากอดีตมีไดรเวอร์โหมดเคอร์เนลที่มีซอร์สโค้ดทั้งหมดในไฟล์ 4,000 บรรทัด เช่นเดียวกันสำหรับโปรแกรม ping แรกที่เคยเขียน (~ 2,000 LOC)
ตัวอย่างเช่นเครื่องมือSysInternals "FileMon" จากอดีตมีไดรเวอร์โหมดเคอร์เนลที่มีซอร์สโค้ดทั้งหมดในไฟล์ 4,000 บรรทัด เช่นเดียวกันสำหรับโปรแกรม ping แรกที่เคยเขียน (~ 2,000 LOC)
คำตอบ:
การใช้หลายไฟล์ต้องใช้ค่าใช้จ่ายในการดูแลระบบเพิ่มเติมเสมอ ต้องทำการติดตั้งสคริปต์การสร้างและ / หรือ makefile ด้วยการรวบรวมและการเชื่อมโยงแยกขั้นตอนตรวจสอบให้แน่ใจว่าการพึ่งพาระหว่างไฟล์ต่าง ๆ ได้รับการจัดการอย่างถูกต้องเขียนสคริปต์ "zip" เพื่อให้ง่ายต่อการแจกจ่ายซอร์สโค้ดด้วยอีเมลหรือดาวน์โหลด บน. โดยทั่วไปแล้ว Modern IDEs ในปัจจุบันมักจะรับภาระจำนวนมาก แต่ฉันค่อนข้างมั่นใจในเวลาที่มีการเขียนโปรแกรม ping แรกไม่มี IDE ดังกล่าวพร้อมใช้งาน และสำหรับไฟล์ที่มีขนาดเล็กถึง ~ 4000 LOC หากไม่มี IDE ที่จัดการไฟล์ได้หลายไฟล์สำหรับคุณการแลกเปลี่ยนระหว่างค่าใช้จ่ายที่กล่าวถึงและประโยชน์จากการใช้ไฟล์หลาย ๆ ไฟล์อาจทำให้ผู้คนตัดสินใจเลือกวิธีการใช้ไฟล์เดียว
เนื่องจาก C ไม่ดีในการทำให้เป็นโมดูล มันทำให้เกิดความยุ่งเหยิง (ไฟล์ส่วนหัวและ #includes ฟังก์ชัน extern ข้อผิดพลาดเกี่ยวกับลิงค์เวลา ฯลฯ ) และยิ่งคุณนำโมดูลเข้ามามากเท่าไหร่ก็ยิ่งมีความยุ่งยากมากขึ้นเท่านั้น
ภาษาที่ทันสมัยกว่ามีความสามารถในการทำให้เป็นโมดูลที่ดีขึ้นในส่วนหนึ่งเนื่องจากพวกเขาเรียนรู้จากความผิดพลาดของ C และทำให้ง่ายต่อการแยกรหัสฐานข้อมูลของคุณออกเป็นหน่วยที่เล็กกว่าและเรียบง่ายกว่า แต่ด้วย C มันจะมีประโยชน์ในการหลีกเลี่ยงหรือลดปัญหาทั้งหมดที่เกิดขึ้นแม้ว่ามันจะหมายถึงการทิ้งสิ่งที่จะถือว่ารหัสมากเกินไปเป็นไฟล์เดียว
นอกเหนือจากเหตุผลที่ผ่านมามีเหตุผลหนึ่งที่จะใช้สิ่งนี้ในซอฟต์แวร์ที่ไวต่อประสิทธิภาพ เมื่อรหัสทั้งหมดอยู่ในหน่วยรวบรวมหนึ่งคอมไพเลอร์จะสามารถทำการปรับให้เหมาะสมทั้งโปรแกรม ด้วยหน่วยการคอมไพล์แยกต่างหากคอมไพเลอร์ไม่สามารถปรับโปรแกรมทั้งหมดให้เหมาะสมในบางวิธี (เช่นการฝังโค้ดไว้)
ตัวเชื่อมโยงสามารถดำเนินการเพิ่มประสิทธิภาพได้อย่างแน่นอนนอกเหนือจากสิ่งที่คอมไพเลอร์สามารถทำได้ แต่ไม่ใช่ทั้งหมด ตัวอย่างเช่น: ตัวเชื่อมโยงที่ทันสมัยใช้งานได้ดีในการขจัดฟังก์ชั่นที่ไม่ได้รับการยืนยัน พวกเขาอาจสามารถทำการปรับให้เหมาะสมอื่น ๆ ได้ แต่ไม่มีสิ่งใดที่คอมไพเลอร์สามารถทำได้ภายในฟังก์ชั่น
ตัวอย่างหนึ่งที่รู้จักกันดีของโมดูลรหัสเดียวคือ SQLite คุณสามารถอ่านเพิ่มเติมเกี่ยวกับเรื่องนี้ได้ในหน้าการควบรวม SQLite
1. บทสรุปผู้บริหาร
ไฟล์ที่มาแยกกันมากกว่า 100 ไฟล์ถูกต่อกันเป็นไฟล์ขนาดใหญ่ไฟล์เดียวของรหัส C ชื่อ "sqlite3.c" และเรียกว่า "the amalgamation" การรวมมีทุกสิ่งที่แอปพลิเคชันต้องฝัง SQLite ไฟล์การควบรวมกิจการมีความยาวมากกว่า 180,000 บรรทัดและมีขนาด 6 เมกะไบต์ขึ้นไป
การรวมรหัสทั้งหมดสำหรับ SQLite เป็นไฟล์ขนาดใหญ่ทำให้ SQLite ง่ายต่อการปรับใช้ - มีเพียงไฟล์เดียวที่จะติดตาม และเนื่องจากรหัสทั้งหมดอยู่ในหน่วยการแปลเดียวคอมไพเลอร์สามารถปรับปรุงการเพิ่มประสิทธิภาพระหว่างโพรซีเดอร์ให้ดีขึ้นส่งผลให้รหัสเครื่องที่อยู่ระหว่าง 5% ถึง 10% เร็วขึ้น
$(CC) $(CFLAGS) $(LDFLAGS) -o $(TARGET) $(CFILES)
กว่าการย้ายทุกอย่างเป็นไฟล์ soudce ไฟล์เดียว คุณยังสามารถทำการคอมไพล์โปรแกรมทั้งหมดเป็นเป้าหมายทางเลือกสำหรับสคริปต์บิลด์แบบดั้งเดิมที่ข้ามการคอมไพล์ไฟล์ต้นฉบับที่ไม่มีการเปลี่ยนแปลงเหมือนกับวิธีที่ผู้คนอาจปิดการทำโปรไฟล์และการดีบักสำหรับเป้าหมายการผลิต คุณไม่มีตัวเลือกนั้นถ้าทุกอย่างอยู่ในแหล่งใหญ่ของแหล่งเดียว ไม่ใช่สิ่งที่คนคุ้นเคย แต่ไม่มีอะไรยุ่งยากเกี่ยวกับเรื่องนี้
นอกเหนือจากปัจจัยด้านความเรียบง่ายที่ผู้ถูกกล่าวถึงกล่าวถึงแล้วโปรแกรม C หลายโปรแกรมถูกเขียนขึ้นโดยบุคคลหนึ่ง
เมื่อคุณมีทีมงานบุคคลมันเป็นที่พึงปรารถนาที่จะแยกแอปพลิเคชันข้ามไฟล์ต้นฉบับหลาย ๆ ไฟล์เพื่อหลีกเลี่ยงความขัดแย้งที่ไม่จำเป็นในการเปลี่ยนรหัส โดยเฉพาะอย่างยิ่งเมื่อมีทั้งโปรแกรมเมอร์ขั้นสูงและรุ่นน้องทำงานอยู่ในโครงการ
เมื่อคนคนหนึ่งทำงานด้วยตัวเองนั่นไม่ใช่ปัญหา
โดยส่วนตัวแล้วฉันใช้ไฟล์หลาย ๆ ไฟล์โดยขึ้นอยู่กับฟังก์ชั่นเป็นเรื่องปกติ แต่นั่นเป็นเพียงฉัน
เพราะ C89 ไม่มีinline
ฟังก์ชั่น ซึ่งหมายความว่าการแบ่งไฟล์ของคุณออกเป็นฟังก์ชั่นทำให้เกิดโอเวอร์เฮดของการผลักดันค่าบนสแต็กและกระโดดไปมา นี่เป็นการเพิ่มค่าใช้จ่ายเล็กน้อยในการนำรหัสไปใช้ในคำสั่ง switch ขนาดใหญ่ 1 รายการ (วนรอบเหตุการณ์) แต่การวนรอบเหตุการณ์มักจะยากที่จะใช้อย่างมีประสิทธิภาพ (หรือถูกต้อง) มากกว่าโซลูชันที่ทำให้เป็นโมดูลมากขึ้น ดังนั้นสำหรับโครงการขนาดใหญ่ผู้คนยังคงเลือกที่จะทำเป็นโมดูล แต่เมื่อพวกเขามีความคิดในการออกแบบล่วงหน้าและสามารถควบคุมสถานะในคำสั่งสวิตช์ 1 พวกเขาเลือกที่
ทุกวันนี้แม้กระทั่งใน C เราก็ไม่จำเป็นต้องเสียสละประสิทธิภาพในการทำให้เป็นโมดูลเพราะแม้แต่ในฟังก์ชั่น C ก็สามารถแทรกเข้ามาได้
inline
คำหลักในคอมไพเลอร์ C89 ไม่สามารถอินไลน์ได้ซึ่งเป็นสาเหตุที่คุณต้องเขียนทุกอย่างในฟังก์ชั่นยักษ์หนึ่งอันไม่ถูกต้อง คุณไม่ควรใช้inline
เป็นเครื่องมือเพิ่มประสิทธิภาพการทำงานโดยทั่วไปคอมไพเลอร์จะรู้ดีกว่าคุณ แต่อย่างใด (และอาจเพิกเฉยต่อคำหลัก)
inline
คำหลักที่มีความหมายลิงเกอร์ที่เกี่ยวข้องซึ่งมีความสำคัญมากกว่าคำถามที่ว่าหรือไม่ที่จะดำเนินการเพิ่มประสิทธิภาพในบรรทัด แต่การใช้งานบางรายที่มีคำสั่งอื่น ๆ ที่จะควบคุมในเยื่อบุและสิ่งดังกล่าวบางครั้งอาจเป็นสิ่งที่สำคัญมาก ในบางกรณีฟังก์ชั่นอาจดูเหมือนว่าใหญ่เกินไปที่จะคุ้มค่ากับการใช้งาน แต่การพับแบบคงที่อาจลดขนาดและเวลาในการประมวลผลให้แทบไม่เหลืออะไรเลย คอมไพเลอร์ที่ไม่ได้รับการเขยิบอย่างแรงที่จะสนับสนุนการเข้าแถวอาจไม่ ...
นี่นับเป็นตัวอย่างของวิวัฒนาการซึ่งฉันประหลาดใจยังไม่ได้กล่าวถึง
ในวันที่มืดของการเขียนโปรแกรมการรวบรวมไฟล์เพียงไฟล์เดียวอาจใช้เวลาหลายนาที หากโปรแกรมถูกทำให้เป็นโมดูลการรวมไฟล์ส่วนหัวที่จำเป็น (ไม่มีตัวเลือกส่วนหัวที่คอมไพล์แล้ว) จะเป็นสาเหตุสำคัญเพิ่มเติมของการชะลอตัว นอกจากนี้คอมไพเลอร์อาจเลือก / จำเป็นต้องเก็บข้อมูลบางอย่างไว้ในดิสก์เองซึ่งอาจไม่มีประโยชน์จากไฟล์สลับอัตโนมัติ
นิสัยที่ปัจจัยสิ่งแวดล้อมเหล่านี้นำไปสู่การดำเนินการพัฒนาอย่างต่อเนื่องและมีการปรับตัวช้าเมื่อเวลาผ่านไป
ในขณะที่กำไรจากการใช้ไฟล์เดียวจะคล้ายกับที่เราได้รับจากการใช้ SSD แทน HDD