โครงสร้างภายในคอมไพเลอร์
การตัดสินใจออกแบบหลักที่ทำให้ Perry เร็ว
01NaN-Boxing
ค่าถูกเก็บเป็น float 64 บิตพร้อม bit pattern พิเศษสำหรับ pointer ทำให้ union type ทำงานได้โดยไม่มี overhead ที่รันไทม์ ซึ่งทำให้ (string | number)[] ทำงานได้อย่างมีประสิทธิภาพ
โดยการเข้ารหัสข้อมูล type โดยตรงใน bit payload ของ NaN ตามมาตรฐาน IEEE 754 Perry หลีกเลี่ยงความจำเป็นของ tagged union หรือ boxed value คำ 64 บิตเดียวสามารถแทนค่า JavaScript type ใดก็ได้ — ตัวเลขใช้การแสดงผลตามธรรมชาติ ในขณะที่ string, object และค่า heap-allocated อื่น ๆ ใช้ pointer bit pattern ที่อยู่ในช่วง NaN
02Monomorphization
Generic ถูกเฉพาะทางในเวลาคอมไพล์ เหมือน Rust การ instantiate type แต่ละครั้งจะสร้างโค้ดที่ปรับให้เหมาะสม กำจัด overhead ของการตรวจสอบ type ที่รันไทม์
เมื่อคุณเขียน Array'<'number'>' และ Array'<'string'>' Perry จะสร้าง implementation ที่แยกกันสองตัวซึ่งปรับให้เหมาะสมอย่างเต็มที่ นั่นหมายความว่าการดำเนินการ array บนตัวเลขใช้เลขคณิตเครื่องโดยตรง — ไม่มี type guard, ไม่มี dynamic dispatch, ไม่มี boxing
03Static Dispatch
ไม่มี virtual table การเรียก method ถูกแก้ไขในเวลาคอมไพล์ ทำให้สามารถเรียกฟังก์ชันโดยตรงและเพิ่มประสิทธิภาพด้วย inlining
Runtime OOP แบบดั้งเดิมใช้ vtable สำหรับการแก้ไข method ซึ่งเพิ่มชั้นของ indirection ในทุกการเรียก Perry แก้ไขการเรียก method ทั้งหมดแบบ static ระหว่างการคอมไพล์ เปลี่ยนการเรียก method ของ interface เป็น jump โดยตรง ซึ่งยังปลดล็อก inlining แบบเข้มข้น — method ขนาดเล็กมักถูกรวมเข้ากับจุดเรียกโดยตรง
04Zero-Cost Abstractions
คลาส, interface และ generic ของ TypeScript คอมไพล์เป็นโค้ดเนทีฟที่มีประสิทธิภาพโดยไม่มี overhead ของ runtime representation
ระบบ type ของ TypeScript มีอยู่เฉพาะเวลาคอมไพล์ — และ Perry รับเรื่องนี้อย่างตรงตัว Interface ไม่สร้างโค้ดรันไทม์ ลำดับชั้นของคลาสถูกทำให้แบน Generic constraint ถูกแก้ไขเป็น type ที่เป็นรูปธรรม ไบนารีที่คอมไพล์แล้วมีเพียงลอจิกจริง โดยไม่มีกลไกนามธรรมที่ interpreter มักแบกรับ