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


35

TD; DR:

มีความสับสนเกี่ยวกับสิ่งที่ฉันถามดังนั้นนี่คือแนวคิดการขับขี่ที่อยู่เบื้องหลังคำถาม:

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

และคำถามไม่ได้เกี่ยวกับ ...

ไม่เกี่ยวกับการเพิ่มประสิทธิภาพขนาดเล็กการปรับให้เหมาะสมก่อนวัยและอื่น ๆ มันไม่เกี่ยวกับ "เพิ่มประสิทธิภาพส่วนนี้หรือส่วนที่ตาย"

ถ้าเช่นนั้นจะเป็นอะไร

เป็นเรื่องเกี่ยวกับระเบียบวิธีและเทคนิคโดยรวมและวิธีคิดเกี่ยวกับการเขียนโค้ดที่เกิดขึ้นเมื่อเวลาผ่านไป:

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

มันเกี่ยวกับวิธีการและรูปแบบของรหัสที่ปัจจุบัน - ภายในทศวรรษนี้ - เห็นและสนับสนุนในกรอบการทำงานส่วนใหญ่ที่สนับสนุนการประชุมส่งต่อผ่านชุมชน มันเป็นการเปลี่ยนความคิดจาก 'monolithic blocks' เป็น 'microservices' และด้วยราคานั้นในแง่ของประสิทธิภาพระดับเครื่องและค่าโสหุ้ยและค่าใช้จ่ายระดับโปรแกรมเมอร์บางส่วนเช่นกัน

คำถามเดิมดังนี้:

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

  • เขียนโค้ดฟังก์ชั่นที่เล็กลง (ทดสอบได้และบำรุงรักษาได้มากกว่านี้)
  • refactor โค้ดที่มีอยู่แล้วให้เป็นโค้ดที่เล็กลงเรื่อย ๆ จนกระทั่งส่วนใหญ่ของเมธอด / ฟังก์ชั่นของคุณมีความยาวเพียงไม่กี่บรรทัดและชัดเจนว่าจุดประสงค์ของมันคืออะไร (ซึ่งสร้างฟังก์ชั่นได้มากกว่าเมื่อเทียบกับบล็อกขนาดใหญ่)
  • ฟังก์ชั่นการเขียนที่ทำสิ่งเดียวเท่านั้น - การแยกข้อกังวล ฯลฯ (ซึ่งมักจะสร้างฟังก์ชั่นมากขึ้นและเฟรมเพิ่มเติมในสแต็ก)
  • สร้างไฟล์เพิ่มเติม (หนึ่งคลาสต่อไฟล์, คลาสที่มากขึ้นสำหรับวัตถุประสงค์ในการย่อยสลาย, สำหรับวัตถุประสงค์เลเยอร์เช่น MVC, สถาปัตยกรรมโดเมน, รูปแบบการออกแบบ, OO, ฯลฯ ซึ่งสร้างการเรียกระบบไฟล์เพิ่มเติม)

นี่คือการเปลี่ยนแปลงเมื่อเปรียบเทียบกับการเข้ารหัสแบบ "เก่า" หรือ "ล้าสมัย" หรือ "ปาเก็ตตี้" ซึ่งคุณมีวิธีการที่ครอบคลุม 2,500 บรรทัดและคลาสขนาดใหญ่และวัตถุเทพเจ้าทำทุกสิ่ง

คำถามของฉันคือ:

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

รายละเอียด

ในขณะที่ฉันไม่คุ้นเคยอย่างใกล้ชิดกับวิธีการจัดการรหัส OO และวิธีการเรียกใช้ใน ASM ในตอนท้ายและวิธีที่การเรียก DB และคอมไพเลอร์การแปลไปยังแขน actuator บน HDD แผ่นเสียงฉันมีความคิดบางอย่าง ฉันคิดว่าการเรียกฟังก์ชั่นพิเศษแต่ละครั้งการเรียกวัตถุหรือการโทร "#include" (ในบางภาษา) สร้างชุดคำสั่งเพิ่มเติมซึ่งเป็นการเพิ่มปริมาณของรหัสและเพิ่มค่าใช้จ่าย "การเดินสายรหัส" โดยไม่ต้องเพิ่มรหัส "ประโยชน์" จริง . ฉันยังนึกภาพว่าการเพิ่มประสิทธิภาพที่ดีสามารถทำได้กับ ASM ก่อนที่มันจะทำงานบนฮาร์ดแวร์ แต่การเพิ่มประสิทธิภาพนั้นก็ทำได้เช่นกันเช่นกัน

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

อัปเดตเพื่อความชัดเจน:

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

