เราควรหลีกเลี่ยงการสร้างวัตถุใน Java?


243

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

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


39
"สร้างวัตถุ Java เป็นงานราคาแพงที่สุดที่คุณสามารถดำเนินการ" ต้องการแบ่งปันแหล่งที่มาของการอ้างสิทธิ์นั้นหรือไม่
Songo

92
และ - การดำเนินการที่แพงที่สุดเมื่อเทียบกับอะไร เปรียบเทียบกับการคำนวณ pi ถึง 900 หลักหรือเปรียบเทียบกับการเพิ่ม int?
jasonk

4
พวกเขากำลังพูดถึงส่วนหนึ่งของการสร้างวัตถุนั้นหรือไม่? ฉันคิดว่า Apple ใช้คิวสำหรับ tableViewCells อย่างไร บางทีเพื่อนร่วมงานของคุณแนะนำให้สร้างวัตถุสองสามชิ้นและนำมาใช้ใหม่เนื่องจากมีค่าใช้จ่ายที่เกี่ยวข้องกับวัตถุเฉพาะเหล่านั้นหรือไม่ แค่พยายามคิดให้ออกว่าทำไมพวกเขาถึงอ้างสิทธิ์เช่นนั้น
Tyler DeWitt

3
นี่คือหนึ่งในสิ่งที่ตลกที่สุดที่ฉันเคยได้ยินเกี่ยวกับการเขียนโปรแกรม)
Mert Akcakaya

22
เลขคณิตค่อนข้างแพงเช่นกัน เราควรหลีกเลี่ยงการคำนวณโอ้และการเริ่มต้น JVM มีราคาแพงมากดังนั้นเราจึงไม่ควรเริ่มต้น JVMs :-)
James Anderson

คำตอบ:


478

เพื่อนร่วมงานของคุณไม่มีความคิดในสิ่งที่พวกเขากำลังพูดถึง

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

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

ทุกอย่างเป็นวัตถุ (ยกเว้นprimitives)

ทุกอย่างที่ไม่ใช่แบบดั้งเดิม ( int, long, doubleฯลฯ ) เป็นวัตถุใน Java ไม่มีวิธีหลีกเลี่ยงการสร้าง Object ใน Java

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

เร็วเท่าช่วงปลายทศวรรษที่ 1990 การใช้งาน JVM ในช่วงต้นทศวรรษ 1990 มีค่าใช้จ่ายด้านประสิทธิภาพในการจัดสรรวัตถุจริง สิ่งนี้ไม่ได้เกิดขึ้นตั้งแต่อย่างน้อยปี 2005

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

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

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

กอง JVM ไม่เติบโตและหดตัวเพื่อให้ส่วนที่เหลือของระบบที่ได้รับผลกระทบในแง่บวกโดยหน่วยความจำฟรีใน JVM กอง -Xmsจัดสรรทั้งหมดของสิ่งที่ระบุเมื่อเริ่มต้นและการแก้ปัญหาคือไม่ปล่อยหน่วยความจำนั้นกลับไปยังระบบปฏิบัติการเพื่อแบ่งปันกับกระบวนการ OS อื่นใด ๆ จนกว่าอินสแตนซ์ของ JVM จะหยุดทำงานอย่างสมบูรณ์ -Xms=1GB -Xmx=1GBจัดสรร RAM 1GB โดยไม่คำนึงถึงจำนวนวัตถุที่ถูกสร้างขึ้นตามเวลาที่กำหนด มีการตั้งค่าบางอย่างที่อนุญาตให้ปล่อยเปอร์เซ็นต์ของหน่วยความจำฮีป แต่สำหรับวัตถุประสงค์เชิงปฏิบัติทั้งหมด JVM ไม่สามารถปล่อยหน่วยความจำนี้ได้เพียงพอสำหรับสิ่งนี้ที่เคยเกิดขึ้นดังนั้นจึงไม่มีกระบวนการอื่นใดที่สามารถเรียกคืนหน่วยความจำนี้ได้ดังนั้นส่วนที่เหลือของระบบจะไม่ได้รับประโยชน์จาก JVM Heap ที่ว่างเช่นกัน RFE สำหรับสิ่งนี้คือ"ยอมรับ" 29-NOV-2006 แต่ไม่มีอะไรทำเกี่ยวกับมันเลย พฤติกรรมนี้ไม่ถือว่าเป็นเรื่องที่ผู้มีอำนาจเป็นกังวล

