มีเหตุผลด้านประสิทธิภาพในการประกาศพารามิเตอร์เมธอดใน Java หรือไม่?


117

มีเหตุผลด้านประสิทธิภาพในการประกาศพารามิเตอร์เมธอดใน Java หรือไม่?

ใน:

public void foo(int bar) { ... }

เมื่อเทียบกับ:

public void foo(final int bar) { ... }

สมมติว่ามีการอ่านอย่างเดียวและไม่เคยแก้ไขได้ในbarfoo()


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

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

นั่นอาจจะเป็น แต่ไม่มีใครเขียนหรือแนะนำไมโครเบนช์มาร์ก ...
กีบ

1
คำตอบของ @ Mike Blandford แนะนำให้ใช้ micro-benchmark ใช่หรือไม่?
เบ็นเพจ

การเขียนมาตรฐานไมโครใน Java เป็นสิ่งที่ยุ่งยากมาก
Edmondo1984

คำตอบ:


97

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

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


5
คุณคิดว่าตัวแปรสุดท้าย / พารามิเตอร์สามารถปรับให้เหมาะสมเป็นตัวแปรลูปได้แม้ว่า ... แต่คอมไพเลอร์ / รันไทม์ที่ดีควรจะสามารถคิดออกได้โดยไม่มีขั้นสุดท้ายอยู่ดี ...
John Gardner

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

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

15

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


8
"ค่อนข้างหายากที่ข้อบกพร่องเกิดจากการกำหนดพารามิเตอร์โดยไม่คาดคิด" ธรรมดากว่าที่คุณคิด ...
RAY

2
@RAY คุณอาจจะพูดถูกจริงๆแล้วฉันไม่มีข้อมูล (นอกเหนือจากประสบการณ์ของตัวเอง) ที่จะสำรองข้อมูลการอ้างสิทธิ์
Dobes Vandermeer

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

0

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

http://www.javaperformancetuning.com/tips/final.shtml

โอ้และอีกหนึ่งแหล่งข้อมูลที่ดี

http://mindprod.com/jgloss/final.html


10
คำถามเกี่ยวกับพารามิเตอร์ที่ถูกประกาศขั้นสุดท้ายซึ่งไม่มีผลกระทบต่อประสิทธิภาพ
Robin

ในขั้นสุดท้ายของ JIT'S (Hotspot) ที่ทันสมัยไม่มีผลต่อประสิทธิภาพ (วัดผลได้) ใด ๆ เลยไม่ว่าจะใช้กับพารามิเตอร์หรือคลาส
kohlerm

2
บทความสองบทความที่คุณเชื่อมโยงทั้งสองแนะนำว่าขั้นสุดท้ายค่อนข้างเป็นเครื่องหมายแสดงความหมายสำหรับนักพัฒนาและคอมไพเลอร์ JIT อาจใช้ขั้นสุดท้าย (แต่ตามที่คนอื่น ๆ ชี้ให้เห็นพวกเขาไม่ต้องการข้อมูลนั้นจริงๆ) ขั้นสุดท้ายจึงค่อนข้างเป็นความหมายซึ่งควบคู่ไปกับความสามารถของคอมไพเลอร์ C / ++ สมัยใหม่ในการอนุมานความเป็นไปได้ของตัวแปรและวิธีการแม้ว่าจะไม่ได้ทำเครื่องหมาย const ไว้อย่างชัดเจนก็ตาม
ron

0

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


-2

ฉันคิดว่าคอมไพเลอร์สามารถลบตัวแปรสุดท้ายแบบคงที่ส่วนตัวทั้งหมดที่มีประเภทดั้งเดิมเช่น int และอินไลน์โดยตรงในโค้ดเช่นเดียวกับมาโคร C ++

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


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