มีการกล่าวว่ามีบางแห่ง (quote TBD) ที่มากถึง 70% ของรหัสทั้งหมดประกอบด้วยคำสั่ง MOV ของ ASM - การโหลด CPU register ที่มีตัวแปรที่เหมาะสมไม่ใช่การคำนวณจริง ในกรณีของฉันคุณโหลดเวลาของ CPU ด้วยคำแนะนำ PUSH / POP เพื่อให้การเชื่อมโยงและพารามิเตอร์ผ่านระหว่างส่วนต่าง ๆ ของรหัส ยิ่งคุณสร้างโค้ดให้น้อยลงคุณจำเป็นต้องมี "การเชื่อมโยง" ของโสหุ้ยมากขึ้น ฉันกังวลว่าการเชื่อมโยงนี้จะเพิ่มในซอฟแวร์ที่ขยายตัวและชะลอตัวลงและฉันสงสัยว่าฉันควรจะกังวลเกี่ยวกับเรื่องนี้หรือไม่และถ้ามีมากแค่ไหนเพราะโปรแกรมเมอร์รุ่นปัจจุบันและอนาคตที่กำลังสร้างซอฟต์แวร์สำหรับศตวรรษหน้า จะต้องอยู่กับและบริโภคซอฟต์แวร์ที่สร้างขึ้นโดยใช้วิธีการเหล่านี้

อัปเดต: หลายไฟล์

ฉันกำลังเขียนรหัสใหม่ในขณะนี้ซึ่งจะเป็นการแทนที่รหัสเก่าอย่างช้าๆ โดยเฉพาะฉันได้ตั้งข้อสังเกตว่าหนึ่งในชั้นเรียนเก่าเป็นไฟล์ ~ 3000 บรรทัด (ดังกล่าวก่อนหน้า) ตอนนี้มันกำลังกลายเป็นชุดของไฟล์ 15-20 ที่ตั้งอยู่ในไดเรกทอรีต่าง ๆ รวมถึงไฟล์ทดสอบและไม่รวมถึงเฟรมเวิร์ก PHP ที่ฉันใช้เพื่อผูกบางสิ่งเข้าด้วยกัน มีไฟล์เพิ่มเติมเข้ามาเช่นกัน เมื่อพูดถึงดิสก์ I / O การโหลดหลายไฟล์จะช้ากว่าการโหลดไฟล์ขนาดใหญ่หนึ่งไฟล์ แน่นอนว่าไม่ใช่ทุกไฟล์ที่โหลดมันจะโหลดตามต้องการและมีตัวเลือกแคชดิสก์และตัวเลือกแคชหน่วยความจำอยู่ แต่ผมก็ยังเชื่อว่าloading multiple filesจะประมวลผลได้มากกว่าloading a single fileในหน่วยความจำ ฉันกำลังเพิ่มที่อยู่ในความกังวลของฉัน

ปรับปรุง: พึ่งพาฉีดทุกอย่าง

กลับมาที่นี่อีกซักพักนึง .. ฉันคิดว่าคำถามของฉันผิดไป หรือบางทีฉันเลือกที่จะเข้าใจผิดบางคำตอบ ฉันไม่ได้พูดถึงการเพิ่มประสิทธิภาพแบบไมโครเนื่องจากคำตอบบางอย่างแยกออกมา (อย่างน้อยฉันก็คิดว่าการเรียกสิ่งที่ฉันกำลังพูดถึงเรื่องการเพิ่มประสิทธิภาพแบบไมโครเป็นตัวเรียกชื่อผิด) แต่เกี่ยวกับการเคลื่อนไหวของ "รหัส Refactor ในทุกระดับของรหัส ฉันมาจาก Zend Con เมื่อเร็ว ๆ นี้ที่รูปแบบของรหัสนี้เป็นหนึ่งในประเด็นหลักและเป็นจุดศูนย์กลางของการประชุม แยกตรรกะออกจากมุมมองดูจากโมเดลจำลองจากฐานข้อมูลและหากทำได้ให้แยกข้อมูลออกจากฐานข้อมูล พึ่งพา - ฉีดทุกสิ่งซึ่งบางครั้งหมายถึงเพียงแค่เพิ่มรหัสการเดินสายไฟ (ฟังก์ชั่นชั้นเรียนสำเร็จรูป) ที่ไม่ทำอะไรเลยแต่ทำหน้าที่เป็นจุดตะเข็บ / ตะขอได้อย่างง่ายดายเพิ่มขนาดโค้ดในกรณีส่วนใหญ่

