การแทนที่รหัสที่ได้รับการปรับปรุงด้วยรหัสที่อ่านได้นั้นเป็นเรื่องปกติหรือไม่


78

บางครั้งคุณพบสถานการณ์ที่คุณต้องขยาย / ปรับปรุงบางรหัสที่มีอยู่ คุณจะเห็นว่ารหัสเก่านั้นผอมมาก แต่มันก็ยากที่จะขยายและใช้เวลาในการอ่าน

มันเป็นความคิดที่ดีที่จะแทนที่ด้วยรหัสที่ทันสมัย?

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

คอมไพเลอร์ดูเหมือนว่าจะเริ่มดีขึ้นเช่นกันดังนั้นสิ่งต่าง ๆ เช่นstruct abc = {}กลายเป็นเงียบ ๆmemset, shared_ptrs ค่อนข้างผลิตรหัสเดียวกันเป็นตัวชี้ดิบ twiddling, แม่แบบทำงานได้ดีสุดเพราะพวกเขาผลิตรหัสซุปเปอร์ลีนและอื่น ๆ

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

เป็นความคิดที่ดีที่จะเปลี่ยนรหัสดังกล่าวถ้าคุณต้องสัมผัสชิ้นส่วนเล็ก ๆ ด้วยวิธีใด?


20
ความสามารถในการอ่านและการปรับให้เหมาะสมนั้นไม่ได้ใช้เวลาส่วนใหญ่
deadalnix

23
ความสามารถในการอ่านสามารถปรับปรุงได้ด้วยความคิดเห็นบางอย่าง?
YetAnotherUser

17
เป็นเรื่องที่น่ากังวลว่า OOP-ification นั้นถือเป็น 'รหัสสมัยใหม่'
James

7
เช่นเดียวกับปรัชญาของ slackware: ถ้ามันไม่พังก็ไม่ได้แก้ไขอย่างน้อยคุณก็มีเหตุผลที่ดีมาก ๆ ที่จะทำมัน
osdamv

5
ด้วยรหัสที่ได้รับการปรับปรุงคุณหมายถึงรหัสที่ได้รับการปรับปรุงจริงหรือที่เรียกว่ารหัสการเพิ่มประสิทธิภาพ
dan04

คำตอบ:


115

ที่ไหน?

  • ในหน้าแรกของเว็บไซต์ Google ก็ไม่สามารถยอมรับได้ เก็บสิ่งต่าง ๆ โดยเร็วที่สุด

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

โดยทั่วไปแล้วข้อกำหนดที่ไม่สามารถใช้งานได้สำหรับส่วนของรหัสที่คุณใช้อยู่มีอะไรบ้าง หากการดำเนินการต้องอยู่ภายใต้ 900 ms ในบริบทที่กำหนด (เครื่องจักร, โหลด, ฯลฯ ) 80% ของเวลาและที่จริงแล้วมันทำงานภายใต้ 200 ms แน่นอนว่า 100% ของเวลาทำให้โค้ดอ่านง่ายขึ้นแม้ว่าจะส่งผลกระทบต่อประสิทธิภาพเล็กน้อย หากในทางตรงกันข้ามการกระทำเดียวกันไม่เคยดำเนินการภายในสิบวินาทีดีคุณควรลองดูว่ามีอะไรผิดปกติกับประสิทธิภาพ (หรือความต้องการในสถานที่แรก)

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


47
+1! หากคุณไม่มีตัวเลขให้รับตัวเลขบางส่วน หากคุณไม่มีเวลารับตัวเลขคุณไม่มีเวลาเปลี่ยน
Tacroy

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

6
แทนที่จะเพิ่มคำตอบอื่นฉัน +1 คำตอบนี้ หากการทำความเข้าใจเกี่ยวกับการแยกส่วนของโค้ดนั้นสำคัญมาก ฉันทำงานในสภาพแวดล้อม C / C ++ / Assembly ด้วยรหัสดั้งเดิมที่มีอายุนับสิบปีกับผู้มีส่วนร่วมนับสิบ หากรหัสใช้งานได้โปรดปล่อยให้อยู่คนเดียวและกลับไปใช้งานได้
Chris K

นั่นเป็นเหตุผลที่ฉันมักจะเขียนโค้ดที่อ่านได้เท่านั้น สามารถไปถึงประสิทธิภาพได้โดยการตัดฮอตสปอตสองสามอัน
Luca

36

