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


48

สมมติฐาน

  1. ข้อดีอย่างหนึ่งของไลบรารีส่วนหัวเท่านั้นสำหรับ C ++ คือไม่จำเป็นต้องรวบรวมแยกต่างหาก

  2. ใน C และ C ++ inlineเหมาะสมเมื่อฟังก์ชันถูกกำหนดในไฟล์ส่วนหัว *

  3. ตามเนื้อผ้ามีการใช้รูปแบบ C, .c / .h โดยที่ส่วนหัวแสดงส่วนติดต่อสาธารณะที่น้อยที่สุดของหน่วยการแปล ในทำนองเดียวกัน. cpp / hpp

คำถาม

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

* - การกำหนดฟังก์ชั่นในส่วนหัวช่วยให้คอมไพเลอร์สามารถเห็นการใช้งานในระหว่างการรวบรวมหน่วยการแปลใด ๆ และทำให้สามารถสร้างโค้ดอินไลน์ได้


2
คุณจะแปลกใจว่าตัวเชื่อมโยง C ++ สมัยใหม่จำนวนมาก (GCC, MSVC, ICC และอื่น ๆ ) สามารถแทรกโค้ดในหน่วยการแปลที่แยกกันได้อย่างไร ฉันจะพูดว่า "โดยทั่วไปไม่" ในมุมมองประสิทธิภาพเนื่องจากจำนวนครั้งที่เครื่องมือเพิ่มประสิทธิภาพ linkers ท้าทายความคาดหวังของฉันและจัดการให้เป็นแบบอินไลน์ต่อไป (ซึ่งไม่รวมบริบท dylib ที่ฝังอยู่ในส่วนหัว . อย่างไรก็ตามไลบรารีที่เป็นส่วนหัวเท่านั้นโดยที่พวกเขามีความเสถียรทั้งในส่วนต่อประสานและการนำไปใช้งานนั้นมีความเซ็กซี่เพราะความง่ายในการปรับใช้ในโครงการใหม่

1
ฉันไม่ทราบว่าสิ่งนี้สมควรได้รับคำตอบแบบเต็ม แต่ข้อดีอย่างหนึ่งของ libs เท่านั้นคือความง่ายในการติดตั้งและการใช้งาน: ดาวน์โหลด #include "lib.h (pp)" เสร็จแล้ว
WeRelic

คำตอบ:


44

ข้อดีอย่างหนึ่งของไลบรารีเฉพาะส่วนหัวสำหรับ C ++ คือไม่จำเป็นต้องรวบรวมแยกต่างหาก

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

ใน C และ C ++ แบบอินไลน์ทำให้เข้าใจได้เฉพาะเมื่อมีการกำหนดฟังก์ชันในไฟล์ส่วนหัว *

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

ตามเนื้อผ้ามีการใช้รูปแบบ C, .c / .h โดยที่ส่วนหัวแสดงส่วนติดต่อสาธารณะที่น้อยที่สุดของหน่วยการแปล ในทำนองเดียวกัน. cpp / hpp

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

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

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

IMHO ความนิยมของ libs ส่วนหัวเท่านั้นเกิดจากความนิยมของการเขียนโปรแกรมเมตาเทมเพลต สำหรับคอมไพเลอร์ส่วนใหญ่ templated libs จะต้องเป็นส่วนหัวเท่านั้นเนื่องจากคอมไพเลอร์สามารถเริ่มต้นกระบวนการคอมไพล์หลักได้เมื่อมีการระบุพารามิเตอร์ประเภทและสำหรับการคอมไพล์และการเพิ่มประสิทธิภาพอย่างเต็มรูปแบบคอมไพเลอร์ต้องเห็น "ทั้งสองอย่างทันที" ค่าพารามิเตอร์ ซึ่งทำให้เป็นไปไม่ได้ (หรืออย่างน้อยที่สุด) เพื่อสร้างหน่วยการคอมไพล์ "precompiled" สำหรับไลบรารีดังกล่าว


6
ดังนั้นในระยะสั้นห้องสมุดส่วนหัวเท่านั้นมีความสะดวกสบายมากกว่ามากขึ้นมีประสิทธิภาพ ; และเนื่องจาก C ++ ไม่มีผู้จัดการแพ็คเกจมาตรฐานสิ่งนี้จะช่วยผลักดันการยอมรับ
Matthieu M.

6
@ MatthieuM: ไม่บางครั้งรหัสที่คอมไพล์อาจมีประสิทธิภาพมากขึ้นและสำหรับ libs เทมเพลตการออกแบบส่วนหัวเท่านั้นโดยทั่วไปไม่ใช่คำถามของความสะดวกสบาย และเวลาในการรวบรวมที่เพิ่มขึ้นนั้นไม่สะดวกสบายอย่างแน่นอน
Doc Brown

การมีรหัสร้อนในส่วนหัวอาจนำไปสู่การรวบรวมรหัสที่มีประสิทธิภาพมากขึ้นอย่างไรก็ตามเรื่องนี้ไม่จำเป็นต้องมีรหัสทั้งหมดในส่วนหัวและดังนั้นจึงเป็นอิสระ IMHO จากห้องสมุดส่วนหัวเท่านั้น
Matthieu M.

1
@ MatthieuM: นั่นถูกต้องแน่นอนอย่างไรก็ตามฉันคิดว่าคำว่า "สะดวกกว่า" ไม่ได้อธิบายกรณีอย่างชัดเจน
Doc Brown

3
ฉันทำงานในโครงการฝังตัวขนาดใหญ่ด้านบนของ OS ที่บางลงและเก่ากว่าสำหรับนายจ้างคนก่อนของฉันและในกรณีเหล่านั้นฉันสามารถยืนยันถึงความเจ็บปวดจากการรวบรวมครั้งที่ยาวนาน ใครก็ตามที่จับการบรรจุไฟล์ส่วนหัวมากเกินไปจะได้รับการจัดการอย่างไร้ความปราณี
Fred Thomsen

15

ก่อนอื่นเราจะทำลายสมมติฐานบางส่วนของคุณ:

  1. ข้อดีอย่างหนึ่งของไลบรารีส่วนหัวเท่านั้นสำหรับ C ++ คือไม่จำเป็นต้องรวบรวมแยกต่างหาก

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

  1. ใน C และ C ++ แบบอินไลน์ทำให้รู้สึกได้เฉพาะเมื่อมีการกำหนดฟังก์ชันในไฟล์ส่วนหัว *

ใช่เอฟเฟกต์เดียวที่inlineเหลืออยู่คือข้อยกเว้นสำหรับกฎข้อจำกัดความเดียว
วิบัติแก่เจ้าหากคำจำกัดความเหล่านั้นแตกต่างไปในทางใดทางหนึ่ง

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

  1. ตามเนื้อผ้ามีการใช้รูปแบบ C, .c / .h โดยที่ส่วนหัวแสดงส่วนติดต่อสาธารณะที่น้อยที่สุดของหน่วยการแปล ในทำนองเดียวกัน. cpp / hpp

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

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

PIMPLรูปแบบการออกแบบใช้สำหรับลดรายละเอียดดังกล่าว

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

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

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

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

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

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