ไปได้เร็วแค่ไหน?


39

Go เป็นหนึ่งในไม่กี่ภาษาที่ควรจะเรียกใช้ 'ใกล้กับโลหะ' นั่นคือมันถูกรวบรวมพิมพ์แบบคงที่และเรียกใช้งานโค้ดโดยไม่ต้องใช้ VM สิ่งนี้ควรให้ความได้เปรียบด้านความเร็วเหนือ Java, C # และอื่น ๆ อย่างไรก็ตามดูเหมือนว่าอยู่หลัง Java (ดูProgramming Language Shootout )

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


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

1
ฉันเข้าใจว่า แต่ฉันสงสัยว่ามันสมเหตุสมผลที่จะคาดหวังว่าความเร็วของ Go ในการจับคู่ / แซงเช่น Java เมื่อคอมไพเลอร์เติบโตเต็มที่
เกร็ก Slodkowicz

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

8
ปลุกฉันก่อนที่คุณจะไป ... อะไรนะ! . ขออภัยฉันอดไม่ได้ มาที่นี่ธง .. มาที่นี่..
ทิมโพสต์

2
@delnan - หรือเป็นเรื่องง่ายกว่าที่จะพูดว่า "Java" มากกว่าที่จะพูดว่า "Java (TM) SE Runtime Environment (build 1.6.0_25-b06) Java HotSpot (TM) เซิร์ฟเวอร์ 64-Bit VM (สร้าง 20.0-b11) โหมดผสม) ":-)
igouy

คำตอบ:


46

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

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

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

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

สำหรับส่วนที่เหลือของเกณฑ์มาตรฐาน Java และ Go นั้นเป็นแบบคอในคอโดยที่ Go จะใช้หน่วยความจำน้อยลงอย่างมากและในกรณีส่วนใหญ่โค้ดก็จะน้อยลง ดังนั้นแม้ว่า Go จะช้ากว่า Java ในการทดสอบจำนวนหนึ่ง แต่ Java นั้นค่อนข้างเร็ว แต่ Go ก็ทำได้ค่อนข้างดีเมื่อเปรียบเทียบกันและ Go ก็อาจจะเร็วขึ้นอย่างเห็นได้ชัดในอนาคตอันใกล้

ฉันรอคอยเมื่อ gccgo (คอมไพเลอร์ Go ที่ใช้ codegen gcc) เป็นผู้ใหญ่ ที่ควรทำให้ Go ค่อนข้างสอดคล้องกับ C สำหรับโค้ดหลายประเภทซึ่งน่าสนใจ


2
ทำได้ดีสำหรับการทำความเข้าใจว่าจำเป็นต้องดูซอร์สโค้ดและตรวจสอบสิ่งที่กำลังทำอยู่เสมอ!
igouy

1
สำหรับเวลาเริ่มต้นของ Java สำหรับโปรแกรมเหล่านั้นโปรดดู shootout.alioth.debian.org/help.php#java
igouy

2
นั่นคือว่าชนิดของคำตอบผมก็หวังว่าสำหรับขอบคุณ!
เกร็ก Slodkowicz

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

22
  1. โดยไม่ต้องบอกว่าปัญหาใดได้รับการแก้ไขมาตรฐานทั้งหมดไม่มีจุดหมาย
  2. JVM และ CLR ทั้งสองใช้ JIT เพื่อสร้างรหัสเครื่อง ไม่มีเหตุผลที่สิ่งนี้ควรช้าลง เป็นเพียงค่าใช้จ่ายในการบูต
  3. ไปถูกออกแบบมาเพื่อสร้างอย่างรวดเร็ว คุณไม่มีเวลาในการคอมไพล์และการเพิ่มประสิทธิภาพเวลาบูตมากมาย รวบรวมคอมไพล์ไลบรารีมาตรฐานของตัวเองตามเวลาที่แอพ Java บูต

จะไปได้เร็วขึ้นที่รันไทม์? ใช่. จะไปเร็วกว่าเดิมที่รันไทม์หรือไม่ ฉันไม่รู้ บางทีผู้สร้างคอมไพเลอร์จะเพิ่มการเพิ่มประสิทธิภาพที่ไม่จำเป็นในราคาของเวลารวบรวม แต่ฉันไม่คิดว่าพวกเขาจะสนใจเรื่องนั้นมากนัก พวกเขาทำงานที่ Google
สิ่งที่พวกเขาต้องการคือภาษาที่ช่วยให้การพัฒนารวดเร็วและมีประสิทธิภาพในสิ่งที่พวกเขาทำ นรกแม้ว่ามาตรฐานนั้นน่าเชื่อถือ แต่ก็หมายความว่าพวกมันมีความเร็วเพียงครึ่งเดียวของ C และเร็วกว่า Python ถึง 14 เท่า นี่เป็นสิ่งที่ดีเกินพอ
ฮาร์ดแวร์ราคาถูกรหัสมีราคาแพง รหัสมีแนวโน้มที่จะใหญ่ขึ้นและช้าลงเมื่อคุณลงทุนเงินฮาร์ดแวร์จะถูกลงและเล็กลง คุณต้องการภาษาที่ไม่ต้องมี 4 เฟรมเวิร์คและคลาส 2,000 เพื่อให้ได้สิ่งที่มีประโยชน์
ไม่มีอะไรที่มีอยู่ในการออกแบบของ Go ซึ่งทำให้มันช้า อย่างไรก็ตามมีบางสิ่งบางอย่างในตัวออกแบบของ Go ซึ่งทำให้ช้ากว่าชุดประกอบ: สามัญสำนึก