UPDATE 2: การ "แยกรหัสเป็นไฟล์เพิ่มเติม" มีผลกระทบต่อประสิทธิภาพอย่างมากหรือไม่ (ในทุกระดับของการคำนวณ)

ปรัชญาของcompartmentalize your code into multiple filesการใช้คอมพิวเตอร์ในปัจจุบันส่งผลอย่างไร (ประสิทธิภาพ, การใช้ดิสก์, การจัดการหน่วยความจำ, งานประมวลผล CPU)

ฉันกำลังพูดถึง

ก่อน...

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

.. และตอนนี้*

วันนี้ฉันพบว่าตัวเองกำลังดูรหัสที่แสดงบัญชีแยกประเภทที่มีคุณสมบัติเช่น .. หากรายการนั้นเป็น "คำสั่งซื้อ" แสดงบล็อก HTML ของคำสั่งซื้อ หากสามารถคัดลอกรายการโฆษณาได้ให้พิมพ์บล็อก HTML ที่แสดงไอคอนและพารามิเตอร์ HTML ไว้ด้านหลังเพื่อให้คุณสามารถทำสำเนาได้ หากรายการนั้นสามารถเลื่อนขึ้นหรือลงให้แสดงลูกศร HTML ที่เหมาะสม เป็นต้นฉันสามารถสร้าง Zend Framework ผ่านทางpartial()การโทรซึ่งโดยพื้นฐานแล้วหมายถึง "การเรียกใช้ฟังก์ชันที่ใช้พารามิเตอร์ของคุณและแทรกลงในไฟล์ HTML แยกต่างหากที่มันเรียก" ฉันสามารถสร้างฟังก์ชั่น HTML แยกต่างหากสำหรับส่วนที่เล็กที่สุดของบัญชีแยกประเภท หนึ่งรายการสำหรับลูกศรขึ้น, ลูกศรลง, หนึ่งรายการสำหรับ "ฉันสามารถคัดลอกรายการนี้" ฯลฯ สร้างไฟล์ได้อย่างง่ายดายเพียงเพื่อแสดงส่วนเล็ก ๆ ของหน้าเว็บ การใช้โค้ดของฉันและโค้ดเบื้องหลัง Zend Framework ของฉันระบบ / สแต็กอาจเรียกไฟล์ใกล้เคียงกันได้ถึง 20-30 ไฟล์

อะไร?

ฉันสนใจในแง่มุมการสึกหรอบนเครื่องที่สร้างขึ้นโดยการแบ่งรหัสออกเป็นไฟล์เล็ก ๆ หลายไฟล์

ตัวอย่างเช่นการโหลดไฟล์เพิ่มเติมหมายถึงการที่พวกเขาอยู่ในสถานที่ต่าง ๆ ของระบบไฟล์และในสถานที่ต่าง ๆ ของฟิสิคัล HDD ซึ่งหมายถึง HDD มากขึ้นในการค้นหาและอ่านเวลา

สำหรับ CPU อาจหมายถึงการสลับบริบทและโหลดรีจิสเตอร์ต่างๆ

ในบล็อกย่อยนี้ (อัปเดต # 2) ฉันสนใจมากขึ้นในการใช้หลายไฟล์เพื่อทำงานเดียวกันกับที่ทำได้ในไฟล์เดียวส่งผลกระทบต่อประสิทธิภาพของระบบ

ใช้ Zend Form API เทียบกับ HTML ธรรมดา

ฉันใช้ Zend Form API กับวิธีปฏิบัติ OO ที่ทันสมัยที่สุดและทันสมัยที่สุดเพื่อสร้างฟอร์ม HTML ที่มีการตรวจสอบความถูกต้องเปลี่ยนPOSTเป็นวัตถุโดเมน

เอาไป 35 ไฟล์เพื่อทำ

35 files = 
    = 10 fieldsets x {programmatic fieldset + fieldset manager + view template} 
    + a few supporting files

ซึ่งทั้งหมดนี้สามารถแทนที่ด้วยไฟล์ HTML + PHP + JS + CSS อย่างง่ายจำนวนไม่กี่ไฟล์ซึ่งอาจรวมเป็นไฟล์น้ำหนักเบาทั้งหมด 4 ไฟล์

มันจะดีกว่า มันคุ้มหรือไม่ ... ลองนึกภาพการโหลด 35 ไฟล์ + ไฟล์ไลบรารี Zend Zramework จำนวนมากที่ทำให้ทำงานได้ vs ไฟล์ธรรมดา 4 ไฟล์


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

7
@ ด่าน: คุณช่วยกรุณาใส่ปฏิทินลงในโค้ดของคุณเพื่อกำหนดเกณฑ์มาตรฐานหลังจากการบำรุงรักษา 1, 5 และ 10 ปี หากฉันจำได้ว่าฉันจะตรวจสอบผลลัพธ์อีกครั้ง :)
mattnz

