เราทุกคนรู้ว่าการเพิ่มประสิทธิภาพก่อนวัยอันควรเป็นรากฐานของความชั่วร้ายทั้งหมดเพราะมันนำไปสู่รหัสที่อ่านไม่ได้ / ไม่สามารถทำได้ ยิ่งแย่ลงคือการมองดูในแง่ร้ายเมื่อมีคนใช้ "การเพิ่มประสิทธิภาพ" เพราะพวกเขาคิดว่ามันจะเร็วขึ้น แต่มันก็ช้าลงเรื่อย ๆ ?
เราทุกคนรู้ว่าการเพิ่มประสิทธิภาพก่อนวัยอันควรเป็นรากฐานของความชั่วร้ายทั้งหมดเพราะมันนำไปสู่รหัสที่อ่านไม่ได้ / ไม่สามารถทำได้ ยิ่งแย่ลงคือการมองดูในแง่ร้ายเมื่อมีคนใช้ "การเพิ่มประสิทธิภาพ" เพราะพวกเขาคิดว่ามันจะเร็วขึ้น แต่มันก็ช้าลงเรื่อย ๆ ?
คำตอบ:
ในโครงการเก่าเราสืบทอดโปรแกรมเมอร์ระบบฝังตัว (ยอดเยี่ยม) ที่มีประสบการณ์ Z-8000 จำนวนมาก
สภาพแวดล้อมใหม่ของเราคือ Sparc Solaris 32 บิต
คนหนึ่งไปและเปลี่ยน ints ทั้งหมดเป็นกางเกงขาสั้นเพื่อเร่งความเร็วโค้ดของเราเนื่องจากการคว้า 16 บิตจาก RAM เร็วกว่าการคว้า 32 บิต
ฉันต้องเขียนโปรแกรมตัวอย่างเพื่อแสดงว่าการคว้าค่า 32- บิตบนระบบ 32- บิตนั้นเร็วกว่าการคว้าค่า 16- บิตและอธิบายว่าการคว้าค่า 16- บิตที่ CPU ต้องทำให้กว้าง 32 บิต การเข้าถึงหน่วยความจำแล้วปิดบังหรือเปลี่ยนบิตที่ไม่จำเป็นสำหรับค่า 16 บิต
ฉันคิดว่าวลี "การเพิ่มประสิทธิภาพก่อนวัยอันควรเป็นรากของความชั่วร้ายทั้งหมด" เป็นวิธีใช้มากกว่า สำหรับหลาย ๆ โครงการมันกลายเป็นข้ออ้างที่จะไม่คำนึงถึงผลงานจนกว่าจะถึงช่วงปลายของโครงการ
วลีนี้มักเป็นสิ่งที่ทำให้ผู้คนหลีกเลี่ยงงาน ฉันเห็นวลีนี้ใช้เมื่อคนควรพูดว่า "Gee เราไม่ได้คิดอย่างนั้นล่วงหน้าและไม่มีเวลาจัดการกับมันตอนนี้"
ฉันเคยเห็นตัวอย่าง "ไร้สาระ" อีกมากมายของปัญหาด้านประสิทธิภาพการทำงานที่โง่กว่าตัวอย่างของปัญหาที่เกิดขึ้นเนื่องจาก "การมองดูในแง่ร้าย"
สิ่งที่ฉันคิดว่าเป็นคำกล่าวที่ดีกว่าคือ: "การเพิ่มประสิทธิภาพโดยไม่มีการวัดและความเข้าใจไม่ใช่การเพิ่มประสิทธิภาพเลยการเปลี่ยนแปลงแบบสุ่ม"
งานที่มีประสิทธิภาพที่ดีนั้นใช้เวลานาน - บ่อยกว่านั้นเพื่อที่จะพัฒนาคุณสมบัติหรือส่วนประกอบเอง
ฐานข้อมูลเป็นพื้นที่เล่นในแง่ร้าย
รายการโปรดรวมถึง:
นั่นอยู่ด้านบนของหัวของฉัน
ฉันคิดว่าไม่มีกฎเด็ดขาด: มีบางสิ่งที่ได้รับการปรับปรุงให้ดีที่สุดล่วงหน้าและบางอย่างก็ไม่ใช่
ตัวอย่างเช่นฉันทำงานใน บริษัท ที่เราได้รับแพ็กเก็ตข้อมูลจากดาวเทียม แต่ละแพ็คเก็ตมีค่าใช้จ่ายเป็นจำนวนมากดังนั้นข้อมูลทั้งหมดจึงได้รับการปรับให้เหมาะสมที่สุด (เช่นบรรจุ) ตัวอย่างเช่นละติจูด / ลองจิจูดไม่ได้ส่งเป็นค่าสัมบูรณ์ (ลอย) แต่เป็นการปรับเทียบสัมพัทธ์กับมุม "ทางตะวันตกเฉียงเหนือ" ของโซน "ปัจจุบัน" เราต้องแกะข้อมูลทั้งหมดก่อนจึงจะสามารถใช้งานได้ แต่ฉันคิดว่านี่ไม่ใช่การมองโลกในแง่ร้ายมันเป็นการเพิ่มประสิทธิภาพอัจฉริยะเพื่อลดต้นทุนการสื่อสาร
ในทางกลับกันสถาปนิกซอฟต์แวร์ของเราตัดสินใจว่าข้อมูลที่ไม่ได้บรรจุควรจัดรูปแบบเป็นเอกสาร XML ที่อ่านได้ง่ายมากและเก็บไว้ในฐานข้อมูลของเราเช่นนั้น (ต่างจากการเก็บแต่ละฟิลด์ไว้ในคอลัมน์ที่สอดคล้องกัน) แนวคิดของพวกเขาคือ "XML คืออนาคต", "พื้นที่ว่างในดิสก์ราคาถูก" และ "ตัวประมวลผลราคาถูก" ดังนั้นจึงไม่จำเป็นต้องเพิ่มประสิทธิภาพอะไรเลย ผลลัพธ์คือแพ็คเก็ต 16 ไบต์ของเราถูกเปลี่ยนเป็นเอกสาร 2kB ที่จัดเก็บในคอลัมน์เดียวและสำหรับการสืบค้นที่ง่ายเราต้องโหลดเมกะไบต์ของเอกสาร XML ในหน่วยความจำ! เราได้รับมากกว่า 50 แพ็คเก็ตต่อวินาทีดังนั้นคุณสามารถจินตนาการได้ว่าประสิทธิภาพการทำงานนั้นแย่เพียงใด (BTW บริษัท ล้มละลาย)
ดังนั้นอีกครั้งไม่มีกฎเด็ดขาด ใช่บางครั้งการเพิ่มประสิทธิภาพเร็วเกินไปเป็นข้อผิดพลาด แต่บางครั้งคำขวัญ "cpu / พื้นที่ดิสก์ / หน่วยความจำราคาถูก" เป็นรากเหง้าที่แท้จริงของความชั่วร้ายทั้งหมด
โอ้พระเจ้าที่ดีฉันคิดว่าฉันได้เห็นพวกเขาทั้งหมด บ่อยครั้งที่มันเป็นความพยายามในการแก้ไขปัญหาประสิทธิภาพการทำงานโดยคนที่ขี้เกียจเกินไปที่จะแก้ไขปัญหาของพวกเขาจนถึงสาเหตุของปัญหาประสิทธิภาพการทำงานเหล่านั้นหรือแม้แต่การค้นคว้าว่ามีปัญหาประสิทธิภาพจริงหรือไม่ ในหลายกรณีเหล่านี้ฉันสงสัยว่ามันไม่ใช่แค่กรณีของบุคคลนั้นที่ต้องการลองใช้เทคโนโลยีเฉพาะและมองหาเล็บที่เข้ากับค้อนใหม่ของพวกเขาอย่างหมดจด
นี่คือตัวอย่างล่าสุด:
สถาปนิกข้อมูลมาหาฉันพร้อมข้อเสนอที่ซับซ้อนเพื่อแบ่งพาร์ติชั่นตารางคีย์ในแอพพลิเคชั่นขนาดใหญ่และซับซ้อน เขาต้องการทราบว่าความพยายามในการพัฒนาประเภทใดที่จำเป็นสำหรับการเปลี่ยนแปลง บทสนทนาเป็นดังนี้:
ฉัน:ทำไมคุณถึงพิจารณาเรื่องนี้ ปัญหาที่คุณพยายามแก้ไขคืออะไร
เขา:ตาราง X กว้างเกินไปเรากำลังแบ่งพาร์ติชันด้วยเหตุผลด้านประสิทธิภาพ
ฉัน:อะไรทำให้คุณคิดว่ากว้างเกินไป
เขา:ที่ปรึกษากล่าวว่ามีคอลัมน์มากเกินไปที่จะมีในตารางเดียว
ฉัน:และนี่คือสิ่งที่ส่งผลกระทบต่อประสิทธิภาพการทำงาน?
เขา:ใช่ผู้ใช้รายงานการชะลอตัวเป็นระยะในโมดูล XYZ ของแอปพลิเคชัน
ฉัน:คุณรู้ได้อย่างไรว่าความกว้างของโต๊ะเป็นสาเหตุของปัญหาอย่างไร
เขา:นั่นคือตารางสำคัญที่ใช้โดยโมดูล XYZ และมันก็เหมือนกับ 200 คอลัมน์ มันจะต้องเป็นปัญหา
ฉัน (อธิบาย):แต่โมดูล XYZ โดยเฉพาะใช้คอลัมน์ส่วนใหญ่ในตารางนั้นและคอลัมน์ที่ใช้นั้นไม่สามารถคาดเดาได้เนื่องจากผู้ใช้กำหนดค่าแอปให้แสดงข้อมูลที่ต้องการแสดงจากตารางนั้น เป็นไปได้ว่า 95% ของเวลาที่เราจะเลิกเล่นกับทุกโต๊ะกลับมาอยู่ด้วยกันซึ่งจะส่งผลเสียต่อประสิทธิภาพ
เขา:ที่ปรึกษาบอกว่ากว้างเกินไปและเราต้องเปลี่ยนมัน
ฉัน:ใครคือที่ปรึกษานี้ ฉันไม่รู้ว่าเราจ้างที่ปรึกษาหรือไม่พวกเขาคุยกับทีมพัฒนาเลย
เขา:เรายังไม่ได้จ้างพวกเขา นี่เป็นส่วนหนึ่งของข้อเสนอที่เสนอ แต่ยืนยันว่าเราต้องการสร้างฐานข้อมูลนี้ใหม่
ฉัน:เอ่อ ดังนั้นที่ปรึกษาที่ขายบริการออกแบบฐานข้อมูลจึงคิดว่าเราต้องการการออกแบบฐานข้อมูลอีกครั้ง ....
บทสนทนาดำเนินต่อไปเรื่อย ๆ หลังจากนั้นฉันลองดูที่คำถามอีกครั้งและพิจารณาว่ามันอาจถูกทำให้แคบลงด้วยการทำให้เป็นมาตรฐานแบบธรรมดาโดยไม่จำเป็นต้องใช้กลยุทธ์การแบ่งพาร์ติชันที่แปลกใหม่ แน่นอนว่านี่เป็นจุดที่สงสัยเมื่อฉันตรวจสอบปัญหาประสิทธิภาพการทำงาน (ไม่ได้รับการรายงานก่อนหน้านี้) และติดตามพวกเขาลงในสองปัจจัย:
แน่นอนว่าสถาปนิกยังคงผลักดันให้มีการแบ่งพาร์ติชันตามแนวตั้งของตารางที่แขวนอยู่บนเมตาดาต้าปัญหา "กว้างเกินไป" เขายังสนับสนุนกรณีของเขาโดยรับข้อเสนอจากที่ปรึกษาฐานข้อมูลรายอื่นที่สามารถระบุได้ว่าเราต้องการการเปลี่ยนแปลงการออกแบบที่สำคัญในฐานข้อมูลโดยไม่ต้องดูแอพหรือทำการวิเคราะห์ประสิทธิภาพ
ฉันเห็นผู้คนใช้ alphadrive-7 เพื่อบ่มเพาะ CHX-LT โดยสิ้นเชิง นี่คือการปฏิบัติที่ผิดปกติ วิธีปฏิบัติที่ใช้กันทั่วไปมากขึ้นคือการเริ่มต้นหม้อแปลง ZT เพื่อลดการบัฟเฟอร์ (เนื่องจากมีความต้านทานต่อการโอเวอร์โหลดสุทธิมากขึ้น) และสร้างรูปแบบจาวาแบบกราฟิก
มองโลกในแง่ร้ายโดยสิ้นเชิง!
ฉันยอมรับว่าไม่มีอะไรที่ทำให้โลกแตกเป็นเสี่ยง ๆ แต่ฉันจับคนที่ใช้ StringBuffer เพื่อต่อสาย Stratenate นอกวงใน Java มันเป็นเรื่องง่ายเหมือนการพลิก
String msg = "Count = " + count + " of " + total + ".";
เข้าไป
StringBuffer sb = new StringBuffer("Count = ");
sb.append(count);
sb.append(" of ");
sb.append(total);
sb.append(".");
String msg = sb.toString();
มันเคยเป็นเรื่องธรรมดาที่จะใช้เทคนิคในวงเพราะมันวัดได้เร็วกว่า สิ่งนี้คือ StringBuffer ถูกซิงโครไนซ์ดังนั้นจึงมีค่าใช้จ่ายเพิ่มเติมหากคุณต่อเชื่อมสตริงไม่กี่สตริงเท่านั้น (ไม่ต้องพูดถึงว่าความแตกต่างนั้นเล็กน้อยในระดับนี้) ประเด็นอื่น ๆ อีกสองข้อเกี่ยวกับการฝึกฝนนี้:
ฉันเคยเห็นฐานข้อมูล MSSQL ที่ใช้ตาราง 'รูท' ตารางรูทมีสี่คอลัมน์: GUID (uniqueidentifier), ID (int), LastModDate (datetime) และ CreateDate (datetime) ตารางทั้งหมดในฐานข้อมูลเป็น Foreign Key จะไปที่ตารางรูต เมื่อใดก็ตามที่แถวใหม่ถูกสร้างขึ้นในตารางใด ๆในฐานข้อมูลคุณต้องใช้กระบวนงานที่เก็บไว้สองสามรายการเพื่อแทรกรายการในตารางรูตก่อนที่คุณจะไปถึงตารางจริงที่คุณสนใจ (แทนที่จะเป็นฐานข้อมูลที่ทำงานให้ คุณใช้ทริกเกอร์ง่าย ๆ )
สิ่งนี้สร้างความยุ่งเหยิงจากการได้ยินและปวดหัวที่ไร้ประโยชน์จำเป็นต้องมีสิ่งใดที่เขียนไว้ด้านบนเพื่อใช้ sprocs (และกำจัดความหวังของฉันในการแนะนำ LINQ ให้กับ บริษัท มันเป็นไปได้ แต่ก็ไม่คุ้มกับอาการปวดหัว) อย่าทำสิ่งที่ควรทำ
นักพัฒนาที่เลือกเส้นทางนี้ได้รับการปกป้องภายใต้สมมติฐานที่ว่านี้ช่วยประหยัดพื้นที่ได้มากเพราะเราไม่ได้ใช้ Guids บนโต๊ะตัวเอง (แต่ ... ไม่ใช่ GUID ที่สร้างในตารางรูทสำหรับทุกแถวที่เราสร้างใช่ไหม) ปรับปรุงประสิทธิภาพอย่างใดและทำให้ "ง่าย" ในการตรวจสอบการเปลี่ยนแปลงในฐานข้อมูล
โอ้และแผนภาพฐานข้อมูลดูเหมือนแมงมุมกลายพันธุ์จากนรก
วิธีการเกี่ยวกับPOBI - แง่ลบอย่างชัดเจนโดยเจตนา?
Collegue ของฉันใน 90s เหนื่อยกับการถูกเตะในตูดโดย CEO เพียงเพราะ CEO ใช้เวลาวันแรกของทุกซอฟต์แวร์ ERP (รุ่นที่กำหนดเอง) การเปิดตัวด้วยปัญหาการหาตำแหน่งในการทำงานใหม่ แม้ว่าฟังก์ชันใหม่จะกระทืบกิกะไบต์และทำให้เป็นไปไม่ได้เขาก็พบรายละเอียดบางอย่างหรือแม้กระทั่งปัญหาสำคัญที่ดูเหมือนจะคร่ำครวญ เขาเชื่อว่ารู้มากเกี่ยวกับการเขียนโปรแกรมและได้เตะของเขาด้วยการเตะลาโปรแกรมเมอร์
เนื่องจากลักษณะที่ไร้ความสามารถของการวิจารณ์ (เขาเป็นซีอีโอไม่ใช่คนไอที) เพื่อนร่วมงานของฉันไม่สามารถจัดการให้ถูกต้องได้ หากคุณไม่มีปัญหาด้านประสิทธิภาพคุณไม่สามารถกำจัดมัน ...
จนกระทั่งวางจำหน่ายหนึ่งครั้งเขาวางการเรียกใช้ฟังก์ชัน Delay (200) จำนวนมาก (เป็น Delphi) ลงในรหัสใหม่ ใช้เวลาเพียง 20 นาทีหลังจากไปใช้ชีวิตจริงและเขาได้รับคำสั่งให้ไปปรากฏตัวในห้องทำงานของ CEO เพื่อเรียกดูข้อความที่เกินกำหนดด้วยตนเอง
มีเพียงสิ่งผิดปกติเท่านั้นที่เพื่อนร่วมงานของฉันปิดเสียงเมื่อเขากลับมายิ้มล้อเล่นออกไปหา BigMac หรือสองคนในขณะที่เขามักจะเตะโต๊ะเปลวไฟเกี่ยวกับ CEO และ บริษัท และใช้เวลาที่เหลือทั้งวันกลายเป็นความตาย .
ตามปกติเพื่อนร่วมงานของฉันได้พักหนึ่งหรือสองวันที่โต๊ะทำงานของเขาพัฒนาทักษะการเล็งใน Quake จากนั้นในวันที่สองหรือสามเขาลบการโทรล่าช้าสร้างใหม่และปล่อย "แพทช์ฉุกเฉิน" ซึ่งเขากระจายคำ เขาใช้เวลา 2 วัน 1 คืนเพื่อแก้ไขปัญหาหลุมการแสดง
นี่เป็นครั้งแรก (และครั้งเดียว) ที่ซีอีโอผู้ชั่วร้ายพูดว่า "ทำได้ดีมาก!" ให้เขา. นั่นคือทั้งหมดที่นับใช่มั้ย
นี่คือ POBI จริง
แต่มันก็เป็นกระบวนการทางสังคมที่ได้รับการปรับให้เหมาะสมที่สุดดังนั้นมันจึงเป็น 100%
ฉันคิด.
"ความเป็นอิสระของฐานข้อมูล" นี่หมายความว่าไม่มี procs, ทริกเกอร์และอื่น ๆ - แม้จะไม่มีคีย์ต่างประเทศ
var stringBuilder = new StringBuilder();
stringBuilder.Append(myObj.a + myObj.b + myObj.c + myObj.d);
string cat = stringBuilder.ToString();
ใช้งาน StringBuilder ได้ดีที่สุดที่ฉันเคยเห็น
ใช้ regex เพื่อแยกสตริงเมื่อ string.split ง่ายพอเพียง
สายเกินไปที่จะรู้หัวข้อนี้ แต่ฉันเห็นนี้เมื่อเร็ว ๆ นี้:
bool isFinished = GetIsFinished();
switch (isFinished)
{
case true:
DoFinish();
break;
case false:
DoNextStep();
break;
default:
DoNextStep();
}
คุณรู้ไหมในกรณีที่บูลีนมีค่าพิเศษบางอย่าง ...
ตัวอย่างที่เลวร้ายที่สุดที่ฉันนึกได้คือฐานข้อมูลภายในที่ บริษัท ของฉันมีข้อมูลเกี่ยวกับพนักงานทุกคน มันได้รับการอัพเดตคืนจาก HR และมีบริการเว็บ ASP.NET อยู่ด้านบน แอปอื่น ๆ อีกมากมายใช้บริการเว็บเพื่อเติมข้อมูลเช่นฟิลด์ค้นหา / ดรอปดาวน์
มองโลกในแง่ร้ายคือนักพัฒนาคิดว่าการเรียกใช้บริการเว็บซ้ำ ๆ จะช้าเกินไปที่จะทำการสืบค้น SQL ซ้ำ ดังนั้นเขาทำอะไร เหตุการณ์เริ่มต้นของแอปพลิเคชันจะอ่านในฐานข้อมูลทั้งหมดและแปลงเป็นวัตถุในหน่วยความจำโดยเก็บไว้เรื่อย ๆ จนกว่าแอพพลิเคชั่นจะถูกรีไซเคิล รหัสนี้ช้ามากมันใช้เวลา 15 นาทีในการโหลดพนักงานน้อยกว่า 2,000 คน หากคุณนำแอพพลิเคชั่นกลับมาใช้ใหม่ระหว่างวันโดยไม่ได้ตั้งใจอาจใช้เวลา 30 นาทีขึ้นไปเพราะแต่ละคำขอบริการเว็บจะเริ่มการโหลดซ้ำหลายครั้งพร้อมกัน ด้วยเหตุผลนี้การจ้างงานใหม่จะไม่ปรากฏในฐานข้อมูลในวันแรกเมื่อสร้างบัญชีของพวกเขาและดังนั้นจึงไม่สามารถเข้าถึงแอปภายในส่วนใหญ่ในสองสามวันแรกของพวกเขา
ระดับที่สองของการมองโลกในแง่ร้ายคือผู้จัดการฝ่ายพัฒนาไม่ต้องการสัมผัสมันเพราะกลัวว่าจะทำลายแอพพลิเคชั่นที่ต้องพึ่งพากัน แต่เราก็ยังคงมีแอพพลิเคชั่นที่สำคัญเป็นระยะ ๆ
ดูเหมือนไม่มีใครพูดถึงการเรียงลำดับดังนั้นฉันจะ
หลายครั้งที่แตกต่างกันฉันได้ค้นพบว่ามีคนสร้างฟองอากาศด้วยมือขึ้นมาเพราะสถานการณ์ "ไม่ต้องการ" การเรียกอัลกอริธึมแบบเร็ว "แฟนซี" ที่มีอยู่แล้ว นักพัฒนารู้สึกพึงพอใจเมื่อมีการทำฟองสบู่แบบ handcrafted ทำงานได้ดีพอกับข้อมูลสิบแถวที่พวกเขาใช้สำหรับการทดสอบ มันไม่ได้ไปมากกว่าเช่นกันหลังจากที่ลูกค้าเพิ่มสองสามพันแถว
ฉันเคยทำงานในแอพที่เต็มไปด้วยรหัสเช่นนี้:
1 tuple *FindTuple( DataSet *set, int target ) {
2 tuple *found = null;
3 tuple *curr = GetFirstTupleOfSet(set);
4 while (curr) {
5 if (curr->id == target)
6 found = curr;
7 curr = GetNextTuple(curr);
8 }
9 return found;
10 }
เพียงแค่ลบfound
กลับไปnull
ที่จุดสิ้นสุดและเปลี่ยนบรรทัดที่หกเป็น:
return curr;
ประสิทธิภาพของแอปเพิ่มขึ้นเป็นสองเท่า
ฉันเคยพยายามแก้ไขโค้ดที่รวมอัญมณีเหล่านี้ในคลาส Constants
public static String COMMA_DELIMINATOR=",";
public static String COMMA_SPACE_DELIMINATOR=", ";
public static String COLIN_DELIMINATOR=":";
แต่ละเหล่านี้ถูกใช้หลายครั้งในส่วนที่เหลือของแอปพลิเคชันเพื่อวัตถุประสงค์ที่แตกต่างกัน COMMA_DELIMINATOR ปล่อยรหัสที่มีการใช้งานมากกว่า 200 รายการใน 8 แพ็คเกจที่แตกต่างกัน
ตัวใหญ่อันดับหนึ่งตลอดกาลที่ฉันพบเจอครั้งแล้วครั้งเล่าในซอฟต์แวร์ภายใน:
ไม่ใช้คุณสมบัติของ DBMS สำหรับเหตุผล "ความสะดวก" เพราะ "เราอาจต้องการเปลี่ยนไปใช้ผู้จำหน่ายรายอื่นในภายหลัง"
อ่านริมฝีปากของฉัน. สำหรับงานในบ้าน: มันจะไม่เกิดขึ้น!
ฉันมีเพื่อนร่วมงานที่พยายามใช้เครื่องมือเพิ่มประสิทธิภาพคอมไพเลอร์ C ของเราและเขียนรหัสประจำที่เขาสามารถอ่านได้เท่านั้น หนึ่งในเทคนิคที่เขาโปรดปรานคือการเปลี่ยนวิธีการที่สามารถอ่านได้เช่น (ทำโค้ดบางส่วน):
int some_method(int input1, int input2) {
int x;
if (input1 == -1) {
return 0;
}
if (input1 == input2) {
return input1;
}
... a long expression here ...
return x;
}
เป็นนี้
int some_method() {
return (input == -1) ? 0 : (input1 == input2) ? input 1 :
... a long expression ...
... a long expression ...
... a long expression ...
}
นั่นคือบรรทัดแรกของวิธีที่อ่านได้ครั้งเดียวจะกลายเป็น " return
" และตรรกะอื่น ๆ ทั้งหมดจะถูกแทนที่ด้วยนิพจน์ที่ประกอบกันเป็นชั้นที่ลึกลงไป เมื่อคุณพยายามที่จะโต้เถียงเกี่ยวกับวิธีการที่ไม่สามารถกำจัดได้เขาจะชี้ให้เห็นข้อเท็จจริงที่ว่าเอาต์พุตแอสเซมบลีของวิธีการของเขาสั้นลงสามหรือสี่ มันก็ไม่จำเป็นต้องใด ๆได้เร็วขึ้นแต่มันก็มักจะเป็นขนาดเล็กบิตสั้น นี่เป็นระบบฝังตัวซึ่งการใช้หน่วยความจำเป็นครั้งคราวสำคัญ แต่มีการปรับให้เหมาะสมที่ทำได้ง่ายกว่านี้ซึ่งจะทำให้โค้ดอ่านได้
จากนั้นหลังจากนี้ด้วยเหตุผลบางอย่างเขาตัดสินใจว่าptr->structElement
มันอ่านไม่ได้เกินไปดังนั้นเขาจึงเริ่มเปลี่ยนสิ่งเหล่านี้เป็น(*ptr).structElement
ทฤษฎีที่อ่านได้ง่ายขึ้นและเร็วขึ้นเช่นกัน
การเปลี่ยนรหัสที่อ่านได้เป็นรหัสที่อ่านไม่ได้สำหรับการปรับปรุงมากที่สุด 1% และบางครั้งรหัสช้าลง
if
อ่านกว่า การยืนหยัดในแถลงการณ์เกี่ยวกับการแสดงออกในคเป็นความเชื่อทางวัฒนธรรม / ศาสนาไม่ใช่การปฏิบัติตามวัตถุประสงค์ใด ๆ (แนวทางที่ดีกว่า: หากไตรภาคที่ซ้อนกันยาวเกินไปที่จะอ่านคุณไม่ควรใช้if
อย่างใดอย่างหนึ่ง)
if
ในฟังก์ชั่นและแทนที่ด้วยไตรภาค ไม่เป็นไรและอ่านได้บ่อยกว่า ฉันกำลังพูดถึงการแทนที่วิธีบรรทัด 30+ ทั้งหมดด้วยคำสั่งส่งคืนเดียวและสามเทอม ไม่มีใครคิดว่ารหัสใหม่อ่านได้ง่ายกว่า แต่ผู้พัฒนาคิดว่ามันเร็วกว่า
ในหนึ่งในงานแรกของฉันในฐานะนักพัฒนาที่มีความชำนาญฉันได้เข้าร่วมโครงการสำหรับโปรแกรมที่กำลังประสบปัญหาการปรับขนาด มันจะทำงานได้ดีพอสมควรกับชุดข้อมูลขนาดเล็ก แต่จะพังได้อย่างสมบูรณ์เมื่อได้รับข้อมูลปริมาณมาก
ขณะที่ฉันขุดฉันพบว่าโปรแกรมเมอร์ต้นฉบับพยายามเร่งความเร็วสิ่งต่างๆด้วยการวิเคราะห์แบบขนาน - เปิดเธรดใหม่สำหรับแหล่งข้อมูลเพิ่มเติมแต่ละแหล่ง อย่างไรก็ตามเขาทำผิดพลาดในการที่กระทู้ทั้งหมดต้องใช้ทรัพยากรที่ใช้ร่วมกันซึ่งพวกเขาถูกล็อค แน่นอนประโยชน์ทั้งหมดของการเกิดพร้อมกันหายไป ยิ่งไปกว่านั้นระบบส่วนใหญ่จะเปิดใช้งานเธรดมากกว่า 100 เธรดเท่านั้นที่จะล็อคทั้งหมด เครื่อง dev เนื้อของฉันเป็นข้อยกเว้นในการที่มันปั่นผ่านชุดข้อมูล 150 แหล่งในเวลาประมาณ 6 ชั่วโมง
ดังนั้นในการแก้ไขฉันลบส่วนประกอบหลายเธรดและทำความสะอาด I / O เมื่อไม่มีการเปลี่ยนแปลงใด ๆ เวลาดำเนินการของชุดข้อมูล 150 ซอร์สลดลงต่ำกว่า 10 นาทีบนเครื่องของฉันและจากระยะอนันต์ไปต่ำกว่าครึ่งชั่วโมงบนเครื่องของ บริษัท โดยเฉลี่ย
ฉันคิดว่าฉันสามารถเสนออัญมณีนี้ได้:
unsigned long isqrt(unsigned long value)
{
unsigned long tmp = 1, root = 0;
#define ISQRT_INNER(shift) \
{ \
if (value >= (tmp = ((root << 1) + (1 << (shift))) << (shift))) \
{ \
root += 1 << shift; \
value -= tmp; \
} \
}
// Find out how many bytes our value uses
// so we don't do any uneeded work.
if (value & 0xffff0000)
{
if ((value & 0xff000000) == 0)
tmp = 3;
else
tmp = 4;
}
else if (value & 0x0000ff00)
tmp = 2;
switch (tmp)
{
case 4:
ISQRT_INNER(15);
ISQRT_INNER(14);
ISQRT_INNER(13);
ISQRT_INNER(12);
case 3:
ISQRT_INNER(11);
ISQRT_INNER(10);
ISQRT_INNER( 9);
ISQRT_INNER( 8);
case 2:
ISQRT_INNER( 7);
ISQRT_INNER( 6);
ISQRT_INNER( 5);
ISQRT_INNER( 4);
case 1:
ISQRT_INNER( 3);
ISQRT_INNER( 2);
ISQRT_INNER( 1);
ISQRT_INNER( 0);
}
#undef ISQRT_INNER
return root;
}
เนื่องจากสแควร์รูทถูกคำนวณในที่ที่มีความอ่อนไหวมากฉันจึงมีหน้าที่มองหาวิธีที่จะทำให้มันเร็วขึ้น การปรับโครงสร้างขนาดเล็กนี้ช่วยลดเวลาดำเนินการหนึ่งในสาม (สำหรับการรวมกันของฮาร์ดแวร์และคอมไพเลอร์ที่ใช้ YMMV):
unsigned long isqrt(unsigned long value)
{
unsigned long tmp = 1, root = 0;
#define ISQRT_INNER(shift) \
{ \
if (value >= (tmp = ((root << 1) + (1 << (shift))) << (shift))) \
{ \
root += 1 << shift; \
value -= tmp; \
} \
}
ISQRT_INNER (15);
ISQRT_INNER (14);
ISQRT_INNER (13);
ISQRT_INNER (12);
ISQRT_INNER (11);
ISQRT_INNER (10);
ISQRT_INNER ( 9);
ISQRT_INNER ( 8);
ISQRT_INNER ( 7);
ISQRT_INNER ( 6);
ISQRT_INNER ( 5);
ISQRT_INNER ( 4);
ISQRT_INNER ( 3);
ISQRT_INNER ( 2);
ISQRT_INNER ( 1);
ISQRT_INNER ( 0);
#undef ISQRT_INNER
return root;
}
แน่นอนว่ามีทั้งวิธีที่เร็วกว่าและดีกว่าในการทำเช่นนี้ แต่ฉันคิดว่ามันเป็นตัวอย่างที่ค่อนข้างดีของการมองโลกในแง่ร้าย
แก้ไข: ลองคิดดูว่าวงวนที่ยังไม่ได้หมุนนั้นจริง ๆ แล้วก็เป็นแง่ร้ายอย่างเป็นระเบียบ การขุดแม้ว่าการควบคุมเวอร์ชันฉันสามารถแสดงขั้นตอนที่สองของการปรับโครงสร้างอีกครั้งซึ่งทำได้ดีกว่าข้างต้น:
unsigned long isqrt(unsigned long value)
{
unsigned long tmp = 1 << 30, root = 0;
while (tmp != 0)
{
if (value >= root + tmp) {
value -= root + tmp;
root += tmp << 1;
}
root >>= 1;
tmp >>= 2;
}
return root;
}
นี่เป็นอัลกอริทึมเดียวกันทั้งหมดแม้ว่าจะมีการนำไปใช้ที่แตกต่างกันเล็กน้อยดังนั้นฉันจึงถือว่ามีคุณสมบัติ
isqrt()
คำนวณfloor(sqrt())
แต่ทำไมรหัสนี้ใช้งานได้?
นี่อาจเป็นในระดับที่สูงกว่าสิ่งที่คุณเป็นอยู่ แต่การแก้ไข (ถ้าคุณได้รับอนุญาต) ยังเกี่ยวข้องกับความเจ็บปวดในระดับที่สูงขึ้น:
ยืนยันในการนำมือของ Object Relationship Manager / Data Access Layer แทนการใช้หนึ่งในไลบรารีที่สร้างขึ้นทดสอบแล้วและเป็นผู้ใหญ่
ข้อ จำกัด foreign-key ทั้งหมดถูกลบออกจากฐานข้อมูลเพราะมิฉะนั้นจะมีข้อผิดพลาดมากมาย
สิ่งนี้ไม่ตรงกับคำถาม แต่ฉันจะพูดถึงมันเป็นเรื่องเตือนอยู่แล้ว ฉันกำลังทำงานกับแอพแบบกระจายที่ทำงานช้าและบินลงไปที่ DC เพื่อนั่งในที่ประชุมโดยมีจุดประสงค์หลักในการแก้ปัญหา หัวหน้าโครงการเริ่มร่างสถาปัตยกรรมใหม่เพื่อแก้ไขความล่าช้า ฉันอาสาที่ฉันทำการวัดบางอย่างในช่วงสุดสัปดาห์ที่แยกคอขวดออกเป็นวิธีการเดียว ปรากฏว่ามีการบันทึกที่หายไปในการค้นหาในท้องถิ่นทำให้แอปพลิเคชันต้องไปที่เซิร์ฟเวอร์ระยะไกลในทุกธุรกรรม โดยการเพิ่มบันทึกกลับไปที่ร้านค้าในพื้นที่ความล่าช้าถูกกำจัด - แก้ปัญหาได้แล้ว หมายเหตุสถาปัตยกรรมใหม่จะไม่สามารถแก้ไขปัญหาได้
ตรวจสอบก่อนการใช้งานจาวาสคริปต์ทุกครั้งว่ามีวัตถุที่คุณทำงานอยู่หรือไม่
if (myObj) { //or its evil cousin, if (myObj != null) {
label.text = myObj.value;
// we know label exists because it has already been
// checked in a big if block somewhere at the top
}
ปัญหาของฉันกับรหัสประเภทนี้ดูเหมือนจะไม่มีใครสนใจถ้ามันไม่มีอยู่จริง? ไม่ทำอะไรเลยเหรอ? ไม่ได้ให้ข้อเสนอแนะกับผู้ใช้?
ฉันยอมรับว่าObject expected
ข้อผิดพลาดนั้นน่ารำคาญ แต่นี่ไม่ใช่ทางออกที่ดีที่สุดสำหรับสิ่งนั้น
วิธีการเกี่ยวกับความคลั่งไคล้ YAGNI มันเป็นรูปแบบของการมองโลกในแง่ร้ายก่อนวัยอันควร ดูเหมือนว่าทุกครั้งที่คุณสมัคร YAGNI จากนั้นคุณก็จำเป็นต้องใช้มันส่งผลให้มีความพยายามในการเพิ่ม 10 เท่ามากกว่าที่คุณได้เพิ่มไว้ในตอนแรก หากคุณสร้างโปรแกรมที่ประสบความสำเร็จคุณก็จะต้องต่อรอง หากคุณคุ้นเคยกับการสร้างโปรแกรมที่ชีวิตของเขาหมดลงอย่างรวดเร็วให้ฝึกฝน YAGNI ต่อไปเพราะฉันคิดว่า YAGNI
ไม่ใช่การเพิ่มประสิทธิภาพก่อนวัยอันควรอย่างแน่นอน - แต่เข้าใจผิดอย่างแน่นอน - นี่ถูกอ่านบนเว็บไซต์ BBC จากบทความที่พูดถึง Windows 7
นายเคอร์แรนกล่าวว่าทีม Microsoft Windows ได้รับความสนใจในทุกด้านของระบบปฏิบัติการเพื่อปรับปรุง "เราสามารถโกนทิ้งได้ 400 มิลลิวินาทีจากเวลาปิดเครื่องโดยตัดแต่งเพลงปิดไฟล์ WAV เล็กน้อย
ตอนนี้ฉันยังไม่ได้ลอง Windows 7 ดังนั้นฉันอาจผิด แต่ฉันยินดีที่จะเดิมพันว่ามีปัญหาอื่น ๆ ที่สำคัญมากกว่าระยะเวลาที่ปิดเครื่อง หลังจากทั้งหมดเมื่อฉันเห็นข้อความ 'ปิดระบบ Windows' จอภาพจะปิดและฉันเดินไป - 400 มิลลิวินาทีนั้นมีประโยชน์ต่อฉันอย่างไร
มีคนในแผนกของฉันเคยเขียนคลาสสตริง อินเทอร์เฟซที่ชอบCString
แต่ไม่มีการพึ่งพา Windows
"การเพิ่มประสิทธิภาพ" อย่างหนึ่งที่พวกเขาทำคือไม่จัดสรรหน่วยความจำเกินความจำเป็น เห็นได้ชัดว่าไม่ทราบว่าเหตุผลของคลาสเช่นstd::string
จัดสรรหน่วยความจำส่วนเกินเพื่อให้ลำดับของ+=
การดำเนินการสามารถทำงานในเวลา O (n)
แต่ทุกเดียว+=
โทรบังคับจัดสรรซึ่งกลายผนวกซ้ำเป็น O (n²) อัลกอริทึม Schlemiel จิตรกร
อดีตเพื่อนร่วมงานของฉัน ( จริง ๆ แล้วเป็นsoab ) ได้รับมอบหมายให้สร้างโมดูลใหม่สำหรับ Java ERP ของเราที่ควรรวบรวมและวิเคราะห์ข้อมูลของลูกค้า (อุตสาหกรรมค้าปลีก) เขาตัดสินใจที่จะแยกฟิลด์ปฏิทิน / วันที่ออกทุก ๆ วันในองค์ประกอบของมัน (วินาที, นาที, ชั่วโมง, วัน, เดือน, ปี, วัน, สัปดาห์, bimester, trimester (!)) เพราะ "ฉันจะค้นหา 'ทุกวันจันทร์' ได้อย่างไร
ไม่มีความผิดต่อใคร แต่ฉันเพิ่งให้คะแนน (java) ที่มีสิ่งนี้
import java.lang.*;