1
JIT ส่วนใหญ่ (ทั้งหมด?) จะคอมไพล์ระหว่างรันไทม์ไม่ใช่เมื่อโหลดโค้ดครั้งแรก รหัสเครื่องนี้อาจไม่ถูกสร้างขึ้นสำหรับบางรหัสและยังสามารถทำให้ใช้งานไม่ได้ง่ายเช่นหากobjsในfor (obj : objs) { obj.meth() }มีการใช้งานที่แตกต่างกันmethทุกครั้งและ JIT พยายามอินไลน์ แน่นอนว่าทั้งหมดนี้เป็นประโยชน์ในกรณีทั่วไป แต่ก็ยังเป็นที่น่าสังเกต

@delnan: V8 JITs โค้ดใด ๆ ก่อนดำเนินการ นอกจากนี้ LLVM ยังถูกสร้างขึ้นโดยคำนึงถึง JIT ดังนั้น (ด้วยความพยายามบางอย่าง) คุณสามารถเพิ่มประสิทธิภาพได้ทันเวลาซึ่งอาจเกิดขึ้นได้ในเวลารวบรวม อย่างไรก็ตามการปรับให้เหมาะสมบางอย่างเช่นการวิเคราะห์การหลบหนีใช้งานได้จริงกับ JIT เท่านั้น
back2dos

3
>> โดยไม่ต้องบอกว่าปัญหาใดได้รับการแก้ไข << ดูแล้วคุณจะพบว่าหน้าเว็บเหล่านั้นพูดได้ว่าปัญหาใดได้รับการแก้ไข ในความเป็นจริงคุณจะพบซอร์สโค้ดโปรแกรม, สร้างคำสั่ง, รันคำสั่ง, เวอร์ชันการใช้ภาษา, ya da ya da ya
igouy

10

ฉันยังสังเกตเห็นว่า Go นั้นช้ามากโดยเฉพาะในเกณฑ์มาตรฐานregex-dna รัสค็อกซ์อธิบายว่าทำไมโกจึงไม่ใช่นักแสดงในมาตรฐานนี้ เหตุผลก็คือแพคเกจ regexp ของ Go นั้นใช้อัลกอริทึมการจับคู่ที่แตกต่างกันซึ่งทำงานได้ไม่ดีในการวัดประสิทธิภาพนี้ แต่อาจจะเร็วกว่าในการวัดประสิทธิภาพอื่น ๆ นอกจากนี้ยัง Ruby, Python และภาษาสคริปต์อื่น ๆ จะใช้การดำเนินงานของ C วิธีการจับคู่

ในที่สุดเกมเกณฑ์มาตรฐานภาษาคอมพิวเตอร์ประกอบด้วยมาตรฐานขนาดเล็กที่อาจไม่สะท้อนลักษณะเฉพาะของภาษาที่วัดได้อย่างแม่นยำและแม้กระทั่งเป็นสื่อกลางในการแสดงผลที่ไม่ถูกต้อง นี้งานวิจัยที่ตีพิมพ์เมื่อเร็ว ๆ นี้โดย Googleให้ภาพรวมที่ถูกต้องมากขึ้นในลักษณะภาษาหลายไป Scala, Java และ C ++ - โดยเฉพาะอย่างยิ่ง "โวลต์การวิเคราะห์ผลการดำเนินงาน" ส่วนหนึ่ง ดังนั้นในที่สุด Go ก็เกือบจะหิวความจำเหมือนกับ Java (81% ของหน่วยความจำของ Java) และใช้หน่วยความจำได้มากถึง 170% เท่ากับ Scala (ไม่สามารถหาได้ในกระดาษ

แต่อีกครั้ง Go ยังเด็กและยังอยู่ภายใต้การพัฒนาอย่างมาก (การเปลี่ยนแปลง API)! การปรับปรุงหลายอย่างกำลังจะมาเร็ว ๆ นี้


3
>> บทความวิจัยนี้เพิ่งตีพิมพ์โดย Google << มันไม่ใช่บทความวิจัยและไม่ได้เผยแพร่โดย Google เป็นรายงานประสบการณ์โดยพนักงาน Google หนึ่งคนที่นำเสนอในการประชุมเชิงปฏิบัติการ Scala Days 2011
igouy

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

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

บนหน้าปกคุณสามารถอ่านที่อยู่ทางไปรษณีย์ที่ผู้เขียนสามารถติดต่อได้และที่อยู่อีเมลของผู้เขียน ตรวจสอบ URL ของไฟล์ PDF ที่คุณโพสต์ จดโดเมน - days2011.scala-lang.org - The Scala Days 2011 "การประชุมเชิงปฏิบัติการ Scala
igouy

1

Go เร็วกว่า Python และช้ากว่า Java เล็กน้อย ประสบการณ์คร่าวๆของฉันพบว่า Go จะเร็วกว่า Python มาก (1-2 คำสั่ง) และช้ากว่า Java ประมาณ 10-20% อย่างไรก็ตาม Go จะเร็วกว่า Java เล็กน้อยหากใช้กับ quad-core (x64) Go มีประสิทธิภาพมากขึ้นในแง่ของ RAM ของหน่วยความจำ

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

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

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

อย่างไรก็ตามนั่นเป็นเพียงประสบการณ์ของนักพัฒนา


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