1
ใช่แล้วว่าเป็นนักเตะตัวจริง ฉันคิดว่าเราทุกคนตกลงที่จะทำการค้นหาน้อยลงและการเรียกใช้ฟังก์ชั่นนั้นเร็วขึ้น อย่างไรก็ตามฉันไม่สามารถจินตนาการกรณีที่เป็นที่ต้องการสิ่งต่าง ๆ เช่นบำรุงรักษาและฝึกอบรมสมาชิกทีมใหม่ได้อย่างง่ายดาย
Dan Sabin

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

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

คำตอบ:


10

คำถามของฉันคือเมื่อเรียกรหัสลงไปยังรหัสเครื่องถึง 1 และ 0 เพื่อประกอบคำแนะนำฉันควรกังวลหรือไม่ว่ารหัสที่แยกจากชั้นเรียนของฉันพร้อมฟังก์ชั่นเล็ก ๆ น้อย ๆ มากมายสร้างค่าใช้จ่ายพิเศษมากเกินไป?

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

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

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

มีการกล่าวว่ามีบางแห่ง (quote TBD) ที่มากถึง 70% ของรหัสทั้งหมดประกอบด้วยคำสั่ง MOV ของ ASM - การโหลด CPU register ที่มีตัวแปรที่เหมาะสมไม่ใช่การคำนวณจริง

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

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


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

1
โดยส่วนตัวแล้วฉันพบว่ารหัส "" ทันสมัย ​​"" ค่อนข้างง่ายต่อการโพรไฟล์ ... ฉันเดาว่ารหัสที่บำรุงรักษาได้ดีกว่าคือมันง่ายกว่าในการทำโปรไฟล์ แต่มีข้อ จำกัด ที่การแบ่งสิ่งต่าง ๆ ออกเป็นชิ้นเล็ก ๆ บำรุงรักษาได้น้อยลง ...
AK_

25

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

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

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

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

รหัสบำรุงรักษาที่มีโมดูลขนาดเล็กและการทดสอบหน่วยง่ายต่อการเปลี่ยนแปลงรหัสที่ไม่ต้องการอีกต่อไปจะง่ายต่อการระบุและลบ รหัสที่แตกหักนั้นง่ายต่อการระบุสามารถซ่อมแซมหรือเปลี่ยนได้อย่างมั่นใจ

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

เหนือสิ่งอื่นใดโค้ดที่ถูกต้องช้านั้นเร็วกว่าโค้ดที่ไม่ถูกต้องเร็วมาก


thankx เพื่อผลักดันเรื่องนี้ไปยังที่ที่ฉันกำลังไปฉันไม่ได้พูดถึง micro-optimization แต่การย้ายทั่วโลกไปสู่การเขียนโค้ดที่มีขนาดเล็กลงรวมการฉีดที่ต้องพึ่งพามากขึ้น ที่ทุกคนจะต้องเชื่อมต่อกันเพื่อให้พวกเขาทำงาน ฉันมักจะคิดว่าสิ่งนี้ทำให้เกิดการเชื่อมโยง / ตัวเชื่อมต่อ / ตัวแปรผ่าน / MOV / PUSH / POP / CALL / JMP ที่ระดับฮาร์ดแวร์มากขึ้น ฉันยังเห็นคุณค่าในการเปลี่ยนไปสู่การอ่านรหัสแม้ว่าค่าใช้จ่ายของการเสียสละรอบการคำนวณระดับฮาร์ดแวร์สำหรับ "ปุย"
เดนนิส

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

17

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

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

เช่น C ++, inline สามารถเพิ่มประสิทธิภาพได้ หลายครั้งที่มันอาจจะไม่ทำอะไรเลยหรืออาจลดประสิทธิภาพลง แต่ฉันเองก็ไม่เคยพบเจอว่าตัวเองเคยได้ยินเรื่องราว Inline ไม่มีอะไรมากไปกว่าการแนะนำให้คอมไพเลอร์เพื่อปรับแต่งซึ่งสามารถละเว้นได้

