การตรวจสอบประเภทในล่าม / ผู้แปลภาษาแบบไดนามิกเช่น JavaScript เป็นอย่างไร


11

ในภาษาแบบไดนามิกเช่น JavaScript หรือ Python ชนิดของตัวแปรจะถูกกำหนดที่รันไทม์ นี่คือเหตุผลหนึ่งที่ทำให้ช้ากว่าภาษาที่พิมพ์เช่น Java

การตรวจสอบประเภทดำเนินการอย่างไร อะไรเป็นเหตุผลสำคัญที่ทำให้กระบวนการนี้ช้า


มันไม่ได้ช้าลงเพราะมันเป็นแบบไดนามิกมันช้ากว่าเพราะมันยากที่จะทำให้มันเร็วขึ้น JavaScript นั้นแท้จริงแล้วได้รับการปรับให้เหมาะสมที่สุดและค่อนข้างเร็ว
Derek Litz

คำตอบ:


5

มีความสับสนในคำถาม

มีข้อสันนิษฐานว่าการตรวจสอบชนิดช้าซึ่งไม่จำเป็นต้องเป็นกรณีนี้

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

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

เกี่ยวกับการทำประเภทการตรวจสอบใน JavaScript โปรดดูที่: http://www.cs.brown.edu/~sk/Publications/Papers/Published/gsk-flow-typing-theory/ สำหรับภาพรวมทั่วไปเพิ่มเติมเกี่ยวกับวิธีการทำงานของตัวตรวจสอบชนิดหนังสือเรียนภาษาการเขียนโปรแกรมมาตรฐานจะครอบคลุมอัลกอริทึม ตัวอย่างเช่นhttp://www.cs.brown.edu/~sk/Publications/Books/ProgLangs/


ฉันยังได้เขียนแบบสำรวจขนาดเล็กเกี่ยวกับการติดตาม JITs และภาษาแบบไดนามิกในhashcollision.org/comprehensive/tracing.pdf

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

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

1
ดำเนินการต่อ: แต่บ่อยครั้งโดยเฉพาะอย่างยิ่งในภาษาไดนามิกคุณต้องการแสดงค่าของประเภทต่างๆ การเลือกปฏิบัติมีหลายวิธี แท็กประเภทเป็นเรื่องธรรมดา แต่มีเทคนิคอื่น ๆ ตัวอย่างเช่นคุณอาจวางบางประเภทไว้ในขอบเขตของหน่วยความจำที่ถูกบล็อก โปรดดู "การแสดงข้อมูลประเภทในภาษาที่พิมพ์แบบไดนามิก" lambda-the-ultimate.org/node/3912สำหรับการสำรวจที่ครอบคลุมของเทคนิคการเป็นตัวแทน

7

โดยพื้นฐานแล้วในภาษาที่ไม่มีการพิมพ์ทุกจุดอ้างอิงไปยังวัตถุที่มีทั้งประเภทและค่า ตัวอย่างเช่นvar a = 3ชี้ไปที่อินสแตนซ์ที่มีค่า 3 และชนิด int ถ้าคุณทำการa = "bla"อ้างอิงจะถูกอัพเดตเป็นอินสแตนซ์ที่มีสตริง "bla" และสตริงประเภทวัตถุเก่าจะถูกทิ้ง ฯลฯ ...

สิ่งนี้ช้าเพราะทุกครั้งที่มีการดำเนินการ (เช่นa + b) ในประเภทพื้นฐานเหล่านี้รันไทม์จะต้องตรวจสอบวัตถุก่อนตรวจสอบว่าประเภทของพวกเขาเข้ากันได้ดำเนินการสร้างวัตถุใหม่

ในทางตรงกันข้ามa + bใน C ++ หรือ Java ตรวจสอบ ณเวลารวบรวมว่าประเภทนั้นถูกต้องและเข้ากันได้จากนั้น a และ b จะถูกเก็บไว้เป็นค่าทันที (ไม่ใช่การอ้างอิง) และการเพิ่มเป็นการดำเนินการของตัวประมวลผลอย่างง่ายในค่าเหล่านี้

แน่นอนว่านี่คือทฤษฎีทั้งหมด ในทางปฏิบัติการเพิ่มประสิทธิภาพจำนวนมากสามารถทำได้ในกระบวนการนี้เพื่อหลีกเลี่ยงค่าใช้จ่ายส่วนใหญ่และภาษาที่พิมพ์แบบไดนามิกสามารถทำได้ค่อนข้างเร็ว


1
เทคนิคเช่นแคชแบบอินไลน์ polymorphic สามารถปรับปรุงประสิทธิภาพได้อย่างมาก งานเขียนของ David Ungar (Self) และ Eliot Miranda (Squeak, Visual Works Smalltalk virtual machine) เป็นข้อมูลที่มากที่สุดเกี่ยวกับประสิทธิภาพของภาษาแบบไดนามิก
Frank Shearar

0

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


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