โดยปกติไม่มี

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

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

แน่นอนโปรไฟล์โปรไฟล์โปรไฟล์โดยเฉพาะถ้าเป็นพื้นที่เส้นทางที่สำคัญ


2
ใช่ แต่คุณคิดว่าจำเป็นต้องปรับให้เหมาะสม เราไม่รู้เสมอว่าเป็นหรือไม่และเราอาจต้องการพิจารณาสิ่งนี้ก่อน
haylem

2
@haylem: ไม่ฉันคิดว่ารหัสทำงานตามที่เป็นอยู่ ฉันยังสันนิษฐานว่าการปรับเปลี่ยนรหัสนั้นจะทำให้เกิดปัญหาแบบ knock-on ที่อื่นในระบบ (เว้นแต่คุณกำลังจัดการกับรหัสอันน่ารำคาญเล็กน้อยที่ไม่มีการพึ่งพาภายนอก)
Demian Brecht

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

29

โดยย่อ: มันขึ้นอยู่กับ

  • คุณต้องการหรือใช้เวอร์ชันที่ปรับปรุงใหม่ / ปรับปรุงแล้วหรือไม่?

    • จะได้รับเป็นรูปธรรมทันทีหรือในระยะยาว?
    • นี่เป็นเพียงเพื่อการบำรุงรักษาหรือสถาปัตยกรรมจริง ๆ ?
  • จำเป็นต้องปรับให้เหมาะสมจริง ๆ หรือไม่

    • ทำไม?
    • คุณต้องการได้รับเป้าหมายอะไร?

ในรายละเอียด

คุณจะต้องล้างสิ่งที่เป็นเงางามหรือไม่?

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

โดยเฉพาะอย่างยิ่งรู้สิ่งนี้:

มันมีสิ่งที่เรียกว่าOver-Engineering

มันเป็นรูปแบบการต่อต้านและมันมาพร้อมกับปัญหาในตัว:

  • มันอาจจะขยายมากขึ้นแต่มันอาจจะไม่ง่ายที่จะขยาย
  • มันอาจจะไม่ง่ายที่จะเข้าใจ ,
  • สุดท้าย แต่ไม่ท้ายสุดที่นี่: คุณอาจทำให้รหัสทั้งหมดช้าลง

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

คุณจะไม่ต้องการมัน

หลักการ YAGNIไม่สมบูรณ์มุมฉากกับปัญหาอื่น ๆ แต่มันจะช่วยให้ถามตัวเองคำถาม: คุณจะต้องการหรือไม่

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

ถ้ามันไม่พังอย่าแก้ไข

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

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

  • จริง ๆ แล้ว
  • จริง ๆ ต้องทำ
  • ในที่สุดจะต้องทำ
  • และมันทำได้ดีเพียงใด

จำเป็นต้องปรับให้เหมาะสมจริง ๆ หรือไม่

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

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

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

วัด, วัด, วัด

ในฐานะที่เป็นคน Google ตอนนี้มันเป็นเรื่องของข้อมูล! หากคุณสามารถสำรองข้อมูลได้แสดงว่าจำเป็น

มีเรื่องนี้ไม่เก่านักที่ทุก ๆ $ 1 ที่ใช้ในการพัฒนาจะต้องตามมาอย่างน้อย $ 1 ในการทดสอบและอย่างน้อย $ 1 ในการสนับสนุน (แต่จริงๆแล้วมันมีมากขึ้น)

การเปลี่ยนแปลงส่งผลกระทบต่อสิ่งต่างๆมากมาย:

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

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

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


โดยทั่วไป ...

ใช่ แต่...

อย่าเข้าใจฉันผิดโดยทั่วไปฉันยินดีที่จะทำตามที่คุณแนะนำและฉันมักจะสนับสนุน แต่คุณต้องระวังต้นทุนระยะยาว

ในโลกที่สมบูรณ์แบบมันเป็นทางออกที่ถูกต้อง:

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

ในทางปฏิบัติ:

  • คุณอาจทำให้แย่ลง

    คุณต้องการดวงตาที่มากขึ้นเพื่อที่จะมองมันและยิ่งคุณซับซ้อนมันมากขึ้นดวงตาที่คุณต้องการมากขึ้น

  • คุณไม่สามารถทำนายอนาคตได้

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

  • มันแสดงให้เห็นจากมุมมองของผู้บริหารค่าใช้จ่ายมากสำหรับไม่มีกำไรโดยตรง