โอกาสที่ถ้าคุณกำลังพัฒนาโปรแกรมระดับสูงค่าใช้จ่ายไม่ควรกังวลหากมีสิ่งใดสิ่งหนึ่งที่จะเริ่มต้นด้วย คอมไพเลอร์ฉลาดมากในวันนี้และควรจัดการกับสิ่งนี้อยู่ดี โปรแกรมเมอร์หลายคนมี code-to-live โดย: อย่าเชื่อใจผู้แปล หากสิ่งนี้ใช้ได้กับคุณดังนั้นแม้กระทั่งการปรับแต่งเล็กน้อยที่คุณรู้สึกว่ามีความสำคัญก็สามารถทำได้ แต่โปรดจำไว้ว่าทุกภาษาแตกต่างกันในเรื่องนี้ Java ทำการเพิ่มประสิทธิภาพแบบอินไลน์โดยอัตโนมัติเมื่อรันไทม์ ใน Javascript อินไลน์สำหรับหน้าเว็บของคุณ (ตรงข้ามกับไฟล์ที่แยกต่างหาก) เป็นการเพิ่มประสิทธิภาพและทุกๆสิบวินาทีของหน้าเว็บอาจนับรวม แต่นั่นเป็นปัญหาของ IO มากกว่า

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

อ่านดีแบบอินไลน์โดยเฉพาะ: http://www.gotw.ca/gotw/033.htm


มาจากมุมมองของคำถามของฉันฉันไม่ได้มุ่งเน้นไปที่การทำ inlining ต่อ seh แต่ใน "การเดินสายที่มีการประมวลผล" ซึ่งใช้ CPU, บัสและกระบวนการเวลาของ I / O ที่เชื่อมโยงโค้ดหลาย ๆ ชิ้น ฉันสงสัยว่ามีบางจุดที่มีรหัสสายไฟ 50% ขึ้นไปและรหัสจริง 50% ที่คุณต้องการเรียกใช้หรือไม่ ฉันคิดว่ามีปุยมากมายแม้ในรหัสที่รัดกุมที่สุดที่สามารถเขียนได้และดูเหมือนว่าจะเป็นความจริงของชีวิต มากของรหัสที่เกิดขึ้นจริงที่วิ่งบนบิตและไบต์ระดับโลจิสติก - ค่าย้ายจากที่หนึ่งไปยังอีกกระโดดไปยังสถานที่หนึ่งหรืออื่นและมีเพียงบางครั้งทำเพิ่ม ..
เดนนิส

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

3
@Dennis - สิ่งหนึ่งที่ต้องพิจารณาคือในภาษา OO อาจมีความสัมพันธ์กันเล็กน้อยระหว่างสิ่งที่โปรแกรมเมอร์เขียน (a + b) และโค้ดใดที่ถูกสร้างขึ้น (เพิ่มอย่างง่าย ๆ ของสองรีจิสเตอร์ย้ายจากหน่วยความจำก่อน จากนั้นเรียกใช้ฟังก์ชันเป็นตัวดำเนินการของวัตถุ +?) ดังนั้น 'ฟังก์ชั่นเล็ก ๆ ' ที่ระดับของโปรแกรมเมอร์อาจเป็นอะไรก็ได้ แต่เล็ก ๆ เมื่อแสดงผลเป็นรหัสเครื่อง
Michael Kohne

2
@Dennis ฉันสามารถพูดได้ว่าการเขียนรหัส ASM (โดยตรงไม่ได้รวบรวม) สำหรับ Windows ไปตามบรรทัดของ "mov, mov, invoke, mov, mov, invoke" ด้วยการเรียกใช้เป็นมาโครที่ทำการโทรโดยการพุช / ปรากฏ ... บางครั้งคุณจะทำการเรียกใช้ฟังก์ชันในรหัสของคุณเอง แต่มันก็แคระโดยการเรียกระบบปฏิบัติการทั้งหมด
Brian Knoblauch

12

นี่คือการเปลี่ยนแปลงเมื่อเทียบกับแนวทางปฏิบัติแบบ "เก่า" หรือ "ไม่ดี" ซึ่งคุณมีวิธีการที่ครอบคลุม 2,500 บรรทัดและชั้นเรียนขนาดใหญ่ทำทุกอย่าง

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

ฉันคิดว่าคำพูดที่โด่งดังจาก Donald Knuth นั้นมีความเกี่ยวข้องมากที่นี่:

เราควรลืมเกี่ยวกับประสิทธิภาพเล็กน้อยพูดถึง 97% ของเวลา: การเพิ่มประสิทธิภาพก่อนวัยอันควรเป็นรากฐานของความชั่วร้ายทั้งหมด

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


11

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

