เหตุใดจึงยากที่จะให้ประสิทธิภาพขณะใช้ห้องสมุด


10

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

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

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

ในนัดเดียว :

  • สิ่งที่ทำให้เขียนโค้ดด้วยตัวเองรับประกันของประสิทธิภาพการทำงาน?
  • ทำไมจึงมีความเสี่ยงในการพึ่งพาเฟรมเวิร์ก / ไลบรารีเมื่อคุณต้องรับประกันประสิทธิภาพสูง?

1
คุณช่วยชี้แจงคำถามที่แน่นอนได้ไหม? บางทีคำตอบที่เป็นไปได้ที่คุณนึกไว้อาจช่วยได้เช่นกัน
Amir Ali Akbari

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

คำตอบ:


4

มีการกระทำเกมเขียนใหม่กว่าและมากกว่าตัวเอง (และยังคงทำมัน) ปฏิกิริยาทันทีของฉันคือการปรับตัว

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

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

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

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

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

จนถึงตอนนี้มันไม่เกี่ยวกับ C / C ++ แต่ถ้าด้วยเหตุผลบางอย่างคุณไม่สามารถเปลี่ยนกรอบงานได้เช่นคุณต้องทำการแปลงข้อมูลสองครั้งเพื่อเปลี่ยนจากปลายด้านหนึ่งไปอีกด้านหนึ่งโดยทั่วไปคุณจะต้องใช้บางสิ่งที่ช่วยลดค่าใช้จ่ายเพิ่มเติม ในกรณีของฉันตัวแปลง TAI-> UTC หรือ UTC-> TAI ดีที่สุดคือ raw C (หรือ FPGA) ไม่มีความสง่างามที่เป็นไปได้ไม่มีโครงสร้างข้อมูลอัจฉริยะที่ลึกซึ้งซึ่งทำให้เกิดปัญหาเล็กน้อย มันเป็นเพียงประโยคเปลี่ยนที่น่าเบื่อและทำไมไม่ใช้ภาษาที่คอมไพเลอร์เก่งในการปรับให้เหมาะสม


1
+1 นั่นอาจเป็นความผิดของฉันที่ไม่ชัดเจนในโพสต์ของฉันดังนั้นคนอื่นไม่เคยได้รับมาก่อน นี่เป็นคำตอบที่ฉันต้องการอย่างแน่นอน ขอบคุณ
รูเบนส์

7

ฉันไม่คิดว่าทุกคนจะมาถึง C / C ++ เมื่อประสิทธิภาพเป็นปัญหา

ข้อได้เปรียบในการเขียนรหัสระดับต่ำคือการใช้รอบ CPU น้อยลงหรือบางครั้งหน่วยความจำน้อยลง แต่ฉันทราบว่าภาษาระดับสูงกว่าสามารถโทรไปยังภาษาระดับต่ำกว่าและทำเพื่อรับค่านี้บางส่วน ภาษา Python และ JVM สามารถทำได้

ตัวอย่างเช่นนักวิทยาศาสตร์ด้านข้อมูลที่ใช้ Scikit-Learn บนเดสก์ท็อปของเธอกำลังเรียกรูทีนพื้นฐานที่ได้รับการปรับให้เหมาะสมที่สุดเพื่อทำการบีบตัวเลข ไม่มีจุดในการเขียนรหัสใหม่สำหรับความเร็ว

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

ภาษาระดับสูงจะช่วยให้คุณสามารถใช้อัลกอริธึมการกระจายที่ซับซ้อนมากขึ้นในเวลาของนักพัฒนามากกว่า C / C ++ ในระดับมาตราส่วนอัลกอริทึมอย่างชาญฉลาดที่มีการเคลื่อนไหวของข้อมูลที่ดีกว่าจะเอาชนะรหัสเนทีฟใบ้

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

ฉันไม่เข้าใจการติดตามเกี่ยวกับ "การอนุญาต" และ "ปิดการใช้งาน" และ "ยืนยัน" หรือไม่


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

1
ไม่เป็นคำถามที่ดีคุณสามารถสะท้อนความคิดเห็นของคุณได้ที่นี่เพื่อแก้ไขคำถามหากคุณต้องการ
Sean Owen

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

4

ดังที่เราทราบในโลกดิจิทัลมีหลายวิธีที่จะทำงานเดียวกัน / รับผลลัพธ์ที่คาดหวัง ..