ทำให้เป็นส่วนหนึ่งของกระบวนการ

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

หากคุณมีกระบวนการที่จะจัดการกับการตัดสินใจดังกล่าวคุณต้องถอดความเป็นส่วนตัวออก:

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

การครอบคลุมการทดสอบการทำโปรไฟล์และการเก็บรวบรวมข้อมูลนั้นเป็นเรื่องยาก

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

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

บทวิจารณ์โค้ดเป็นการทดสอบห้องโถงของทีมพัฒนา

และฉันคิดว่าส่วนสุดท้ายคือกุญแจสำคัญที่นี่: ทำการตรวจสอบโค้ด คุณจะไม่ทราบคุณค่าของการปรับปรุงของคุณหากคุณทำให้พวกเขาเป็นโสด การตรวจสอบโค้ดคือ "การทดสอบห้องโถง" ของเรา: ปฏิบัติตามกฎหมายของ Linus รุ่น Raymondเพื่อตรวจจับข้อบกพร่องและตรวจหาวิศวกรรมและรูปแบบการต่อต้านอื่น ๆ และเพื่อให้แน่ใจว่ารหัสสอดคล้องกับความสามารถของทีมของคุณ ไม่มีจุดในการมีรหัส "ดีที่สุด" หากไม่มีใครอื่น แต่คุณสามารถเข้าใจและบำรุงรักษาได้และนั่นจะเป็นทั้งการเพิ่มประสิทธิภาพที่เป็นความลับและการออกแบบสถาปัตยกรรม 6 ชั้นที่ลึกล้ำ

โปรดจำไว้ว่า:

ทุกคนรู้ว่าการดีบักนั้นยากกว่าการเขียนโปรแกรมตั้งแต่แรก ดังนั้นหากคุณฉลาดเท่าที่จะเป็นเมื่อคุณเขียนมันคุณจะแก้ไขข้อบกพร่องได้อย่างไร - Brian Kernighan


"ถ้ามันไม่พังไม่ต้องแก้ไข" ไปกับการปรับโครงสร้าง ไม่สำคัญว่าจะมีอะไรทำงานได้หรือไม่หากไม่สามารถรักษาได้ต้องมีการเปลี่ยนแปลง
Miyamoto Akira

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

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

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

8

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

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

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

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


8

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

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

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

หากการเพิ่มประสิทธิภาพค่อนข้างเก่าวิธีการที่ใหม่กว่าอาจเร็วกว่าและอ่านได้มากกว่า

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


6

หากการทำโปรไฟล์แสดงให้เห็นว่าการปรับให้เหมาะสมนั้นไม่จำเป็น (มันไม่ได้อยู่ในส่วนที่สำคัญ) หรือแม้กระทั่งมีรันไทม์ที่แย่ลง (เนื่องจากการปรับให้เหมาะสมก่อนกำหนดไม่ดี) ให้แน่ใจว่าแทนที่ด้วยรหัสที่อ่านง่าย

ตรวจสอบให้แน่ใจว่ารหัสนั้นทำงานเหมือนกันกับการทดสอบที่เหมาะสม


5

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

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


4

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

แต่...

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

Martin Fowler เขียนหนังสือเกี่ยวกับเรื่องนี้


3

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

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


3

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

#ifdef READABLE_ALT_IMPLEMENTATION

   double x=0;
   for(double n: summands)
     x += n;
   return x;

#else

   auto subsum = [&](int lb, int rb){
          double x=0;
          while(lb<rb)
            x += summands[lb++];
          return x;
        };
   double x_fin=0;
   for(double nsm: par_eval( subsum
                           , partitions(n_threads, 0, summands.size()) ) )
     x_fin += nsm;
   return x_fin;

#endif