จากประสบการณ์ของฉันนี่คือสิ่งที่นำไปสู่การชะลอตัวและพวกเขาไม่เล็ก พวกเขาเป็นคำสั่งขนาด:

  • การสันนิษฐานว่าบรรทัดของรหัสใด ๆ ใช้เวลามากพอ ๆ กับที่อื่น ๆ ตัวอย่างเช่นเมื่อเทียบกับcout << endl a = b + cอดีตใช้เวลานานกว่าพันครั้งในอดีต Stackexchange มีคำถามมากมายในแบบฟอร์ม "ฉันได้ลองวิธีที่แตกต่างของการปรับรหัสนี้ให้ดีขึ้นแล้ว แต่ดูเหมือนว่ามันจะไม่สร้างความแตกต่างทำไมล่ะ?" เมื่อมีการเรียกใช้ฟังก์ชั่นใหญ่ ๆ อยู่ตรงกลาง

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

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

  • โครงสร้างข้อมูลของ Galloping OOP เป็นกระบวนทัศน์ที่มีประโยชน์มาก แต่ไม่สนับสนุนให้มีการลดโครงสร้างข้อมูลให้น้อยที่สุด - แต่เป็นการสนับสนุนให้พยายามซ่อนความซับซ้อนของมัน ตัวอย่างเช่นมีแนวคิดของ "การแจ้งเตือน" ซึ่งหากมีการแก้ไข datum A ในทางใดทางหนึ่ง A จะออกเหตุการณ์การแจ้งเตือนเพื่อให้ B และ C ยังสามารถปรับเปลี่ยนตนเองเพื่อให้วงดนตรีทั้งมวลสอดคล้องกัน สิ่งนี้สามารถแพร่กระจายไปทั่วหลายชั้นและขยายค่าใช้จ่ายของการปรับเปลี่ยนอย่างมากมาย ดังนั้นจึงเป็นไปได้อย่างสิ้นเชิงที่การเปลี่ยนแปลง A จะสามารถยกเลิกได้ในไม่ช้าหรือเปลี่ยนไปใช้การดัดแปลงอื่นหมายถึงความพยายามที่ใช้ในการพยายามทำให้วงดนตรีคงเส้นคงวาต้องทำอีกครั้ง ความสับสนที่น่าจะเป็นของบั๊กในตัวจัดการการแจ้งเตือนเหล่านี้และเวียน ฯลฯ จะดีกว่าถ้าพยายามรักษาโครงสร้างข้อมูลให้เป็นมาตรฐานเพื่อให้การเปลี่ยนแปลงใด ๆ เกิดขึ้นในที่เดียวเท่านั้น หากไม่สามารถหลีกเลี่ยงข้อมูลที่ไม่ได้มาตรฐานจะเป็นการดีกว่าที่จะมีการส่งข้อมูลเป็นระยะเพื่อซ่อมแซมความไม่สอดคล้องกันแทนที่จะทำท่าว่าจะสามารถรักษาข้อมูลให้สอดคล้องกับสายจูงสั้น ๆ ได้

... เมื่อฉันคิดมากกว่าฉันจะเพิ่ม


8

คำตอบสั้น ๆ คือ "ใช่" และโดยทั่วไปรหัสจะช้าลงเล็กน้อย

แต่บางครั้งการปรับโครงสร้าง OO-ish ที่เหมาะสมจะเปิดเผยการปรับปรุงที่ทำให้โค้ดเร็วขึ้น ฉันทำงานในโครงการหนึ่งที่เราสร้างอัลกอริทึม Java ที่ซับซ้อนมากขึ้น OO-ish ด้วยโครงสร้างข้อมูลที่เหมาะสม getters และอื่น ๆ แทนที่จะเป็นอาร์เรย์ซ้อนกันของวัตถุที่ยุ่งเหยิง แต่ด้วยการแยกและ จำกัด การเข้าถึงโครงสร้างข้อมูลได้ดีขึ้นเราสามารถเปลี่ยนจาก Array ขนาดยักษ์ของ Doubles (ด้วยค่า Null สำหรับผลลัพธ์ว่าง) เป็น Array ที่มีการจัดระเบียบมากขึ้นเป็นสองเท่าด้วย NaN เพื่อผลลัพธ์ที่ว่างเปล่า สิ่งนี้ให้ความเร็วเพิ่มขึ้น 10 เท่า

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


1
ฉันไม่เห็นว่าทำไมการเปลี่ยนจากDoubles เป็นdoubles ต้องมีโครงสร้างที่ดีกว่า
svick

ว้าวโหวตลง? รหัสลูกค้าดั้งเดิมไม่ได้จัดการกับ Double.NaNs แต่ตรวจสอบหาค่า Null เพื่อแสดงค่าว่าง หลังจากปรับโครงสร้างเราสามารถจัดการกับสิ่งนี้ (ผ่านการห่อหุ้ม) ด้วยตัวรับของผลลัพธ์อัลกอริทึมต่างๆ แน่นอนว่าเราสามารถเขียนรหัสลูกค้าใหม่ได้ แต่วิธีนี้ง่ายกว่ามาก
949300