และความรับผิดชอบ / ความเสี่ยงที่มาจากรหัสอยู่บนไหล่ของนักพัฒนา ..

นี่คือขนาดเล็ก แต่ฉันคิดว่าเป็นตัวอย่างที่มีประโยชน์มากจาก. NET โลก ..

นักพัฒนา. NET จำนวนมากใช้ BinaryReader ในตัว - BinaryWriter ในการจัดลำดับข้อมูลเพื่อประสิทธิภาพ / รับการควบคุมกระบวนการ

นี่คือซอร์สโค้ด CSharp ของ FrameWork ที่สร้างขึ้นในคลาส BinaryWriter 'หนึ่งในวิธีการเขียนที่โอเวอร์โหลด:

// Writes a boolean to this stream. A single byte is written to the stream
// with the value 0 representing false or the value 1 representing true.
// 
public virtual void Write(bool value) 
{
     //_buffer is a byte array which declared in ctor / init codes of the class
    _buffer = ((byte) (value? 1:0));

    //OutStream is the stream instance which BinaryWriter Writes the value(s) into it.
    OutStream.WriteByte(_buffer[0]);
}

ตามที่คุณเห็นวิธีการนี้สามารถเขียนได้โดยไม่ต้องกำหนดค่าเพิ่มเติมให้กับตัวแปร _buffer:

public virtual void Write(bool value) 
{
    OutStream.WriteByte((byte) (value ? 1 : 0));
}

หากไม่มีการกำหนดเราอาจได้รับมิลลิวินาทีเล็กน้อย .. มิลลิวินาทีไม่กี่นี้สามารถยอมรับว่าเป็น "เกือบไม่มีอะไร" แต่จะเกิดอะไรขึ้นถ้ามีการเขียนหลายพัน (เช่นในกระบวนการเซิร์ฟเวอร์)

สมมติว่า "น้อย" คือ 2 (มิลลิวินาที) และอินสแตนซ์หลายพันเป็นเพียง 2.000 .. ซึ่งหมายถึงเวลาดำเนินการมากขึ้น 4 วินาที 4 วินาทีกลับมาในภายหลัง ..

ถ้าเรายังคงอยู่ภายใต้. NET และถ้าคุณสามารถตรวจสอบซอร์สโค้ดของ BCL -. NET Base Class Library- จาก MSDN คุณสามารถเห็นประสิทธิภาพที่หายไปจำนวนมากจากนักพัฒนาตัดสินใจ ..

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

กำไรเล็กน้อยนี้ทำให้เรามีประสิทธิภาพโดยรวม ..

และถ้าเรากลับไปที่ BinaryWriter.Write () วิธีการ ..

ที่จริงแล้วการกำหนดให้กับการนำ _buffer มาใช้ไม่ใช่ข้อผิดพลาดของนักพัฒนานี่เป็นการตัดสินใจที่จะ "อยู่ในที่ปลอดภัย"!

สมมติว่าเราตัดสินใจที่จะไม่ใช้ _buffer และตัดสินใจที่จะใช้วิธีที่สอง .. ถ้าเราพยายามส่งหลายพันไบต์ผ่านสาย (เช่นอัพโหลด / ดาวน์โหลดข้อมูล BLOB หรือ CLOB) ด้วยวิธีที่สองมันล้มเหลวโดยทั่วไปเพราะ การเชื่อมต่อขาดหายไป .. เพราะเราพยายามส่งข้อมูลทั้งหมดโดยไม่ตรวจสอบและควบคุมกลไกเมื่อการเชื่อมต่อขาดหายไปทั้งเซิร์ฟเวอร์และลูกค้าไม่เคยรู้ว่าข้อมูลที่ส่งมาเสร็จสมบูรณ์หรือไม่

หากนักพัฒนาตัดสินใจที่จะ "อยู่ในที่ปลอดภัย" โดยปกติจะหมายถึงต้นทุนด้านประสิทธิภาพขึ้นอยู่กับกลไก "อยู่ในที่ปลอดภัย" ที่นำมาใช้

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

และข้อสังเกตเล็ก ๆ : ผู้พัฒนาห้องสมุดเชิงพาณิชย์พยายามที่จะอยู่ในที่ปลอดภัยเสมอเพราะพวกเขาไม่รู้ว่ารหัสของพวกเขาจะใช้ที่ใด


4

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

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

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

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

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

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

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