3

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

  1. ค้นหาการทดสอบประสิทธิภาพและสนับสนุนข้อมูลการทำโปรไฟล์ หากไม่มีการทดสอบประสิทธิภาพสิ่งที่สามารถยืนยันได้โดยไม่มีหลักฐานสามารถยกเลิกได้โดยไม่มีหลักฐาน ยืนยันว่ารหัสที่ทันสมัยของคุณเร็วขึ้นและลบรหัสเดิม หากใครก็ตามที่โต้แย้ง (แม้แต่ตัวคุณเอง) ขอให้พวกเขาเขียนรหัสการทำโปรไฟล์เพื่อพิสูจน์ว่าแบบใดที่เร็วกว่า
  2. หากรหัสการทำโปรไฟล์มีอยู่ให้เขียนรหัสที่ทันสมัยอยู่ดี <function>_clean()ชื่อมันบางอย่างเช่น จากนั้น "แข่ง" รหัสของคุณกับรหัสที่ไม่ดี หากรหัสของคุณดีกว่าให้ลบรหัสเดิมออก
  3. หากรหัสเก่าเร็วขึ้นให้ทิ้งรหัสที่ทันสมัยไว้ในนั้น มันทำหน้าที่เป็นเอกสารที่ดีสำหรับสิ่งที่โค้ดอื่น ๆ มีไว้เพื่อทำและเนื่องจากมีรหัส "race" อยู่ที่นั่นคุณจึงสามารถรันมันต่อไปเพื่อทำเอกสารคุณสมบัติด้านประสิทธิภาพและความแตกต่างระหว่างสองพา ธ นอกจากนี้คุณยังสามารถทดสอบหน่วยสำหรับความแตกต่างในการทำงานของโค้ด ที่สำคัญรหัสที่ทันสมัยจะเอาชนะรหัส "เพิ่มประสิทธิภาพ" ในหนึ่งวันรับประกัน จากนั้นคุณสามารถลบรหัสที่ไม่ดีได้

QED


3

ถ้าฉันสามารถสอนโลกได้สิ่งหนึ่ง (เกี่ยวกับซอฟต์แวร์) ก่อนที่ฉันจะตายฉันจะสอนมันว่า "ประสิทธิภาพเทียบกับ X" เป็นปัญหาที่ผิดพลาด

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

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

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


กุญแจสำคัญของประสิทธิภาพในหลาย ๆ กรณีคือการมีรหัสทำงานให้มากที่สุดเท่าที่จะทำได้ในรูปแบบที่สามารถทำได้อย่างมีประสิทธิภาพ สิ่งหนึ่งที่ทำให้ฉันหงุดหงิดกับ. NET ก็คือมันไม่มีกลไกที่มีประสิทธิภาพเช่นการคัดลอกส่วนหนึ่งของคอลเลกชันหนึ่งไปอีกที่หนึ่ง คอลเลกชันส่วนใหญ่เก็บกลุ่มของรายการต่อเนื่องจำนวนมาก (หากไม่ใช่สิ่งของทั้งหมด) ในอาร์เรย์ดังนั้นเช่นการคัดลอก 5,000 รายการสุดท้ายจากรายการ 50,000 รายการควรแยกย่อยเป็นการดำเนินการคัดลอกจำนวนมาก (ถ้าไม่ใช่แค่หนึ่ง) และอีกไม่กี่รายการ ขั้นตอนดำเนินการไม่เกินครั้งละไม่กี่ครั้ง
supercat

น่าเสียดายที่แม้ในกรณีที่การดำเนินการดังกล่าวเป็นไปได้อย่างมีประสิทธิภาพก็มักจะจำเป็นต้องมีการวนรอบ "ใหญ่" สำหรับ 5,000 ซ้ำ (และในบางกรณี 45,000!) หากการดำเนินการสามารถลดลงไปยังสิ่งต่าง ๆ เช่นคัดลอกอาร์เรย์จำนวนมากจากนั้นการดำเนินการเหล่านั้นสามารถปรับให้เหมาะกับองศาที่รุนแรงซึ่งให้ผลตอบแทนที่สำคัญ หากการวนซ้ำแต่ละรอบต้องทำตามขั้นตอนเป็นสิบ ๆ ครั้งมันเป็นการยากที่จะปรับให้เหมาะสมโดยเฉพาะอย่างยิ่ง
supercat

2

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

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

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


1
หนึ่งในคนที่ฉันทำงานด้วยตอนนี้ชอบที่จะปรับสิ่งต่าง ๆ ในพื้นที่ที่ผู้ใช้เข้าชมเดือนละครั้งถ้าเป็นเช่นนั้น มันต้องใช้เวลาและไม่บ่อยนักที่ทำให้เกิดปัญหาอื่น ๆ เพราะเขาชอบโค้ดและคอมมิชชันและปล่อยให้ QA หรือฟังก์ชั่นดาวน์สตรีมอื่น ๆ ทดสอบจริง ๆ : / เพื่อความเป็นธรรมโดยทั่วไปเขาเร็วเร็วและแม่นยำ แต่เงิน "การเพิ่มประสิทธิภาพ" เพนนี ante เหล่านี้เพียงทำให้สิ่งที่ยากขึ้นสำหรับส่วนที่เหลือของทีมและการเสียชีวิตถาวรของพวกเขาจะเป็นสิ่งที่ดี
DaveE

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

