เพิ่มประสิทธิภาพโปรแกรมผ่านข้อกำหนดของรหัส Java เพิ่มประสิทธิภาพการใช้หน่วยความจำและป้องกันการรั่วไหลของหน่วยความจำ
ทรัพยากรที่มีอยู่สำหรับโปรแกรมที่จะใช้ (หน่วยความจำ, เวลา CPU, แบนด์วิดท์เครือข่าย ฯลฯ ) มี จำกัด การเพิ่มประสิทธิภาพมักจะมีสองด้าน: ลดขนาดของรหัสและปรับปรุงประสิทธิภาพการทำงานของรหัส บทความนี้ส่วนใหญ่กล่าวถึงวิธีการปรับปรุงประสิทธิภาพของรหัส
ในโปรแกรม Java สาเหตุส่วนใหญ่ของปัญหาการปฏิบัติงานไม่ได้อยู่ในภาษา Java แต่อยู่ในโปรแกรมเอง มันเป็นสิ่งสำคัญมากในการพัฒนานิสัยการเขียนรหัสที่ดีเช่นการใช้ Java.lang.String Class และ Java.util.Vector Class ซึ่งสามารถปรับปรุงประสิทธิภาพของโปรแกรมได้อย่างถูกต้องและชาญฉลาด มาวิเคราะห์ปัญหานี้โดยละเอียดด้านล่าง
1. พยายามระบุว่าตัวดัดแปลงสุดท้ายของคลาส
ใน Java Core API มีตัวอย่างมากมายของการใช้ขั้นสุดท้ายเช่น java.lang.string การระบุขั้นสุดท้ายสำหรับคลาสสตริงป้องกันผู้คนจากการเขียนทับความยาว () วิธี นอกจากนี้หากมีการระบุคลาสเป็นขั้นสุดท้ายวิธีทั้งหมดของคลาสนั้นถือเป็นที่สิ้นสุด คอมไพเลอร์ Java จะมองหาโอกาสในการอินไลน์วิธีสุดท้ายทั้งหมด (ซึ่งเกี่ยวข้องกับการใช้งานคอมไพเลอร์เฉพาะ) การเคลื่อนไหวนี้สามารถปรับปรุงประสิทธิภาพได้โดยเฉลี่ย 50%
2. พยายามนำวัตถุกลับมาใช้ใหม่
โดยเฉพาะอย่างยิ่งเมื่อใช้วัตถุสตริงจะใช้ StringBuffer แทนเมื่อเกิดการต่อการเชื่อมต่อสตริง เนื่องจากระบบไม่เพียง แต่ต้องใช้เวลาในการสร้างวัตถุ แต่ยังต้องใช้เวลาในการเก็บขยะและประมวลผลวัตถุเหล่านี้ในอนาคต ดังนั้นการสร้างวัตถุมากเกินไปจะมีผลกระทบอย่างมากต่อประสิทธิภาพของโปรแกรม
3. พยายามใช้ตัวแปรท้องถิ่น
ตัวแปรอื่น ๆ เช่นตัวแปรคงที่ตัวแปรอินสแตนซ์ ฯลฯ ถูกสร้างขึ้นในกองและช้าลง นอกจากนี้ตัวแปรท้องถิ่นอาจได้รับการปรับให้เหมาะสมต่อไปขึ้นอยู่กับคอมไพเลอร์/JVM เฉพาะ ดู "ใช้ตัวแปรสแต็กทุกครั้งที่เป็นไปได้"
4. อย่าทำซ้ำการเริ่มต้นของตัวแปร <br /> โดยค่าเริ่มต้นเมื่อเรียกตัวสร้างคลาส Java จะเริ่มต้นตัวแปรเป็นค่าที่แน่นอน: วัตถุทั้งหมดถูกตั้งค่าเป็น null ตัวแปรจำนวนเต็ม (ไบต์สั้น, int, ยาว) เป็น 0 ตัวแปรลอยและสองตัวถูกตั้งค่าเป็น 0.0 และค่าโลจิคัลถูกตั้งค่าเป็นเท็จ สิ่งนี้ควรสังเกตได้โดยเฉพาะอย่างยิ่งเมื่อคลาสได้มาจากอีกคลาสเพราะเมื่อวัตถุถูกสร้างขึ้นด้วยคำหลักใหม่ตัวสร้างทั้งหมดในห่วงโซ่คอนสตรัคเตอร์จะถูกเรียกโดยอัตโนมัติ
5. ในการพัฒนาระบบแอปพลิเคชัน Java + Oracle ลองใช้แบบฟอร์มตัวพิมพ์ใหญ่ใน Java เพื่อลดภาระการแยกวิเคราะห์ของตัวแยกวิเคราะห์ Oracle
6. ในระหว่างการเขียนโปรแกรม Java ระวังเมื่อทำการเชื่อมต่อฐานข้อมูลและการดำเนินการสตรีมมิ่ง I/O
เนื่องจากการทำงานของวัตถุขนาดใหญ่เหล่านี้จะทำให้เกิดค่าใช้จ่ายของระบบขนาดใหญ่และหากคุณไม่ระวังมันจะนำไปสู่ผลกระทบร้ายแรง
7. เนื่องจาก JVM มีกลไก GC ของตัวเองจึงไม่ต้องการการพิจารณาจากนักพัฒนาโปรแกรมมากเกินไปซึ่งจะช่วยลดภาระของนักพัฒนาในระดับหนึ่ง แต่ยังพลาดอันตรายที่ซ่อนอยู่ ใน ระบบ
เงื่อนไขสำหรับ JVM ในการรีไซเคิลขยะคือวัตถุไม่ได้อ้างอิง ดังนั้นจึงขอแนะนำให้เราตั้งค่าเป็นโมฆะด้วยตนเองหลังจากใช้วัตถุ
8. เมื่อใช้กลไกการซิงโครไนซ์ลองใช้การซิงโครไนซ์วิธีการแทนการซิงโครไนซ์บล็อก
9. ลดการคำนวณตัวแปรซ้ำ ๆ ซ้ำ ๆ <br /> ตัวอย่างเช่น: สำหรับ (int i = 0; i <list.size; i ++) {
-
-
ควรถูกแทนที่ด้วย:
สำหรับ (int i = 0, int len = list.size (); i <len; i ++) {
-
-
10. พยายามใช้กลยุทธ์การโหลดขี้เกียจนั่นคือเริ่มสร้างเมื่อจำเป็น
ตัวอย่างเช่น: string str =“ aaa”;
ถ้า (i == 1) {
list.add (str);
-
ควรถูกแทนที่ด้วย:
ถ้า (i == 1) {
string str =“ aaa”;
list.add (str);
-
11. ใช้ความผิดปกติด้วยความระมัดระวัง
ความผิดปกติไม่ดีต่อประสิทธิภาพ ในการโยนข้อยกเว้นคุณต้องสร้างวัตถุใหม่ก่อน ตัวสร้างของอินเทอร์เฟซแบบ throwable เรียกใช้วิธีการในท้องถิ่น (ดั้งเดิม) ชื่อ FillinstackTrace () และวิธี FillinstackTrace () ตรวจสอบสแต็กและรวบรวมข้อมูลการติดตามการโทร ตราบใดที่มีการโยนข้อยกเว้น VM จะต้องปรับสแต็กการโทรเนื่องจากวัตถุใหม่ถูกสร้างขึ้นระหว่างการประมวลผล ข้อยกเว้นสามารถใช้สำหรับการจัดการข้อผิดพลาดเท่านั้นและไม่ควรใช้เพื่อควบคุมการไหลของโปรแกรม
12. อย่าใช้ในวง:
พยายาม {
} จับ() {
-
ควรวางไว้บนชั้นนอกสุด
13. การใช้ StringBuffer:
StringBuffer แสดงถึงตัวแปรสตริงที่เขียนได้
มีวิธีการก่อสร้างสามวิธี:
StringBuffer ();
StringBuffer (ขนาด int);
StringBuffer (String Str); // กำหนด 16 อักขระ + str.length () พื้นที่อักขระคุณสามารถตั้งค่าความสามารถในการเริ่มต้นผ่านตัวสร้าง StringBuffer ซึ่งสามารถปรับปรุงประสิทธิภาพได้อย่างมีนัยสำคัญ
ตัวสร้างที่กล่าวถึงที่นี่คือ StringBuffer (ความยาว int) และพารามิเตอร์ความยาวระบุจำนวนอักขระที่สตริงบัฟเฟอร์ปัจจุบันสามารถถือได้ นอกจากนี้คุณยังสามารถใช้วิธีการ ensurecapacity (ความจุขั้นต่ำ int) เพื่อตั้งค่าความจุหลังจากสร้างวัตถุ StringBuffer ก่อนอื่นมาดูพฤติกรรมเริ่มต้นของ StringBuffer จากนั้นหาวิธีที่ดีกว่าในการปรับปรุงประสิทธิภาพ
StringBuffer รักษาอาร์เรย์อักขระไว้ภายใน เมื่อ StringBuffer ถึงกำลังการผลิตสูงสุดมันจะเพิ่มกำลังการผลิตเป็น 2 เท่าของความจุปัจจุบันและเพิ่ม 2 นั่นคือ (2*ค่าเก่า +2) หากคุณใช้ค่าเริ่มต้นหลังจากการเริ่มต้นให้เพิ่มอักขระลงไป ถึง 70 (2*34+2) ไม่ว่าจะเป็นอะไรตราบใดที่ Stringbuffer ถึงความจุสูงสุดมันจะต้องสร้างอาร์เรย์ตัวละครใหม่แล้วจึงทำการคัดลอกทั้งตัวละครเก่าและใหม่ ดังนั้นจึงไม่ผิดที่จะตั้งค่าความสามารถในการเริ่มต้นที่สมเหตุสมผลสำหรับ StringBuffer ซึ่งจะนำมาซึ่งประสิทธิภาพการทำงานทันที สิ่งนี้แสดงให้เห็นถึงบทบาทของการปรับกระบวนการเริ่มต้น StringBuffer ดังนั้นการใช้ค่าความจุที่เหมาะสมในการเริ่มต้นสตริงบัฟเฟอร์จึงเป็นคำแนะนำที่ดีที่สุดเสมอ
14. ใช้ Java Class Java.util.vector อย่างสมเหตุสมผล
พูดง่ายๆคือเวกเตอร์เป็นอาร์เรย์ของ java.lang.Object อินสแตนซ์ เวกเตอร์คล้ายกับอาร์เรย์และองค์ประกอบของมันสามารถเข้าถึงได้ผ่านดัชนีในรูปแบบของจำนวนเต็ม อย่างไรก็ตามหลังจากการสร้างวัตถุประเภทเวกเตอร์ขนาดของวัตถุสามารถขยายและลดลงตามการเพิ่มหรือการลบองค์ประกอบ โปรดพิจารณาตัวอย่างต่อไปนี้ของการเพิ่มองค์ประกอบในเวกเตอร์:
วัตถุ bj = วัตถุใหม่ ();
เวกเตอร์ V = เวกเตอร์ใหม่ (100000);
สำหรับ (int i = 0;
ฉัน <100000;
เว้นแต่จะมีเหตุผลเพียงพอที่จะต้องใช้องค์ประกอบใหม่ที่จะแทรกต่อหน้าเวกเตอร์ทุกครั้งรหัสข้างต้นไม่ดีสำหรับประสิทธิภาพ ในตัวสร้างเริ่มต้นความสามารถในการจัดเก็บข้อมูลเริ่มต้นของเวกเตอร์คือ 10 องค์ประกอบ คลาสเวกเตอร์เป็นเหมือนคลาสสตริงบัฟเฟอร์ ตัวอย่างโค้ดต่อไปนี้เป็นคำสั่งของขนาดเร็วกว่าตัวอย่างก่อนหน้า:
วัตถุ bj = วัตถุใหม่ ();
เวกเตอร์ V = เวกเตอร์ใหม่ (100000);
สำหรับ (int i = 0; i <100000; i ++) {v.add (obj);
กฎเดียวกันนี้ใช้กับวิธีการลบ () ของคลาสเวกเตอร์ เนื่องจากแต่ละองค์ประกอบในเวกเตอร์ไม่สามารถมี "ช่องว่าง" ระหว่างแต่ละองค์ประกอบการลบองค์ประกอบอื่น ๆ ยกเว้นองค์ประกอบสุดท้ายทำให้องค์ประกอบหลังจากองค์ประกอบที่ถูกลบเพื่อก้าวไปข้างหน้า นั่นคือการลบองค์ประกอบสุดท้ายจากเวกเตอร์นั้นน้อยกว่า "ค่าใช้จ่าย" น้อยกว่าการลบองค์ประกอบแรกหลายเท่า
สมมติว่าเราต้องการลบองค์ประกอบทั้งหมดออกจากเวกเตอร์ก่อนหน้านี้เราสามารถใช้รหัสนี้:
สำหรับ (int i = 0; i <100000; i ++)
-
V.Remove (0);
-
อย่างไรก็ตามเมื่อเปรียบเทียบกับรหัสต่อไปนี้รหัสก่อนหน้านี้เป็นคำสั่งของขนาดช้าลง:
สำหรับ (int i = 0; i <100000; i ++)
-
V.Remove (V.Size ()-1);
-
วิธีที่ดีที่สุดในการลบองค์ประกอบทั้งหมดออกจากวัตถุ V ของประเภทเวกเตอร์คือ:
V.removeAllelements ();
สมมติว่าวัตถุ V ของประเภทเวกเตอร์มีสตริง "สวัสดี" พิจารณารหัสต่อไปนี้ซึ่งจะลบสตริง "สวัสดี" ออกจากเวกเตอร์นี้:
สตริง s = "สวัสดี";
int i = v.indexof (s);
ถ้า (i! = -1) v.remove (s);
รหัสดูเหมือนไม่มีอะไรผิดปกติ แต่ก็ไม่ดีสำหรับประสิทธิภาพ ในรหัสนี้เมธอดดัชนี () จะค้นหา V ตามลำดับเพื่อค้นหาสตริง "สวัสดี" และวิธีการลบ (S) จำเป็นต้องค้นหาในลำดับเดียวกัน เวอร์ชันที่ปรับปรุงแล้วคือ:
สตริง s = "สวัสดี";
int i = v.indexof (s);
ถ้า (i! = -1) v.remove (i);
ในรุ่นนี้เราให้ตำแหน่งดัชนีที่แน่นอนโดยตรงขององค์ประกอบที่จะถูกลบในวิธีการลบ () ดังนั้นจึงหลีกเลี่ยงการค้นหาครั้งที่สอง เวอร์ชันที่ดีกว่าคือ:
String S = "Hello";
ในที่สุดลองดูที่โค้ดตัวอย่างเกี่ยวกับคลาสเวกเตอร์:
สำหรับ (int i = 0; i ++; i <v.length)
ถ้า V มี 100,000 องค์ประกอบโค้ดนี้จะเรียกวิธี V.Size () วิธี 100,000 ครั้ง แม้ว่าวิธีการขนาดจะเป็นวิธีที่ง่าย แต่ก็ยังต้องใช้ค่าใช้จ่ายของการเรียกใช้วิธีการอย่างน้อย JVM จำเป็นต้องกำหนดค่าและล้างสภาพแวดล้อมสแต็กสำหรับมัน ที่นี่รหัสภายใน For Loop จะไม่แก้ไขขนาดของวัตถุประเภทเวกเตอร์ V ไม่ว่าด้วยวิธีใดดังนั้นรหัสด้านบนจะถูกเขียนขึ้นใหม่ในแบบฟอร์มต่อไปนี้:
ขนาด int = v.size ();
ในขณะที่นี่เป็นการเปลี่ยนแปลงที่เรียบง่าย แต่ก็ยังชนะการแสดง ท้ายที่สุดทุกรอบ CPU นั้นมีค่า
15. เมื่อคัดลอกข้อมูลจำนวนมากให้ใช้คำสั่ง system.arraycopy ()
16. การปรับโครงสร้างรหัส: เพิ่มความสามารถในการอ่านรหัส
ตัวอย่างเช่น:
คลาสสาธารณะ Shopcart {รายการส่วนตัวรถเข็น; …โมฆะสาธารณะเพิ่ม (รายการวัตถุ) {ถ้า (carts == null) {carts = new ArrayList ();} crts.add (รายการ);} โมฆะสาธารณะลบ (รายการวัตถุ) {ถ้าถ้า (รถเข็น. มี (รายการ)) {carts.remove (รายการ);}} รายการสาธารณะ getCarts () {// ส่งคืนรายการคืนรายการอ่านรายการ unmodifiablelist (รถเข็น);} // วิธีนี้ไม่แนะนำ // นี้ . 17. สร้างอินสแตนซ์ของคลาสโดยไม่ต้องใช้คำหลักใหม่
เมื่อสร้างอินสแตนซ์ของคลาสที่มีคำหลักใหม่ตัวสร้างทั้งหมดในห่วงโซ่คอนสตรัคเตอร์จะถูกเรียกโดยอัตโนมัติ แต่ถ้าวัตถุใช้อินเทอร์เฟซ cloneable เราสามารถเรียกวิธีการโคลน () ของมัน วิธีการ clone () ไม่เรียกตัวสร้างคลาสใด ๆ
เมื่อใช้รูปแบบการออกแบบหากคุณใช้โหมดโรงงานเพื่อสร้างวัตถุมันเป็นเรื่องง่ายมากที่จะใช้เมธอด clone () เพื่อสร้างอินสแตนซ์วัตถุใหม่ ตัวอย่างเช่นต่อไปนี้เป็นการใช้งานทั่วไปของรูปแบบโรงงาน:
เครดิตสาธารณะคงที่ getNewCredit () {
คืนเครดิตใหม่ ();
-
รหัสที่ได้รับการปรับปรุงใช้วิธีการโคลน () ดังนี้:
เครดิตคงที่ส่วนตัว basecredit = เครดิตใหม่ ();
เครดิตสาธารณะคงที่ getNewCredit () {
ผลตอบแทน (เครดิต) basecredit.clone ();
-
แนวคิดข้างต้นยังมีประโยชน์มากสำหรับการประมวลผลอาร์เรย์
18. การคูณและการหาร
พิจารณารหัสต่อไปนี้:
สำหรับ (val = 0; val <100000; val += 5) {
Alterx = val * 8;
-
การแทนที่การคูณด้วยการดำเนินการกะสามารถปรับปรุงประสิทธิภาพได้อย่างมาก นี่คือรหัสที่แก้ไขแล้ว:
สำหรับ (val = 0; val <100000; val += 5) {
Alterx = val << 3;
-
รหัสที่ได้รับการแก้ไขจะไม่ทวีคูณอีกต่อไป 8 แต่แทนที่จะใช้การเลื่อนซ้ายที่เทียบเท่า 3 บิตโดยมี 1 บิตต่อการเลื่อนซ้ายเทียบเท่ากับการคูณด้วย 2 ดังนั้นการเปลี่ยนแปลงที่ถูกต้องโดยการดำเนินการ 1 บิตเทียบเท่ากับการหารด้วย 2 เป็นเรื่องที่ควรค่าแก่การกล่าวถึงว่าแม้ว่าการดำเนินการกะนั้นรวดเร็ว แต่ก็อาจทำให้รหัสเข้าใจยากดังนั้นจึงเป็นการดีที่สุดที่จะเพิ่มความคิดเห็น
19. ปิดการประชุมที่ไร้ประโยชน์ในหน้า JSP
ความเข้าใจผิดทั่วไปคือเซสชันถูกสร้างขึ้นเมื่อมีการเข้าถึงไคลเอนต์ ใช้ <> เพื่อปิดเซสชัน เนื่องจากเซสชันใช้ทรัพยากรหน่วยความจำหากคุณไม่ได้วางแผนที่จะใช้เซสชันคุณควรปิดใน JSP ทั้งหมด
สำหรับหน้าเว็บที่ไม่จำเป็นต้องติดตามสถานะเซสชันการปิดเซสชันที่สร้างขึ้นโดยอัตโนมัติสามารถบันทึกทรัพยากรบางอย่างได้ ใช้คำสั่งหน้าต่อไปนี้: <%@ page session = "false"%>
20. JDBC และ I/O
หากแอปพลิเคชันต้องการเข้าถึงชุดข้อมูลขนาดใหญ่คุณควรพิจารณาใช้การสกัดบล็อก โดยค่าเริ่มต้น JDBC แยกข้อมูล 32 แถวในแต่ละครั้ง ตัวอย่างเช่นสมมติว่าเราต้องการสำรวจชุดระเบียน 5,000 แถว JDBC ต้องเรียกฐานข้อมูล 157 ครั้งก่อนที่จะสามารถแยกข้อมูลทั้งหมดได้ หากขนาดบล็อกเปลี่ยนเป็น 512 จำนวนการโทรไปยังฐานข้อมูลจะลดลงเหลือ 10 เท่า
21. การใช้งาน Servlet และหน่วยความจำ <br /> นักพัฒนาหลายคนบันทึกข้อมูลจำนวนมากไปยังเซสชันผู้ใช้ตามต้องการ บางครั้งวัตถุที่เก็บไว้ในเซสชั่นจะไม่ถูกรีไซเคิลโดยกลไกการรวบรวมขยะในเวลา จากมุมมองของประสิทธิภาพอาการทั่วไปคือผู้ใช้รู้สึกว่าระบบกำลังชะลอตัวลงเป็นระยะ แต่ไม่สามารถระบุเหตุผลของส่วนประกอบที่เฉพาะเจาะจงได้ หากคุณตรวจสอบพื้นที่กอง JVM ของ JVM มันจะปรากฏเป็นความผันผวนของการใช้หน่วยความจำที่ผิดปกติ
มีสองวิธีหลักในการแก้ปัญหาหน่วยความจำประเภทนี้ วิธีแรกคือการใช้อินเทอร์เฟซ HttpsessionBindingListener ในถั่วทั้งหมดที่มีขอบเขตของเซสชัน ด้วยวิธีนี้ตราบใดที่ใช้วิธีการ ValueUnBound () ทรัพยากรที่ใช้โดยถั่วสามารถปล่อยออกมาได้อย่างชัดเจน
อีกวิธีหนึ่งคือการทำให้เซสชันเป็นโมฆะโดยเร็วที่สุด เซิร์ฟเวอร์แอปพลิเคชันส่วนใหญ่มีตัวเลือกในการตั้งค่าช่วงเวลาการทำให้เป็นโมฆะเซสชัน นอกจากนี้วิธี SetMaxinactiveInterval () ของเซสชันยังสามารถเรียกได้ว่าเป็นโปรแกรม
22. ใช้เครื่องหมายบัฟเฟอร์
เซิร์ฟเวอร์แอปพลิเคชันบางตัวได้เพิ่มฟังก์ชั่นการทำเครื่องหมายบัฟเฟอร์สำหรับ JSP ตัวอย่างเช่นเซิร์ฟเวอร์ WebLogic ของ Bea รองรับคุณสมบัตินี้ตั้งแต่เวอร์ชัน 6.0 และโครงการ Open Symphony ยังรองรับคุณสมบัตินี้ด้วย แท็กบัฟเฟอร์ JSP สามารถบัฟเฟอร์ทั้งส่วนหน้าและทั้งหน้า เมื่อหน้า JSP ถูกดำเนินการหากชิ้นส่วนเป้าหมายอยู่ในบัฟเฟอร์แล้วรหัสที่สร้างแฟรกเมนต์จะไม่จำเป็นต้องดำเนินการอีกต่อไป บัฟเฟอร์ระดับหน้าจับคำขอไปยัง URL ที่ระบุและบัฟเฟอร์หน้าผลลัพธ์ทั้งหมด ฟีเจอร์นี้มีประโยชน์อย่างยิ่งสำหรับการช็อปปิ้งตะกร้าแคตตาล็อกและหน้าแรกของพอร์ทัล สำหรับแอปพลิเคชันดังกล่าวการบัฟเฟอร์ระดับหน้าสามารถบันทึกผลลัพธ์ของการดำเนินการหน้าสำหรับคำขอที่ตามมา
23. เลือกกลไกการอ้างอิงที่เหมาะสม
ในระบบแอปพลิเคชัน JSP ทั่วไปชิ้นส่วนส่วนหัวและส่วนท้ายมักจะถูกสกัดและจากนั้นส่วนหัวและส่วนท้ายจะถูกนำมาใช้ตามต้องการ ปัจจุบันมีสองวิธีหลักในการแนะนำทรัพยากรภายนอกในหน้า JSP: รวมคำสั่งและรวมถึงการกระทำ
รวมคำสั่ง: ตัวอย่างเช่น < %@ รวมไฟล์ = "Copyright.html" %> คำสั่งนี้แนะนำทรัพยากรที่ระบุในเวลาคอมไพล์ ก่อนการรวบรวมหน้าพร้อมคำสั่งรวมและทรัพยากรที่ระบุจะถูกรวมเข้ากับไฟล์ ทรัพยากรภายนอกที่อ้างอิงจะถูกกำหนดในเวลาที่รวบรวมซึ่งมีประสิทธิภาพมากกว่าการกำหนดทรัพยากรในเวลารันไทม์
รวมการดำเนินการ: ตัวอย่าง <jsp: รวม page = "copyright.jsp" /> การดำเนินการนี้แนะนำผลลัพธ์ที่สร้างขึ้นหลังจากดำเนินการหน้าที่ระบุ เนื่องจากเสร็จสิ้นในเวลารันไทม์การควบคุมผลลัพธ์เอาต์พุตจึงมีความยืดหยุ่นมากขึ้น อย่างไรก็ตามมันเป็นเพียงค่าใช้จ่ายที่จะใช้รวมถึงการกระทำเมื่อเนื้อหาที่ยกมามีการเปลี่ยนแปลงบ่อยครั้งหรือเมื่อไม่สามารถกำหนดหน้าอ้างอิงได้ก่อนที่คำขอสำหรับหน้าหลักจะปรากฏขึ้น
24. เคลียร์ไม่จำเป็นต้องมีเซสชันในเวลาอีกต่อไป
เพื่อล้างเซสชันที่ไม่ได้ใช้งานอีกต่อไปเซิร์ฟเวอร์แอปพลิเคชันจำนวนมากมีการหมดเวลาเซสชันเริ่มต้นโดยปกติ 30 นาที เมื่อแอปพลิเคชันเซิร์ฟเวอร์ต้องการบันทึกเซสชันมากขึ้นหากความจุหน่วยความจำไม่เพียงพอระบบปฏิบัติการจะถ่ายโอนส่วนหนึ่งของข้อมูลหน่วยความจำไปยังดิสก์ จัดเก็บลงในดิสก์และอาจโยนข้อยกเว้น "หน่วยความจำออก" ในระบบขนาดใหญ่เซสชันอนุกรมมีราคาแพง เมื่อไม่จำเป็นต้องใช้เซสชั่นอีกต่อไปวิธีการ httpsession.invalidate () ควรถูกเรียกในเวลาเพื่อล้างเซสชัน วิธี httpsession.invalidate () สามารถเรียกได้ในหน้าออกของแอปพลิเคชัน
25. อย่าประกาศอาเรย์เป็น: สาธารณะคงที่
26. การอภิปรายเกี่ยวกับประสิทธิภาพการเดินทางของ HashMap
มักจะมีการดำเนินการสำรวจข้ามคีย์และคู่ค่าใน hashmap และมีสองวิธี: แผนที่ <สตริงสตริง []> paramap = ใหม่
hashmap <string, string []> (); ............ // ชุดลูปแรก <string> appfielddefids = paramap.keyset (); ] ค่า = paramap.get (appfielddefid); ...... } // ลูปที่สองสำหรับ (รายการ <สตริง, สตริง []> รายการ: paramap.entryset ()) {สตริง appfielddefid = entry.getKey ( ); สตริง [] ค่า = entry.getValue (); ....... } การใช้งานครั้งแรกมีประสิทธิภาพน้อยกว่าการใช้งานครั้งที่สองอย่างมีนัยสำคัญ
การวิเคราะห์มีดังนี้ Set <string> AppFieldDefids = paramap.keyset ();
รหัสมีดังนี้:
ชุดสาธารณะ <k> keyset () {set <k> ks = keyset; return (ks! = null? ks: (keyset = new keyset ()));} คีย์คลาสส่วนตัวขยาย Abstractset <k> {Public Reterator <k K > iterator () {return newKeyIterator ();} ขนาด int สาธารณะ () {ขนาดคืน;} บูลีนสาธารณะมี (วัตถุ o) {return containskey (o);} บูลีนสาธารณะลบ (วัตถุ o) (o)! = null;} โมฆะสาธารณะ Clear () {hashmap.this.clear ();}}ในความเป็นจริงมันส่งคืนคีย์คลาสส่วนตัวซึ่งสืบทอดมาจาก AbstractSet และใช้อินเทอร์เฟซที่ตั้งไว้
มาดูไวยากรณ์ของสำหรับ/in loops
สำหรับ (การประกาศ: การแสดงออก)
คำแถลง
ในระหว่างขั้นตอนการดำเนินการจะถูกแปลเป็นสูตรต่อไปนี้
สำหรับ (iterator <e> #i = (นิพจน์) .Iterator (); #i.hashNext ();) {
ประกาศ = #i.next ();
คำแถลง
-
ดังนั้น hashmap.keyset (). iterator () เรียกว่าในคำสั่งแรกสำหรับ (สตริง appfielddefid: appfielddefids)
วิธีนี้เรียก NewKeyIterator ()
ตัววนซ้ำ <k> newKeyIterator () {
ส่งคืน Keyiterator ใหม่ ();
-
Keyiterator คลาสส่วนตัวขยาย Hashiterator <K> {
Public K Next () {
Return Nextentry (). getKey ();
-
-
ดังนั้นใน FOR ตัววนซ้ำที่ใช้ในลูปที่สองสำหรับ (รายการ <สตริง, สตริง []> รายการ: paramap.entryset ()) เรียกว่าดังนี้
ใจดี
ผู้เข้าเรียนในชั้นเรียนส่วนตัวขยาย Hashiterator <map.entry <k, v >> {
แผนที่สาธารณะ. entry <k, v> next () {
ส่งคืน Nextentry ();
-
-
ในเวลานี้ลูปแรกได้รับกุญแจและลูปที่สองได้รับประสิทธิภาพการเข้าของ HashMap คือการวนรอบที่สองที่สะท้อนในลูป ใช้ HashMap's GET (คีย์วัตถุ) เพื่อรับค่าค่าตอนนี้ดูที่วิธี GET (Key Object) ของ HashMap
สาธารณะ v รับ (คีย์วัตถุ) {
วัตถุ k = masknull (คีย์);
int hash = hash (k);
int i = indexfor (แฮช, table.length);
รายการ <k, v> e = ตาราง;
ในขณะที่ (จริง) {
ถ้า (e == null)
คืนค่า null;
ถ้า (e.hash == hash && eq (k, e.key))
ส่งคืน e.value;
e = e.next;
-
-
ในความเป็นจริงมันคือการใช้ค่าแฮชเพื่อรับรายการที่เกี่ยวข้องอีกครั้งเพื่อเปรียบเทียบและรับผลลัพธ์
ในลูปที่สองจะได้รับค่ารายการจากนั้นใช้คีย์และค่าโดยตรงซึ่งมีประสิทธิภาพมากกว่าลูปแรก ในความเป็นจริงตามแนวคิดของแผนที่มันควรจะดีกว่าที่จะใช้ลูปที่สอง
27. การใช้อาร์เรย์ (อาร์เรย์) และ arrylist
อาร์เรย์ ([]): มีประสิทธิภาพมากที่สุด
ArrayList: ความสามารถสามารถเติบโตได้
ควรใช้อาร์เรย์ให้มากที่สุดเท่าที่จะทำได้
ArrayList เป็นอาร์เรย์รุ่นที่ซับซ้อน
ArrayList ห่อหุ้มอาร์เรย์ประเภทวัตถุโดยทั่วไปมันไม่มีความแตกต่างที่สำคัญจากอาร์เรย์ วิธีการอาร์เรย์
เมื่อ ArrayList เก็บวัตถุข้อมูลประเภทจะถูกยกเลิกและวัตถุทั้งหมดจะถูกบล็อกเป็นวัตถุ
หมายเหตุ: JDK5 ได้เพิ่มการสนับสนุนสำหรับทั่วไปและการตรวจสอบประเภทสามารถทำได้เมื่อใช้ ArrayList
จากมุมมองนี้ความแตกต่างระหว่าง ArrayList และ Array ส่วนใหญ่เป็นผลมาจากประสิทธิภาพของการเพิ่มความจุแบบไดนามิก
28. พยายามใช้ HashMap และ ArrayList
29. ความแตกต่างระหว่าง StringBuffer และ StringBuilder:
java.lang.StringBuffer ลำดับอักขระที่ไม่แน่นอน บัฟเฟอร์สตริงเหมือนสตริง แต่ไม่สามารถแก้ไขได้
StringBuilder เมื่อเทียบกับคลาสนี้คลาส Java.lang.StringBuilder ควรเป็นที่ต้องการเพราะรองรับการดำเนินการเดียวกันทั้งหมด แต่เร็วกว่าเพราะมันไม่ได้ทำการซิงโครไนซ์ เพื่อประสิทธิภาพที่ดีขึ้นควรระบุความสามารถของ stirngbuffer หรือ stirngbuilder ให้มากที่สุด แน่นอนถ้าสตริงที่คุณทำงานมีความยาวไม่เกิน 16 อักขระคุณจะไม่ต้องการมัน ในกรณีเดียวกันการใช้ stirngbuilder สามารถบรรลุการปรับปรุงประสิทธิภาพประมาณ 10% -15% เมื่อเทียบกับการใช้ StringBuffer แต่ต้องเสี่ยงต่อการไม่ปลอดภัยหลายเธรด ในการเขียนโปรแกรมแบบแยกส่วนจริงโปรแกรมเมอร์ที่รับผิดชอบในโมดูลบางอย่างอาจไม่สามารถระบุได้อย่างชัดเจนว่าโมดูลจะถูกนำไปใช้ในสภาพแวดล้อมแบบมัลติเธรดหรือไม่: ถ้าคุณไม่สามารถระบุได้ว่าคอขวดของระบบของคุณอยู่บนสตริงบัฟเฟอร์และ ตรวจสอบให้แน่ใจว่าโมดูลของคุณจะไม่ทำงานในโหมดมัลติเธรดมิฉะนั้นใช้ StringBuffer
อาหารเสริมอื่น ๆ :
1. วัตถุที่ชัดเจนที่ไม่ได้ใช้ในเวลาและตั้งค่าเป็นโมฆะอีกต่อไป
2. ใช้คำหลักขั้นสุดท้ายคงที่และอื่น ๆ ให้มากที่สุด
3. ใช้วัตถุบัฟเฟอร์ให้มากที่สุด
วิธีเพิ่มประสิทธิภาพรหัสเพื่อให้ไฟล์แหล่งข้อมูล Java และไฟล์คลาสที่รวบรวมได้เล็กลง
1 พยายามใช้การสืบทอด
2 เปิดตัวเลือกการเพิ่มประสิทธิภาพของ Java Compiler: Javac -O ตัวเลือกนี้จะลบหมายเลขบรรทัดในไฟล์คลาสและประกาศวิธีการส่วนตัวแบบส่วนตัวคงที่และขั้นสุดท้าย
3 แยกรหัสทั่วไป
4 อย่าเริ่มต้นอาร์เรย์ขนาดใหญ่ เก็บไว้ในอาร์เรย์คุณสามารถใส่ข้อมูลนี้ลงในสตริงก่อนจากนั้นแยกวิเคราะห์สตริงลงในอาร์เรย์ในระหว่างการรันไทม์
5. วัตถุประเภทวันที่จะใช้พื้นที่มาก
ประเภทยาวจากนั้นแปลงเป็นประเภทวันที่เมื่อใช้
6. พยายามใช้ชื่อสั้น ๆ สำหรับชื่อคลาสชื่อวิธีและชื่อตัวแปร
7 กำหนดตัวแปรของประเภทสุดท้ายคงที่ในอินเตอร์เฟส
8 หากการดำเนินการทางคณิตศาสตร์สามารถใช้สำหรับการเคลื่อนไหวซ้าย / ขวาอย่าใช้ * และ / การดำเนินการ
2. อย่าเริ่มต้นตัวแปรสองครั้ง
Java เริ่มต้นตัวแปรเป็นค่าที่รู้จักโดยค่าเริ่มต้นโดยเรียกตัวสร้างคลาสที่ไม่ซ้ำกัน วัตถุทั้งหมดถูกตั้งค่าเป็น null, จำนวนเต็ม (ไบต์, สั้น, int, ยาว) ถูกตั้งค่าเป็น 0, float และ double ถูกตั้งค่าเป็น 0.0 และตัวแปรบูลีนถูกตั้งค่าเป็นเท็จ สิ่งนี้มีความสำคัญอย่างยิ่งสำหรับคลาสที่ขยายจากคลาสอื่น ๆ เช่นเดียวกับชุดของตัวสร้างทั้งหมดจะถูกเรียกโดยอัตโนมัติเมื่อสร้างวัตถุโดยใช้คำหลักใหม่
3. ทำให้ชั้นเรียนสุดท้ายเป็นไปได้ทุกที่ที่ทำได้
ชั้นเรียนที่ทำเครื่องหมายสุดท้ายไม่สามารถขยายได้ มีตัวอย่างมากมายของเทคโนโลยีนี้ใน Core Java API เช่น java.lang.string การทำเครื่องหมายคลาสสตริงเป็นขั้นสุดท้ายป้องกันไม่ให้นักพัฒนาสร้างวิธีการยาวที่พวกเขาใช้
เพื่อให้ลึกลงไปมากขึ้นหากชั้นเรียนเป็นที่สิ้นสุดวิธีทั้งหมดของชั้นเรียนถือเป็นที่สิ้นสุด คอมไพเลอร์ Java อาจอินไลน์ทุกวิธี (ขึ้นอยู่กับการใช้งานของคอมไพเลอร์) ในการทดสอบของฉันฉันเห็นประสิทธิภาพเพิ่มขึ้นโดยเฉลี่ย 50%
9. ข้อยกเว้นถูกโยนลงไปในที่ที่จำเป็นต้องโยน
ลอง {Some.Method1 (); (Method2Exception E) {// จัดการข้อยกเว้น 2} ลอง {Some.method3 ();} catch (method3exception e) {// จัดการข้อยกเว้น 3} รหัสที่ดาวน์โหลดได้ง่ายกว่าที่จะปรับให้เหมาะสมโดยคอมไพเลอร์
ลอง {Some.Method1 (); catch (method3exception e) {// จัดการข้อยกเว้น 3}
10. การเพิ่มประสิทธิภาพของลูป
แทนที่…
สำหรับ (int i = 0; i <collection.size (); i ++) {
-
-
กับ…
สำหรับ (int i = 0, n = collection.size (); i <n; i ++) {
-
-
5. ในการพัฒนาระบบแอปพลิเคชัน Java + Oracle ให้ลองใช้แบบฟอร์มตัวพิมพ์ใหญ่ในคำสั่ง SQL ที่ฝังตัวใน Java เพื่อลดภาระการแยกวิเคราะห์ของ Oracle Parser
10. พยายามใช้กลยุทธ์การโหลดขี้เกียจนั่นคือเริ่มสร้างเมื่อจำเป็น
ตัวอย่างเช่น: string str =“ aaa”;
ถ้า (i == 1) {
list.add (str);
-
ควรถูกแทนที่ด้วย:
ถ้า (i == 1) {
string str =“ aaa”;
list.add (str);
-
12. อย่าใช้ในวง:
พยายาม {
} จับ() {
-
ควรวางไว้บนชั้นนอกสุด
ข้างต้นเป็นเรื่องเกี่ยวกับบทความนี้
โปรดใช้เวลาแบ่งปันบทความกับเพื่อนของคุณหรือแสดงความคิดเห็น เราจะขอบคุณอย่างจริงใจสำหรับการสนับสนุนของคุณ!