สำหรับบันทึกแล้วฉันไม่ใช่คนที่ลดคำตอบนี้
svick

7

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

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


ฉันยังนึกภาพว่าการเพิ่มประสิทธิภาพที่ดีสามารถทำได้กับ ASM ก่อนที่มันจะทำงานบนฮาร์ดแวร์

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

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

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


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

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


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

4

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


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

3
@JeffO: ฉันไม่เห็นด้วย - อุปกรณ์มือถือที่มีโปรเซสเซอร์ Quad Core เป็นปกติประสิทธิภาพ (โดยเฉพาะอย่างยิ่งเมื่อมันส่งผลกระทบต่อแบตเตอรี่) ในขณะที่ความกังวลมีความสำคัญน้อยกว่าความมั่นคง โทรศัพท์มือถือหรือแท็บเล็ตที่ช้าจะได้รับความคิดเห็นที่ไม่ดีและโทรศัพท์ที่ไม่เสถียรจะถูกสังหาร แอพมือถือมีการเปลี่ยนแปลงตลอดเวลาเกือบทุกวันแหล่งที่มาต้องติดตาม
mattnz

1
@JeffO: สำหรับสิ่งที่คุ้มค่าเครื่องเสมือนที่ใช้กับ Android นั้นค่อนข้างแย่ ตามมาตรฐานอาจลำดับความสำคัญช้ากว่ารหัสเนทีฟ (ในขณะที่สายพันธุ์ที่ดีที่สุดมักจะช้ากว่านิดหน่อย) คาดเดาสิ่งที่ไม่มีใครใส่ใจ การเขียนแอปพลิเคชั่นนั้นรวดเร็วและ CPU ตั้งอยู่ที่นั่นเป็นสองเท่าของนิ้วหัวแม่มือและรอการป้อนข้อมูลของผู้ใช้ 90% ของเวลา
Jan Hudec

มีประสิทธิภาพมากกว่าการใช้ CPU มาตรฐาน โทรศัพท์ Android ของฉันใช้งานได้ดียกเว้นเมื่อ AV กำลังสแกนการอัปเดตจากนั้นดูเหมือนว่าจะวางสายนานกว่าที่ฉันต้องการและรุ่น Quad-Core 2Gb RAM ของมัน! วันนี้แบนด์วิดธ์ (ไม่ว่าจะเป็นเครือข่ายหรือหน่วยความจำ) อาจเป็นคอขวดหลัก ซีพียูที่เร็วมากของคุณน่าจะบิดนิ้วโป้งเป็น 99% ของเวลาและประสบการณ์โดยรวมก็ยังแย่
gbjbaanb

4

เมื่อ 20 กว่าปีที่แล้วซึ่งฉันเดาว่าคุณไม่ได้โทรมาใหม่และไม่ "เก่าหรือไม่ดี" กฎก็คือการทำให้ฟังก์ชั่นเล็กพอที่จะพอดีกับหน้าที่พิมพ์ เรามีเครื่องพิมพ์ดอทเมทริกซ์ดังนั้นจำนวนบรรทัดจึงค่อนข้างคงที่โดยทั่วไปเพียงหนึ่งหรือสองตัวเลือกสำหรับจำนวนบรรทัดต่อหน้า ... น้อยกว่า 2,500 เส้นแน่นอน

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

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

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