พวกเขาทำเพราะเขาทำได้ ที่จริงแล้วเขามักจะบันทึกวงจรบางอย่าง แต่เมื่อผู้ใช้โต้ตอบกับองค์ประกอบของโปรแกรมใช้เวลาจำนวนหนึ่ง (15 ถึง 300-ish) โกนหนวดหนึ่งในสิบวินาทีของรันไทม์เพื่อแสวงหา "ประสิทธิภาพ" นั้นโง่ โดยเฉพาะอย่างยิ่งเมื่อคนที่ติดตามเขาต้องใช้เวลาจริงเพื่อเข้าใจสิ่งที่เขาทำ นี่เป็นแอปพลิเคชั่น PowerBuilder ที่สร้างขึ้นเมื่อ 16 ปีที่แล้วดังนั้นเมื่อพิจารณาถึงแหล่งกำเนิดของสิ่งที่ความคิดเข้าใจได้ แต่เขาปฏิเสธที่จะปรับปรุงความคิดของเขาให้เป็นความจริงในปัจจุบัน
DaveE

@DaveE: ฉันคิดว่าฉันเห็นด้วยกับคนที่คุณทำงานด้วยมากกว่าที่คุณ หากฉันไม่ได้รับอนุญาตให้แก้ไขสิ่งที่ช้าโดยไม่มีเหตุผลที่ดีฉันจะเสียสติ ถ้าฉันเห็นบรรทัดของ C ++ ที่ใช้ตัวดำเนินการ + ซ้ำ ๆ เพื่อรวบรวมสตริงหรือรหัสที่เปิดและอ่าน / dev / urandom ทุกครั้งที่ผ่านลูปเพียงเพราะมีคนลืมตั้งค่าสถานะฉันจะแก้ไขมัน ด้วยความคลั่งไคล้เกี่ยวกับเรื่องนี้ฉันได้พยายามเร่งความเร็วเมื่อคนอื่น ๆ ยอมให้มันเลื่อนทีละหนึ่งไมโครวินาที
Zan Lynx

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

2

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

และรหัสที่ "อ่านไม่ออก" ไม่สามารถปรับให้เหมาะสมได้เสมอ

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


2

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

ดังนั้นรหัสจะถูกปรับให้เหมาะสม + การแสดงความคิดเห็นที่เหมาะสมจะทำให้อ่านได้เช่นกัน

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


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

2

นี่คือตัวอย่างเพื่อดูความแตกต่างระหว่างรหัสอย่างง่ายและรหัสที่ได้รับการปรับปรุง: https://stackoverflow.com/a/11227902/1396264

ในตอนท้ายของคำตอบที่เขาเพิ่งแทนที่:

if (data[c] >= 128)
    sum += data[c];

ด้วย:

int t = (data[c] - 128) >> 31;
sum += ~t & data[c];

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

สิ่งนี้ดำเนินการในเวลาน้อยกว่าหนึ่งในสี่ของเวลาดั้งเดิม (11.54sec เทียบกับ 2.5sec)


1

คำถามหลักที่นี่คือ: จำเป็นต้องเพิ่มประสิทธิภาพ?

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

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

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


1

นี่คือวิธีที่ฉันทำสิ่งต่าง ๆ : อันดับแรกฉันทำให้มันทำงานในโค้ดที่อ่านได้จากนั้นฉันก็ปรับมันให้เหมาะสม ฉันเก็บต้นฉบับดั้งเดิมและบันทึกขั้นตอนการเพิ่มประสิทธิภาพของฉันไว้

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


0

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

บทความเกี่ยวกับการปรับให้เหมาะสมแบบไม่รู้สึกไมโคร :

ในฐานะส่วนใหญ่ของเราฉันรู้สึกเหนื่อยที่จะอ่านโพสต์บล็อกเกี่ยวกับการปรับให้เหมาะสมแบบไม่ใช้ความรู้สึกเช่นการเปลี่ยนการพิมพ์ด้วย echo, ++ $ i โดย $ i ++ หรือเครื่องหมายคำพูดคู่ด้วยคำพูดเดี่ยว ทำไม? เนื่องจากเวลา 99.999999% นั้นไม่เกี่ยวข้อง

