เหตุใด ES6 ดั้งเดิมจึงสัญญาว่าช้ากว่าและใช้หน่วยความจำมากกว่าบลูเบิร์ด


195

ในเกณฑ์มาตรฐานนี้ชุดใช้เวลานานขึ้น 4 เท่าในการดำเนินการกับสัญญา ES6 เมื่อเทียบกับสัญญา Bluebird และใช้หน่วยความจำ 3.6 เท่า

ไลบรารี JavaScript จะเร็วและเบากว่าการใช้งานดั้งเดิมของ v8 ที่เขียนใน C ได้อย่างไร? สัญญาของ Bluebird นั้นมี API เดียวกันกับสัญญา ES6 ดั้งเดิม (รวมถึงวิธีการอรรถประโยชน์เพิ่มเติม)

การใช้งานดั้งเดิมนั้นเขียนได้ไม่ดีหรือมีแง่มุมอื่น ๆ


โปรดทราบว่าการใช้งานจาวาสคริปต์ที่ทันสมัยมีการปรับอย่างหนักและอาจทำงาน nativelyใช้JIT

1
ตามเกณฑ์มาตรฐานนี้ BlueBirdJS จริงช้ากว่าสัญญาพื้นเมือง แต่ PromiseMeSpeedJS จริง ๆ แล้วแซงหน้าทั้งคู่ หนึ่งในหลายสิ่งที่พิสูจน์ให้เห็นผ่าน PromiseMeSpeedJS นี้คือผู้ร้ายประสิทธิภาพการทำงานที่สำคัญสำหรับสัญญาที่เป็นมากเกินไปไม่เหมาะสมของnewผู้ประกอบการเพราะ PromiseMeSpeedJS newไม่ได้ใช้
Jack Giffin

1
@JackGiffin Chrome 67: PromiseMeSpeedJS นั้นช้ากว่า 46% และ Bluebird นั้นช้ากว่า 61%
FINDarkside

คำตอบ:


272

ผู้แต่งครามที่นี่

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

การดำเนิน V8 ก็ไม่เป็นที่ที่ดีที่สุดเป็นนกชนิดหนึ่งก็สำหรับกรณีจัดสรรอาร์เรย์สำหรับตัวจัดการสัญญา สิ่งนี้ใช้หน่วยความจำจำนวนมากเมื่อแต่ละสัญญามีการจัดสรรอาร์เรย์สองสามชุด (มาตรฐานสร้างสัญญา 80k โดยรวมเพื่อให้จัดสรรอาร์เรย์ที่ไม่ได้ใช้ 160k) ในความเป็นจริง 99.99% ของกรณีการใช้งานไม่เคยแยกสัญญามากกว่าหนึ่งครั้งดังนั้นการเพิ่มประสิทธิภาพสำหรับกรณีทั่วไปนี้จะได้รับการปรับปรุงการใช้งานหน่วยความจำขนาดใหญ่

แม้ว่า V8 จะใช้การเพิ่มประสิทธิภาพเช่นเดียวกับ Bluebird แต่ก็ยังคงถูกขัดขวางโดยข้อกำหนด มาตรฐานต้องใช้new Promise(รูปแบบการต่อต้านใน Bluebird) เนื่องจากไม่มีวิธีอื่นในการสร้างคำสัญญาที่สำคัญใน ES6 new Promiseเป็นวิธีที่ช้ามากในการสร้างสัญญาครั้งแรกฟังก์ชั่นผู้ดำเนินงานจัดสรรการปิดอย่างที่สองมันจะผ่าน 2 ปิดแยกเป็นอาร์กิวเมนต์ นั่นคือการปิด 3 ครั้งที่จัดสรรต่อสัญญา แต่การปิดเป็นวัตถุที่มีราคาแพงกว่าสัญญาที่ปรับให้เหมาะสมแล้ว

Bluebird สามารถใช้promisifyซึ่งเปิดใช้งานการปรับแต่งมากมายและเป็นวิธีที่สะดวกกว่าในการใช้ API การโทรกลับและช่วยให้การแปลงโมดูลทั้งหมดเป็นโมดูลที่อิงตามสัญญาในหนึ่งบรรทัด ( promisifyAll(require('redis'));)


10
"ยังถูกขัดขวางโดยสเปค" - ไม่แน่ใจว่ามันหมายถึงอะไร คุณกำลังบอกว่า ES6 กำลังตามสเป็คที่ช้าโดยเนื้อแท้และถ้าเป็นเช่นนั้นหมายความว่าบลูเบิร์ดนั้นไม่ได้สเป็คเหมือนกัน (และถ้าเป็นกรณีนั้นมันจะต่างจากสเป็คอื่นหรือไม่) และมีเหตุผลใดที่ทำให้ ES6 ไม่มีวิธีที่ดีกว่าในการสร้างรูทสัญญานอกเหนือจากnew Promiseหรือปรับปรุงอินสแตนซ์เพื่อให้มีราคาถูกลง (เช่นไม่สร้างการปิด 3 ครั้งต่ออินสแตนซ์)?
แอนโธนี

12
นั่นฟังดูไม่ดีเลย (สำหรับ JS) ฉันไม่ต้องการใช้ห้องสมุดสัญญาเมื่อมีการนำไปใช้ภายใน นี่เป็นสถานการณ์ที่โชคร้ายสำหรับทุกคนถ้าเป็นจริง แต่ฉันมีปัญหาในการดูสัญญา - hype ต่อไปฉันเขียน 100,000 LoC JS apps และฉันก็ยังไม่เห็นความต้องการที่แท้จริงสำหรับเรื่องนี้มันเป็นการปรับปรุงเล็กน้อยมากสำหรับฉันซึ่งส่วนใหญ่เป็นการจัดการข้อผิดพลาดไม่ใช่ การปรับปรุงในการจัดการการโทรกลับ (ฉันไม่เคยอยู่ใน "callback hell" ด้วยรูปแบบการเข้ารหัสของฉัน)
Mörre

19
ใน ES6 คุณไม่สามารถใช้Promise.resolve()เพื่อสร้าง "สัญญาหลัก" ได้หรือไม่?
zetlen

10
@ MörreNoseshine (ต่อ) ผู้เขียน ES6 เข้ามาและกล่าวว่า "เฮ้ลองระบุว่าเครื่องยนต์ JS ต้องให้สัญญาทั่วไป / A + ที่สอดคล้องกับยูทิลิตี้นอกกรอบเพื่อให้ผู้คนมีเครื่องมือสัญญาพื้นฐานอยู่เสมอ " นี่คือความสะดวกสบายที่ดี (ไม่ต้องนำเข้าห้องสมุดเพียงเพื่อทำสิ่งที่รวดเร็วPromise.resolve()หรืออะไรก็ตาม) แต่มันเป็นการใช้งานขั้นพื้นฐานมากและการมีอยู่ของมันไม่ควรทำให้คุณผิดหวังโดยใช้เครื่องมือที่เกี่ยวกับคำสัญญาที่รุนแรงมากขึ้นเช่น Bluebird!
callum

11
@ MörreNoseshine 100k แอพ LOC Javascript ที่อาจไม่เคยมีฟังก์ชั่น async มาก่อน ขอให้โชคดีในการเขียนเกม LoC JS ขนาด 100k พร้อมกับคลัง mysql / redis โดยไม่มี Bluebird
NiCk Newman
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.