Tổng quan về V8 Engine
Tổng quan V8 Engine Pipeline Kiến trúc của V8 được thay đổi theo thời gian. Trong những phiên bản cũ, thiết kế khá phức tạp và khó để mở rộng. Nhưng gần đây, đội ngũ phát triển quyết định thay đổi hướng tiếp cận để V8 trở nên tổng quát hơn từ đó có thể thêm vào những component như ES6, ES7 và ...
Tổng quan V8 Engine
Pipeline
Kiến trúc của V8 được thay đổi theo thời gian. Trong những phiên bản cũ, thiết kế khá phức tạp và khó để mở rộng. Nhưng gần đây, đội ngũ phát triển quyết định thay đổi hướng tiếp cận để V8 trở nên tổng quát hơn từ đó có thể thêm vào những component như ES6, ES7 và những chức năng khác một cách linh động.
Chi tiết về biểu đồ phát triển của V8 có thể xem chi tiết thông qua slides và video.
Ngày nay, V8's pipeline như hình bên dưới
Tại sao chúng ta lại có 2 giai đoạn: Interpreter Ignition và Compiler TurboFan, lý do là chúng ta cần sự cân bằng giữa thời gian khởi tạo, bộ nhớ và tốc độ bởi vì V8 không chỉ thiết kế cho trình duyệt mà còn được sử dụng cho di động và node. Vì vậy, mà đôi lúc chúng ta cần ít bộ nhớ ( cho di động chẳng hạn).
Bạn có thể xem hình dưới đây, bạn vẽ một đường thẳng vuông góc, điểm cắt ngang là những gì bạn đạt được cho engine. Từ đó, có thể hiểu là không thể nào đạt được tốt hết cho mọi trường hợp.
Ignition
Tại sao chúng ta lại cần Ignition, để hiểu rõ lý do chúng ta cần phải lội ngược thời gian khi những phiên bản cũ của V8 hay những trình duyệt engine khác sử dụng JIT để biên dịch ra native code ngay trước khi đoạn lệnh đó được thực thi. Đoạn code đó được biên dịch thông qua JIT tiêu hao một lượng bộ nhớ tương đối mặc dù nó chỉ được thực hiện một lần duy nhất.
Sử dụng Ignition, V8 biên dịch code thành byte code cái mà chi phí lưu trữ của nó chỉ từ 25% -> 50% so với cách ở trên.
Hum, vậy là chúng ta phải biên dịch lại ra mã máy cho mỗi đoạn code?
Thật ra thì Ignition được sinh ra sau TurboFan vì vậy nó tận dụng được sức mạnh của TurboFan và những tiến trình ở trong nó. Trong trường hợp này, mã bytecode từ Ignition có thể đưa vào TurboFan và xử lý bình thường mà không cần phải biên dịch lại ban đầu từ code. Theo như V8 thì tốc độ thực thi từ mã byte code và cùng một đoạn code đó với mã máy thì hai cái là gần như như nhau.
invoke function --> Ignition --> bytecode --> TurboFan (compile part) --> machine code
TurboFan
Khi một đoạn code được gọi, nó được chuyển từ "cold" sang "warm" và nó được chuyển sang "hot" khi được thực thi nhiều lần (số lần để sang "hot" phụ thuộc vào engine). Khi đoạn code là "hot", TurboFan lúc này mới tìm cách để tối ưu hoá thông qua dữ liệu nó thu thập được từ những lần chạy trước (một trong những cách là đoán kiểu dữ liệu).
Ghi chú: Trước đây, V8 sử dụng Code Objects để lưu trữ cách thức truy cập thuộc tính nhưng nó ảnh hưởng tốc độ tải trang (chiếm bộ nhớ). Khi Ignition được giới thiệu, V8 tổng quát hoá TurboFan dựa trên đó xây dựng nên kiến trúc thực thi code, chúng ta có thể nó sử dụng nó cho Inline Cache. Thông qua đó sẽ giảm thời lượng tải trang và những Code Objects nhỏ. Cơ bản, thông tin về cách lưu trữ và tải được mã hoá thông qua một cấu trúc dữ liệu (FeedbackVector), vì vậy TurboFan thực thi tốt hơn dựa trên thông tin đó.
Hình dưới đây là TurboFan's pipeline. Như đã giới thiệu ở trên, bytecode từ Ignition (Interpreter Assembler) có thể đưa vào luồng xử lý của TurboFan để biên dịch ra mã máy.