มีความเข้าใจผิดว่าการสร้างวัตถุขนาดเล็กจำนวนมากทำให้ JVM หยุดชั่วคราวเป็นเวลานานนี่เป็นเท็จเช่นกัน

อัลกอริทึม GC ปัจจุบันถูกปรับให้เหมาะสมสำหรับการสร้างวัตถุขนาดเล็กจำนวนมากที่มีอายุสั้นซึ่งโดยทั่วไปแล้วจะเป็น 99% ของการแก้ปัญหาสำหรับวัตถุ Java ในทุกโปรแกรม ความพยายามที่Object Poolingจะทำให้ JVM ทำงานได้แย่ลงในกรณีส่วนใหญ่

Objects เดียวที่ต้องรวมกำไรในวันนี้คือ Object ที่อ้างถึงทรัพยากรที่ จำกัด ที่อยู่ภายนอก JVM Sockets, ไฟล์, การเชื่อมต่อฐานข้อมูล ฯลฯ และสามารถนำกลับมาใช้ใหม่ได้ วัตถุปกติไม่สามารถรวมรวมกันได้ในลักษณะเดียวกับในภาษาที่อนุญาตให้คุณเข้าถึงตำแหน่งหน่วยความจำโดยตรง การแคชวัตถุเป็นแนวคิดที่แตกต่างกันและอาจหรืออาจไม่ใช่สิ่งที่บางคนเรียกอย่างไร้เดียงสาว่าการรวมกำไรแนวคิดทั้งสองนั้นไม่เหมือนกันและไม่ควรมีการรวมกัน

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

ภาษาไดนามิกเชิงวัตถุกำลังตี C ถึงตอนนี้ในการทดสอบที่ละเอียดอ่อน


274
+1: "การดำเนินการที่แพงที่สุดของคุณจะฟังพวกเขา ... " ดีที่สุดที่ฉันเคยได้ยินบางครั้ง
rjnilsson

21
@DeadMG ถึงแม้จะมีโอเวอร์เฮด GC ที่สะสมอยู่ แต่ Java ก็สามารถเร็วกว่า C ++ ได้ (เช่นเนื่องจากการบีบอัดฮีปทำให้การลดแคชที่ไม่ได้รับสำหรับโครงสร้างข้อมูลบางอย่าง)
SK-logic

13
@ SK-logic: เนื่องจาก GC ไม่สามารถกำหนดค่าได้จึงเป็นเรื่องยากที่สุดในการพิสูจน์ สำหรับการลดการพลาดแคชให้น้อยที่สุดก็ยากที่จะทำเช่นนั้นเมื่อทุกวัตถุต้องเป็นทางอ้อมทำให้สูญเสียพื้นที่แคชและเพิ่มเวลาในการประมวลผล อย่างไรก็ตามฉันขอยืนยันว่าเพียงใช้ตัวจัดสรรที่เหมาะสมใน C ++ เช่นออบเจ็กต์หรือเวทีหน่วยความจำคุณสามารถจับคู่หรือเอาชนะประสิทธิภาพของตัวรวบรวมขยะได้อย่างง่ายดาย ตัวอย่างเช่นคุณสามารถเขียนคลาส arena ของหน่วยความจำที่จะทำงานได้เร็วกว่า_allocaตัดจำหน่าย
DeadMG

33
การสร้างวัตถุมีราคาถูกกว่าที่เคยเป็นมา มันไม่ฟรีแม้ว่า ใครก็ตามที่บอกคุณว่ากำลังโกหก และลิงก์เกี่ยวกับภาษา OO ที่เต้น C คือคำตอบที่เกินจริงสำหรับคนที่พยายามเรียนรู้อย่างแท้จริง
jasonk

17
เป็นเพราะคำตอบประเภทนี้ที่เราท้ายด้วยรหัสเส็งเคร็ง คำตอบที่ถูกต้องคือการสร้างวัตถุใน Java ทั้งการสร้างวัตถุ Java และเริ่มต้นได้ ส่วนแรกราคาถูกส่วนที่สองอาจมีราคาแพงมาก ผู้คนควรดูว่าเกิดอะไรขึ้นกับคอนสตรัคเตอร์ก่อนที่จะใช้newคำสำคัญในฮอตสปอต ฉันเคยเห็นคนใช้new ImageIcon(Image)ในpaint()วิธีการของวัตถุสวิงซึ่งค่อนข้างแพงและทำให้ UI ทั้งหมดซบเซา ดังนั้นจึงไม่ใช่คำตอบขาวดำคิดก่อนใช้newที่ไหนสักแห่ง
qwertzguy