"print" ใช้ opcode มากกว่าหนึ่งอย่าง "echo" เพราะมันจะส่งคืนบางสิ่ง เราสามารถสรุปได้ว่าเสียงสะท้อนนั้นเร็วกว่าการพิมพ์ แต่หนึ่งรหัสไม่มีค่าใช้จ่ายไม่มีอะไรจริงๆ

ฉันได้ลองติดตั้ง WordPress ใหม่แล้ว สคริปต์หยุดทำงานก่อนที่จะจบลงด้วย "ข้อผิดพลาดของรถบัส" บนแล็ปท็อปของฉัน แต่จำนวน opcodes นั้นมากกว่า 2.3 ล้านแล้ว พูดพอแล้ว.


0

การเพิ่มประสิทธิภาพเป็นญาติ ตัวอย่างเช่น:

พิจารณาชั้นเรียนที่มีสมาชิกบูลจำนวนหนึ่ง:

// no nitpicking over BOOL vs bool allowed
class Pear {
 ...
 BOOL m_peeled;
 BOOL m_sliced;
 BOOL m_pitted;
 BOOL m_rotten;
 ...
};

คุณอาจถูกล่อลวงให้แปลงเขตข้อมูล BOOL เป็นบิตฟิลด์:

class Pear {
 ...
 BOOL m_peeled:1;
 BOOL m_sliced:1;
 BOOL m_pitted:1;
 BOOL m_rotten:1;
 ...
};

เนื่องจาก BOOL ถูกพิมพ์เป็น INT (ซึ่งบนแพลตฟอร์ม Windows เป็นจำนวนเต็ม 32 บิตที่ได้รับการรับรอง) สิ่งนี้ใช้เวลาสิบหกไบต์และแพ็คให้เป็นหนึ่งเดียว นั่นคือการออม 93%! ใครจะบ่นเกี่ยวกับเรื่องนี้?

สมมติฐานนี้:

เนื่องจาก BOOL ถูกพิมพ์เป็น INT (ซึ่งบนแพลตฟอร์ม Windows เป็นจำนวนเต็ม 32 บิตที่ได้รับการรับรอง) สิ่งนี้ใช้เวลาสิบหกไบต์และแพ็คให้เป็นหนึ่งเดียว นั่นคือการออม 93%! ใครจะบ่นเกี่ยวกับเรื่องนี้?

นำไปสู่:

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

สิ่งที่เคยเป็น

 push [ebx+01Ch]      ; m_sliced
 call _Something@4    ; Something(m_sliced);

กลายเป็น

 mov  ecx, [ebx+01Ch] ; load bitfield value
 shl  ecx, 30         ; put bit at top
 sar  ecx, 31         ; move down and sign extend
 push ecx
 call _Something@4    ; Something(m_sliced);

รุ่น bitfield ใหญ่กว่าเก้าไบต์

นั่งลงแล้วทำเลขคณิต สมมติว่าแต่ละฟิลด์ bitfielded เหล่านี้มีการเข้าถึงหกครั้งในรหัสของคุณสามครั้งสำหรับการเขียนและสามครั้งสำหรับการอ่าน ค่าใช้จ่ายในการเติบโตของรหัสอยู่ที่ประมาณ 100 ไบต์ จะไม่เท่ากับ 102 ไบต์เนื่องจากเครื่องมือเพิ่มประสิทธิภาพอาจใช้ประโยชน์จากค่าที่ลงทะเบียนแล้วสำหรับการดำเนินการบางอย่างและคำแนะนำเพิ่มเติมอาจมีค่าใช้จ่ายแอบแฝงในแง่ของความยืดหยุ่นในการลงทะเบียนที่ลดลง ความแตกต่างที่แท้จริงอาจมากกว่านั้นอาจจะน้อยกว่า แต่สำหรับการคำนวณด้านหลังของซองจดหมายลองเรียกมันว่า 100 ในขณะเดียวกันการประหยัดหน่วยความจำคือ 15 ไบต์ต่อคลาส ดังนั้นจุดคุ้มทุนคือเจ็ด หากโปรแกรมของคุณสร้างคลาสน้อยกว่าเจ็ดอินสแตนซ์ค่าใช้จ่ายของรหัสนั้นเกินกว่าการประหยัดข้อมูล: การเพิ่มประสิทธิภาพหน่วยความจำของคุณคือการลดความจำ

อ้างอิง

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