วิธี unix คือการทำให้การใช้คำของฉันบล็อกเลโก้อย่างสวยงาม ทำไมคุณถึงใช้ฟังก์ชั่นเทปหลายปีหลังจากเราหยุดใช้เทป เนื่องจากหยดทำงานได้ดีมากและด้านหลังเราสามารถแทนที่อินเตอร์เฟสเทปด้วยอินเตอร์เฟสไฟล์และใช้ประโยชน์จากเนื้อของโปรแกรม เหตุใดจึงต้องเขียนซอฟต์แวร์การเขียน cdrom ใหม่เพียงเพราะ scsi หายไปเนื่องจากส่วนต่อประสานที่ถูกแทนที่ด้วย IDE (หลังจากนั้นจะกลับมาใหม่ในภายหลัง) ใช้ประโยชน์จากบล็อกย่อยที่ขัดอีกครั้งและแทนที่ปลายด้านหนึ่งด้วยบล็อกอินเตอร์เฟสใหม่ (และเข้าใจว่านักออกแบบฮาร์ดแวร์เพียงแค่บล็อกบล็อกอินเตอร์เฟสบนการออกแบบฮาร์ดแวร์ในบางกรณีการทำไดรฟ์ scsi มี IDE เพื่อ scsi อินเตอร์เฟส) สร้างบล็อกเลโก้ขัดเงาขนาดพอสมควรแต่ละบล็อกด้วยวัตถุประสงค์ที่กำหนดไว้อย่างดีและอินพุตและเอาต์พุตที่กำหนดไว้อย่างดี คุณสามารถล้อมรอบการทดสอบรอบ ๆ บล็อกเลโก้แล้วใช้ส่วนต่อประสานผู้ใช้และส่วนต่อประสานกับระบบปฏิบัติการรอบ ๆ บล็อกและบล็อกเดียวกันในทางทฤษฎีการทดสอบอย่างดีและเข้าใจดีไม่จำเป็นต้องทำการดีบั๊ก ในแต่ละปลาย ตราบใดที่อินเทอร์เฟซบล็อกทั้งหมดของคุณได้รับการออกแบบมาเป็นอย่างดีและฟังก์ชั่นการใช้งานที่เข้าใจได้ดีคุณสามารถสร้างสิ่งต่าง ๆ ได้อย่างยอดเยี่ยม เช่นเดียวกับบล็อกเลโก้สีน้ำเงินและสีแดงและสีดำและสีเหลืองที่มีขนาดและรูปร่างที่รู้จักกันคุณสามารถสร้างสิ่งต่าง ๆ ได้มากมาย ตราบใดที่อินเทอร์เฟซบล็อกทั้งหมดของคุณได้รับการออกแบบมาเป็นอย่างดีและฟังก์ชั่นการใช้งานที่เข้าใจได้ดีคุณสามารถสร้างสิ่งต่าง ๆ ได้อย่างยอดเยี่ยม เช่นเดียวกับบล็อกเลโก้สีน้ำเงินและสีแดงและสีดำและสีเหลืองที่มีขนาดและรูปร่างที่รู้จักกันคุณสามารถสร้างสิ่งต่าง ๆ ได้มากมาย ตราบใดที่อินเทอร์เฟซบล็อกทั้งหมดของคุณได้รับการออกแบบมาเป็นอย่างดีและฟังก์ชั่นการใช้งานที่เข้าใจได้ดีคุณสามารถสร้างสิ่งต่าง ๆ ได้อย่างยอดเยี่ยม เช่นเดียวกับบล็อกเลโก้สีน้ำเงินและสีแดงและสีดำและสีเหลืองที่มีขนาดและรูปร่างที่รู้จักกันคุณสามารถสร้างสิ่งต่าง ๆ ได้มากมาย

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


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

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

2

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

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

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


0

[องค์ประกอบเวลาคอมพิวเตอร์] การ

ปรับโครงสร้างใหม่ต่อการมีเพศสัมพันธ์แบบหลวมและฟังก์ชั่นขนาดเล็กส่งผลต่อความเร็วของรหัสหรือไม่?

ใช่แล้ว. แต่มันก็ขึ้นอยู่กับล่ามคอมไพเลอร์และคอมไพเลอร์ของ JIT เพื่อตัดรหัส "ตะเข็บ / เดินสาย" นี้และบางอันก็ทำได้ดีกว่าตัวอื่น ๆ แต่บางตัวก็ทำไม่ได้

ความกังวลหลายไฟล์เพิ่มค่าใช้จ่าย I / O ดังนั้นจึงมีผลต่อความเร็วค่อนข้างน้อย (ในเวลาคอมพิวเตอร์)

[องค์ประกอบความเร็วมนุษย์]

(และฉันควรสนใจไหม)

ไม่คุณไม่ควรสนใจ คอมพิวเตอร์และวงจรเร็ววันนี้มากมายและปัจจัยอื่น ๆ เข้ามาเช่นเวลาแฝงเครือข่าย I / O ฐานข้อมูลและแคช

ดังนั้น 2x - 4x ช้าลงในการเรียกใช้โค้ดเนทีฟเองมักจะถูกจมอยู่กับปัจจัยอื่น ๆ

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


0

คำตอบ (ในกรณีที่คุณพลาด)

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

ในระยะสั้น

ไม่สนใจเรื่องประสิทธิภาพ

ในบริบทของคำถามคอมไพเลอร์และล่ามที่ชาญฉลาดจะดูแลมันอยู่แล้ว

สนใจเกี่ยวกับการเขียนรหัสที่สามารถบำรุงรักษาได้

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

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