94

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

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

ก่อนที่ทุกคนจะพูดถึงเรื่องนี้เป็นกรณีขอบ - ฉันมีแอพพลิเคชั่นที่สร้างโปรไฟล์ของวัตถุ 20 + MB เพื่อประมวลผลข้อมูล ~ 50 แถว นี่เป็นเรื่องปกติในการทดสอบจนกว่าคุณจะเพิ่มขึ้นเป็นร้อยคำขอต่อนาทีและทันใดนั้นคุณกำลังสร้าง 2GB ของข้อมูลต่อนาที หากคุณต้องการทำ 20 reqs / วินาทีคุณกำลังสร้างวัตถุ 400MB แล้วทิ้งมันไป 20 reqs / วินาทีนั้นเล็กมากสำหรับเซิร์ฟเวอร์ที่ดี


7
ฉันอาจเพิ่มตัวอย่าง: ในบางกรณีจริงๆแล้วมันไม่ได้สร้างความแตกต่างในแง่ของความชัดเจนของโค้ด แต่สามารถสร้างความแตกต่างอย่างมากในการทำงาน: เมื่ออ่านจากสตรีมมันไม่ใช่เรื่องแปลกที่จะใช้สิ่งwhile(something) { byte[] buffer = new byte[10240]; ... readIntoBuffer(buffer); ...ที่อาจ byte[] buffer = new byte[10240]; while(something) { ... readIntoBuffer(buffer); ...จะสิ้นเปลืองเมื่อเทียบกับเช่น
JimmyB

4
+1: การสร้างวัตถุที่ไม่จำเป็น (หรือค่อนข้างล้างออกหลังจากลบ) บางครั้งอาจมีค่าใช้จ่ายสูง รหัส 3D Graphics / OpenGL ใน java เป็นที่เดียวที่ฉันได้เห็นการปรับให้เหมาะสมเพื่อลดจำนวนของวัตถุที่สร้างขึ้นเนื่องจาก GC สามารถสร้างความหายนะกับกรอบของคุณได้
Leo

1
ว้าว! 20+ MB เพื่อประมวลผลข้อมูล 50 แถว? ฟังดูบ้า ไม่ว่าในกรณีใดวัตถุเหล่านั้นมีอายุยืนยาวหรือไม่? เพราะเป็นกรณีที่สำคัญสำหรับ GC หากในอีกทางหนึ่งคุณเพียงแค่พูดคุยเกี่ยวกับข้อกำหนดหน่วยความจำนั่นไม่เกี่ยวกับการรวบรวมขยะหรือประสิทธิภาพในการสร้างวัตถุ ...
Andres F.

1
วัตถุมีอายุสั้น (น้อยกว่า 0.5 วินาทีในกรณีทั่วไป) ปริมาณขยะนั้นยังคงส่งผลกระทบต่อประสิทธิภาพการทำงาน
jasonk

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

60

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

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


7
+1 แม้ว่าตัวรวบรวมขยะ "เพียงแค่ใช้งานได้" แต่โปรแกรมเมอร์ Java ทุกคนควรเรียนรู้เกี่ยวกับตัวรวบรวมขยะทั่วไป
benzado

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

4
นั้นขั้นตอนต่อไปสำหรับการวิเคราะห์การหลบหนีคือการ "จัดสรร" ความทรงจำสำหรับวัตถุขนาดเล็กอย่างหมดจดในทะเบียน (เช่นPointวัตถุได้พอดีใน 2 ลงทะเบียนวัตถุประสงค์ทั่วไป)
โจอาคิมซาวเออร์

6
@Joachim Sauer: นั่นเป็นสิ่งที่ทำในการติดตั้ง HotSpot VM ที่ใหม่กว่า มันเรียกว่าการแทนที่สเกลาร์
someguy

1
@someguy: ฉันเคยอ่านเกี่ยวกับเรื่องนี้มานานแล้วเป็นสิ่งต่อไป แต่ไม่ได้ติดตามเพื่อตรวจสอบว่ามันได้ทำไปแล้ว มันเป็นข่าวที่ยอดเยี่ยมที่ได้ยินว่าเรามีสิ่งนี้อยู่แล้ว
โจอาคิมซาวเออร์

38

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

มีคู่ของสถานการณ์ที่พิเศษมากที่เป็นเป็นความคิดที่ดีเพื่อหลีกเลี่ยงการสร้างวัตถุ

  • เมื่อคุณเขียนแอปพลิเคชันที่มีความไวต่อความล่าช้าและต้องการหลีกเลี่ยงการหยุด GC ชั่วคราว ยิ่งคุณสร้างวัตถุมากเท่าไหร่ก็จะยิ่งเกิด GC ขึ้นและโอกาสที่จะหยุดก็จะยิ่งมากขึ้นเท่านั้น นี่อาจเป็นการพิจารณาที่ถูกต้องสำหรับเกมที่เกี่ยวข้องแอปพลิเคชั่นสื่อบางอย่างการควบคุมหุ่นยนต์การซื้อขายความถี่สูงเป็นต้นวิธีการแก้ปัญหาคือการจัดสรรวัตถุ / อาร์เรย์ทั้งหมดที่คุณต้องการล่วงหน้าและนำกลับมาใช้ใหม่ มีห้องสมุดที่มีความเชี่ยวชาญในการให้บริการทุกชนิดของความสามารถนี้เช่นมีJavolution แต่เนื้อหาถ้าคุณสนใจ latency ต่ำคุณควรใช้ C / C ++ / Assembler แทน Java หรือ C # :-)
  • การหลีกเลี่ยงการใช้กล่องแบบดั้งเดิม (Double, Integer และอื่น ๆ ) อาจเป็นประโยชน์อย่างมากในการเพิ่มประสิทธิภาพของไมโครในบางสถานการณ์ เนื่องจาก primitives ที่ไม่มีกล่อง (double, int และอื่น ๆ ) หลีกเลี่ยงค่าใช้จ่ายสำหรับแต่ละออบเจ็กต์พวกเขาจึงทำงานได้เร็วกว่า CPU มากเช่นการประมวลผลเชิงตัวเลขเป็นต้นโดยทั่วไปแล้วอาร์เรย์ดั้งเดิมทำงานได้ดีมากใน Java ดังนั้นคุณจึงต้องการใช้ วัตถุประเภทอื่น ๆ
  • ในสถานการณ์หน่วยความจำที่ จำกัดคุณต้องการลดจำนวนวัตถุ (ใช้งาน) ที่สร้างขึ้นเนื่องจากแต่ละวัตถุมีค่าใช้จ่ายเล็กน้อย (โดยทั่วไป 8-16 ไบต์ขึ้นอยู่กับการนำ JVM ไปใช้) ในกรณีเช่นนี้คุณควรเลือกวัตถุหรืออาร์เรย์ขนาดใหญ่จำนวนเล็กน้อยเพื่อจัดเก็บข้อมูลของคุณแทนที่จะเป็นวัตถุขนาดเล็กจำนวนมาก

3
น่าสังเกตว่าการวิเคราะห์แบบ escape จะอนุญาตให้วัตถุที่มีอายุสั้น (ขอบเขตชีวิต) ถูกเก็บไว้ในสแต็กวัตถุเหล่านี้สามารถถูกจัดสรรคืนได้ฟรีibm.com/developerworks/java/library/j-jtp09275/index.html
Richard Tingle

1
@ ริชาร์ด: จุดที่ดี - การวิเคราะห์การหลบหนีให้การเพิ่มประสิทธิภาพที่ดีมาก คุณต้องระมัดระวังเกี่ยวกับการใช้มันแม้ว่าจะไม่รับประกันว่าจะเกิดขึ้นในการใช้งานจาวาทั้งหมดและในทุกสถานการณ์ ดังนั้นคุณมักจะต้องมีมาตรฐานเพื่อให้แน่ใจว่า
mikera

2
นอกจากนี้การวิเคราะห์การหลบหนีที่ถูกต้อง 100% นั้นเทียบเท่ากับปัญหาการหยุดทำงาน อย่าพึ่งพาการวิเคราะห์การหลบหนีในสถานการณ์ที่ซับซ้อนเนื่องจากมีแนวโน้มที่จะให้คำตอบที่ผิดอย่างน้อยในบางครั้ง
จูลส์

จุดแรกและจุดสุดท้ายไม่ได้นำไปใช้กับวัตถุขนาดเล็กที่ปล่อยออกมาอย่างรวดเร็วพวกเขาตายใน eden (คิดว่าการจัดสรรสแต็กใน C ฟรีมาก) และไม่ส่งผลกระทบต่อเวลา GC หรือการจัดสรรหน่วยความจำ การจัดสรรวัตถุส่วนใหญ่ใน Java ตกอยู่ในหมวดหมู่นี้จึงเป็นหลักฟรี จุดที่สองยังคงใช้ได้
Bill K

17

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

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

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

เมื่อไรที่เรื่องนี้จะเกิดขึ้น? เมื่อใดก็ตามที่คุณสนใจอัตราการตอบกลับในระดับมิลลิวินาทีที่สอดคล้องกันคุณจะสนใจ GC ระบบการซื้อขายอัตโนมัติที่เขียนด้วยภาษาจาวาจะปรับ JVM อย่างหนักเพื่อลดการหยุดชั่วคราว บริษัท ที่จะเขียน Java จะเปลี่ยนเป็น C ++ ในสถานการณ์ที่ระบบต้องตอบสนองสูงตลอดเวลา

สำหรับบันทึกฉันไม่ให้อภัยการหลีกเลี่ยงวัตถุโดยทั่วไป! เริ่มต้นการเขียนโปรแกรมเชิงวัตถุ ปรับวิธีการนี้เฉพาะเมื่อ GC เข้ามาขวางทางแล้วหลังจากพยายามปรับ JVM ให้หยุดชั่วคราวเป็นเวลาน้อยลง หนังสือที่ดีเกี่ยวกับการปรับแต่งประสิทธิภาพ Java คือJava Performanceโดย Charlie Hunt และ Binu John


10
JVM ที่ทันสมัยที่สุดสนับสนุนอัลกอริทึมการรวบรวมขยะที่ดีกว่า "หยุดโลก" เวลาที่ตัดจำหน่ายที่ใช้ในการรวบรวมขยะมักจะน้อยกว่าเวลาที่ใช้ในการโทรหา malloc / ฟรีอย่างชัดเจน การจัดการหน่วยความจำ C ++ ยังทำงานในเธรดแยกกันด้วยหรือไม่

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

2
@ ThorbjørnRavnAndersen: จริงเหรอ? คุณหมายถึงGC หยุดชั่วคราวน้อยลงหรือคุณหมายถึง GC ปกติหรือไม่ ฉันไม่เข้าใจวิธีการที่ประชาคมโลกไม่สามารถหยุดโปรแกรมและยังย้ายวัตถุรอบในเวลาเดียวกัน ... ดูเหมือนว่าค่อนข้างอักษรเป็นไปไม่ได้ฉัน ...
Mehrdad

2
@ ThorbjørnRavnAndersen: จะ "หยุดโลก" แต่จะไม่หยุด "JVM" ได้อย่างไร? ที่ทำให้รู้สึกไม่ ...
Mehrdad

2
@ ThorbjørnRavnAndersen: ไม่ฉันทำไม่ได้จริงๆ ฉันแค่ไม่เข้าใจสิ่งที่คุณพูด บางครั้ง GC อาจหยุดโปรแกรมชั่วคราวซึ่งในกรณีนี้คือ - ตามคำนิยาม - ไม่ใช่ " หยุดชั่วคราว" หรือไม่เคยหยุดโปรแกรมชั่วคราว (ดังนั้นจึงเป็น "หยุดชั่วคราว") ซึ่งในกรณีนี้ฉันไม่เข้าใจว่า ตรงกับคำสั่ง "ของคุณที่จะหยุดโลกเมื่อไม่สามารถติดตามได้" เนื่องจากนั่นดูเหมือนจะบ่งบอกว่าโปรแกรมหยุดชั่วคราวในขณะที่ GC กำลังทำงานอยู่ คุณจะอธิบายให้ฟังว่าเป็นกรณีใด (หยุดชั่วคราวหรือไม่?) และเป็นไปได้อย่างไร
Mehrdad

11

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

นอกจากนั้นคำตอบข้างต้นยังคงเป็นจริง


2
อ่านคำถามอีกครั้ง มันไม่ได้ระบุ JVM ที่ใดก็ได้รวมถึงแท็ก มันพูดถึง Java เท่านั้น
Peter Kelly

9

GC ถูกปรับสำหรับวัตถุระยะสั้นจำนวนมาก

ที่กล่าวว่าหากคุณสามารถลดการจัดสรรวัตถุได้เล็กน้อยคุณควร

ตัวอย่างหนึ่งคือการสร้างสตริงในลูปวิธีที่ไร้เดียงสาจะเป็น

String str = "";
while(someCondition){
    //...
    str+= appendingString;
}

ซึ่งสร้างStringวัตถุใหม่ใน+=การดำเนินการแต่ละครั้ง(รวมทั้ง a StringBuilderและอาร์เรย์ถ่านใหม่)

คุณสามารถเขียนสิ่งนี้ลงใน:

StringBuilder strB = new StringBuilder();
while(someCondition){
    //...
    strB.append(appendingString);
}
String str = strB.toString();

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

แต่นอกเหนือไปจากนั้นคุณควรดึง profiler ขึ้นมาเพื่อค้นหาคอขวดจริงแทนที่จะไล่ผี


ประโยชน์ที่ใหญ่ที่สุดในนี้StringBuilderวิธีการคือก่อนขนาดStringBuilderเพื่อให้มันไม่เคยมีการจัดสรรอาร์เรย์ที่อ้างอิงกับStringBuilder(int)คอนสตรัค สิ่งนี้ทำให้เป็นการจัดสรรครั้งเดียวแทนที่จะเป็นการ1+Nจัดสรร

2
@JarrodRoberson StringBuilder จะเพิ่มความจุอย่างน้อยสองเท่าหรือในคำอื่น ๆ ความจุจะเพิ่มขึ้นอย่างทวีคูณสำหรับการจัดสรร log (n) เท่านั้น
ratchet freak

6

Joshua Bloch (หนึ่งในผู้สร้างแพลตฟอร์ม Java) เขียนไว้ในหนังสือของเขาEffective Javaในปี 2001:

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


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

2
... เร็วกว่าการอ้างอิงถึงสองสตริงที่แตกต่างกัน แต่เหมือนกันของความยาวนั้น
supercat

5

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

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


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

3

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

เท่าที่ข้อกำหนดเกี่ยวกับหน่วยความจำ JVM เกี่ยวข้องรอ Java 8 คุณไม่จำเป็นต้องระบุ -Xmx การตั้งค่าพื้นที่ meta จะดูแลความต้องการหน่วยความจำ JVM และมันจะเติบโตโดยอัตโนมัติ


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

1
การแลกเปลี่ยนสแต็คควรมีกลไกเพื่อแจ้งให้ผู้ใช้ที่ลงคะแนนในคำตอบใด ๆ
AKS

1

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

ดังนั้นให้พิจารณาสิ่งที่ตัวสร้างคลาสทำก่อนที่จะหาว่ามันว่างหรือไม่


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

2
หากค่าใช้จ่ายเพิ่มเติมถูกย้ายไปที่ 'if (firstTime)' การสร้างคลาสในลูปจะยังคงมีราคาแพงกว่าการใช้คลาสซ้ำ
อเล็กซ์

ฉันกำลังจะโพสต์คำตอบที่คล้ายกันและฉันเชื่อว่านี่เป็นคำตอบที่ถูกต้อง ผู้คนจำนวนมากตาบอดด้วยคำพูดเหล่านั้นว่าการสร้างวัตถุ Java มีราคาถูกที่พวกเขาไม่ได้ตระหนักว่าบ่อยครั้งที่ตัวสร้างหรือการเริ่มต้นเพิ่มเติมอาจอยู่ไกลจากราคาถูก ตัวอย่างเช่นคลาส ImageIcon ใน Swing แม้ว่าคุณจะผ่านออบเจ็กต์อิมเมจที่โหลดไว้ล่วงหน้าคอนสตรัคเตอร์นั้นค่อนข้างแพง และฉันไม่เห็นด้วยกับ @GordonM มีหลายคลาสจาก JDK ที่ทำหน้าที่ init ส่วนใหญ่ในคอนสตรัคเตอร์และฉันคิดว่ามันทำให้ code leaner ได้รับการออกแบบที่ดีขึ้น
qwertzguy

1

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

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

หนึ่งในสิ่งที่สะดุดตาที่สุดที่ฉันเคยเห็นที่พัฒนาใน Java ซึ่งทำให้ฉันคิดว่ามันเป็นนักสู้รุ่นหนาในสาขาของฉัน (VFX) เป็นตัวติดตามเส้นทางแบบหลายเธรดแบบมาตรฐาน (ไม่ใช้การแคช irradiance หรือ BDPT หรือ MLS หรืออื่น ๆ ) ซีพียูที่ให้ภาพตัวอย่างแบบเรียลไทม์ที่แปรสภาพอย่างรวดเร็วเป็นภาพที่ปราศจากจุดรบกวน ฉันได้ทำงานกับมืออาชีพใน C ++ อุทิศอาชีพให้กับสิ่งเหล่านี้ด้วยมืออาชีพที่มีปัญหาในการทำเช่นนั้น

แต่ฉันมองไปรอบ ๆ ที่ซอร์สโค้ดและในขณะที่มันใช้วัตถุจำนวนมากในราคาเล็กน้อยส่วนที่สำคัญที่สุดของ tracer path (BVH และ triangles และวัสดุ) อย่างชัดเจนและจงใจหลีกเลี่ยงวัตถุในอาร์เรย์ใหญ่ประเภทดั้งเดิม ( ส่วนใหญ่float[]และint[]) ซึ่งทำให้ใช้หน่วยความจำน้อยลงและรับประกันตำแหน่งเชิงพื้นที่ที่จะได้รับจากหนึ่งfloatในอาร์เรย์ไปยังถัดไป ฉันไม่คิดว่ามันจะเป็นการเก็งกำไรเกินกว่าที่จะคิดว่าถ้าผู้เขียนใช้กล่องชนิดที่ชอบFloatที่นั่นมันจะมีค่าใช้จ่ายค่อนข้างสูงต่อประสิทธิภาพของมัน แต่เรากำลังพูดถึงส่วนที่สำคัญที่สุดของเอ็นจิ้นนั้นและฉันค่อนข้างมั่นใจว่านักพัฒนาเพิ่มประสิทธิภาพอย่างชำนาญเขาได้วัดและใช้การเพิ่มประสิทธิภาพนั้นอย่างรอบคอบมากเพราะเขาใช้วัตถุอย่างมีความสุขทุกที่ด้วย ค่าใช้จ่ายเล็กน้อยเพื่อติดตามเส้นทางเรียลไทม์ที่น่าประทับใจของเขา

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

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


1
ย่อหน้าแรกของคุณอยู่ในเส้นทางที่ถูกต้อง ช่องว่างของ eden และ young นั้นใช้ copy collectors ที่มีขนาดประมาณ 0 ค่าใช้จ่ายสำหรับวัตถุที่ตายแล้ว ฉันขอแนะนำงานนำเสนอนี้ ในหมายเหตุข้างคุณรู้ว่าคำถามนี้มาจากปี 2012 ใช่ไหม?
JimmyJames

@JimmyJames ฉันเบื่อและชอบที่จะกลั่นกรองคำถามรวมถึงคำถามเก่า ๆ ฉันหวังว่าผู้คนจะไม่สนใจเรื่องเวทมนตร์ของฉัน! :-D
Dragon Energy

@JimmyJames มันไม่ใช่กรณีที่ชนิดของกล่องที่มีข้อกำหนดหน่วยความจำเพิ่มเติมและไม่รับประกันว่าจะต่อเนื่องกันในอาร์เรย์? ฉันมักจะคิดว่าวัตถุมีราคาถูกใน Java แต่กรณีหนึ่งที่พวกเขาอาจมีราคาค่อนข้างแพงfloat[]เทียบกับFloat[]ที่ซึ่งการประมวลผลตามลำดับล้านครั้งในอดีตอาจค่อนข้างเร็วกว่าครั้งที่สอง
Dragon Energy

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

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

0

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

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

นี่คือการนำเสนอที่ยอดเยี่ยมในหัวข้อ: https://www.cs.virginia.edu/kim/publicity/pldi09tutorials/memory-efficient-java-tutorial.pdf


0

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


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