Hướng dẫn how does the javascript v8 engine work? - công cụ javascript v8 hoạt động như thế nào?

Từ chế độ xem cấp cao, việc thực hiện động cơ JavaScript V8 bao gồm 5 bước.

  1. Khởi tạo môi trường trong máy chủ
  2. Biên dịch mã JavaScript
  3. Tạo mã byte
  4. Giải thích và thực thi bytecodes
  5. Tối ưu hóa một số byte để hiệu suất tốt hơn

1. Khởi tạo môi trường

Về mặt kỹ thuật, đây không phải là một phần của công việc V8. Đó là quá trình kết xuất của trình duyệt khởi tạo hai mục sau:

  • Môi trường chủ
  • Động cơ V8

Một trình duyệt có nhiều quy trình kết xuất. Thông thường, mỗi tab Trình duyệt có quy trình kết xuất và khởi tạo một thể hiện V8.

Nếu bạn quan tâm đến quy trình kết xuất và nhiều hơn về cách thức hoạt động của trình duyệt, hãy kiểm tra bài đăng này.

Môi trường chủ là gì? Trong bối cảnh của chúng tôi, đó là trình duyệt. Do đó, chúng tôi sẽ sử dụng trình duyệt trên mạng và môi trường máy chủ có thể thay thế cho nhau trong bài đăng này. Tuy nhiên, hãy nhớ rằng trình duyệt chỉ là một trong những môi trường máy chủ cho JavaScript. Một người nổi tiếng khác là môi trường chủ của nút.

Có gì trong môi trường chủ?

Môi trường máy chủ cung cấp mọi thứ mà động cơ JavaScript dựa trên, bao gồm:

  1. Gọi ngăn xếp
  2. Đống
  3. Hàng đợi gọi lại
  4. Vòng lặp sự kiện
  5. API Web và Web DOM

Tương tác người dùng trên trang web kích hoạt một loạt các sự kiện. Trình duyệt đã thêm chúng vào hàng đợi gọi lại cùng với các chức năng gọi lại liên quan. Vòng lặp sự kiện hoạt động giống như một vòng lặp vô hạn trong khi vòng lặp tiếp tục lấy lại một cuộc gọi lại từ hàng đợi. Sau đó, JavaScript trong cuộc gọi lại được biên dịch và thực thi. Một số dữ liệu trung gian được lưu trữ trong ngăn xếp cuộc gọi. Một số được lưu trong đống, chẳng hạn như một mảng hoặc một đối tượng.

Tại sao trình duyệt lưu trữ dữ liệu ở hai nơi khác nhau?

  • Không gian giao dịch cho tốc độ: Một ngăn xếp cuộc gọi đòi hỏi không gian liên tục trong bộ nhớ, giúp việc xử lý nhanh chóng. Tuy nhiên, không gian liên tục là hiếm trong bộ nhớ. Để giải quyết vấn đề, các nhà thiết kế trình duyệt hạn chế nó với kích thước tối đa. Đây là nơi lỗi ngăn xếp ngăn xếp. Thông thường, trình duyệt lưu dữ liệu với kích thước giới hạn trong ngăn xếp cuộc gọi, chẳng hạn như số nguyên và các loại dữ liệu chính khác. A call stack requires continuous space in memory, making it fast to process. However, continuous space is rare in memory. To resolve the issue, browser designers restrain it with max size. This is where the stack-overflow error comes from. Usually, the browser saves data with limited size in the call stack, such as an integer and other primary data types.
  • Tốc độ giao dịch cho không gian: Heap không yêu cầu không gian liên tục để lưu dữ liệu rộng rãi như một đối tượng. Sự đánh đổi là đống tương đối chậm để xử lý dữ liệu. Heap doesn’t require continuous space to save extensive data like an object. The tradeoff is that the heap is relatively slow to process the data.

Theo tôi, ngăn xếp cuộc gọi và vòng lặp sự kiện là hai cơ chế quan trọng để hiểu cách thức hoạt động của JavaScript, vượt ra ngoài bài đăng này.

  • Tôi có một bài viết giải thích cách thức hoạt động của ngăn xếp cuộc gọi. Nhiều tài nguyên đọc được đính kèm ở cuối bài nếu bạn muốn tìm hiểu thêm về cơ chế.
  • Về vòng lặp sự kiện, bài đăng này từ Jake Archibald là bài viết tốt nhất với các ví dụ tương tác.

Động cơ V8 dựa vào và trao quyền cho môi trường máy chủ

Môi trường máy chủ của V8 giống như hệ điều hành máy tính của bạn thành phần mềm. Softwares dựa vào hệ điều hành để chạy. Trong khi đó, họ trao quyền cho hệ thống của bạn để thực hiện rất nhiều nhiệm vụ nâng cao.

Lấy Photoshop, ví dụ. Nó cần được chạy trên Windows hoặc MacOS. Trong khi đó, hệ điều hành của bạn không thể tạo ra một poster đẹp cho bạn, nhưng Photoshop có thể.

Giống như động cơ V8, nó cung cấp các tính năng bổ sung trên đầu môi trường máy chủ:

  • Các tính năng lõi JavaScript dựa trên tiêu chuẩn Ecmascript, chẳng hạn như tạo đối tượng và chức năng
  • Cơ chế thu gom rác
  • Các tính năng Coroutine
  • Và nhiều hơn nữa…

Khi môi trường máy chủ và động cơ V8 đã sẵn sàng, động cơ V8 khởi động bước tiếp theo.

2. Biên dịch mã JavaScript

Ở bước này, động cơ V8 chuyển đổi mã JavaScript thành Cây cú pháp trừu tượng (AST) và tạo phạm vi.

Động cơ V8 không nói ngôn ngữ JavaScript. Kịch bản cần được cấu trúc trước khi xử lý.

AST là một cấu trúc cây, dễ dàng để V8 tiêu hóa.

Trong khi đó, phạm vi được tạo ra ở bước này, bao gồm phạm vi toàn cầu và nhiều phạm vi hơn ở đầu nó được lưu trữ trong môi trường máy chủ. Phạm vi tự nó có giá trị một bài khác để giải thích. Bạn có thể bỏ qua nó một cách an toàn ở đây.

Làm thế nào một AST trông như thế nào?

Hãy để kiểm tra một ví dụ đơn giản bằng cách hiển thị JavaScript sau ở định dạng AST.

const medium = 'good ideas';

Mỗi dòng của mã JavaScript của bạn sẽ được chuyển đổi thành AST, giống như ví dụ ở bước này.

3. Tạo mã byte

Ở bước này, động cơ V8 lấy AST và phạm vi và đầu ra byte.

Làm thế nào để các byte trông như thế nào?

Hãy cùng sử dụng cùng một ví dụ, lần này, với D8, vỏ phát triển của Chrome V8.

Để cài đặt D8 trong macOS, hãy chạy lệnh sau trong thiết bị đầu cuối.

brew install v8

Lưu mã ví dụ của chúng tôi trong tệp JavaScript v8.js và chạy lệnh sau trong thiết bị đầu cuối.

d8 --print-bytecode v8.js

D8 in các byte được tạo dựa trên AST và phạm vi từ bước cuối cùng.

[generated bytecode for function:  (0x0ee70820ffed )]
Parameter count 1
Register count 1
Frame size 8
0xee708210076 @ 0 : 12 00 LdaConstant [0]
0xee708210078 @ 2 : 1d 02 StaCurrentContextSlot [2]
0xee70821007a @ 4 : 0d LdaUndefined
0xee70821007b @ 5 : aa Return
Constant pool (size = 1)
Handler Table (size = 0)
Source Position Table (size = 0)

Parameter count 1 có nghĩa là có một tham số, đó là medium trong trường hợp của chúng tôi. Sau đó, có 4 dòng bytecodes để trình thông dịch thực thi.

4. Giải thích và thực thi Bytecodes

Các byte là một tập hợp các hướng dẫn. Ở bước này, trình thông dịch sẽ thực thi từng dòng byte từ trên xuống dưới.

Trong ví dụ trước, chúng ta thấy 4 byte sau đây.

LdaConstant [0]
StaCurrentContextSlot [2]
LdaUndefined
Return

Mỗi dòng của các byte giống như một khối Lego được đúc sẵn. Cho dù mã của bạn ưa thích đến mức nào, tất cả đều được xây dựng với các khối cơ bản phía sau cảnh.

Các chi tiết của mỗi mã byte nằm ngoài phạm vi của bài đăng này. Nếu bạn quan tâm đến nó, đây là danh sách đầy đủ các byte V8.

5. Biên dịch và thực thi mã máy

Bước này song song với bước trước. Khi thực hiện các byte, V8 tiếp tục giám sát các mã và tìm kiếm cơ hội để tối ưu hóa chúng.

Khi một số mã byte được sử dụng thường xuyên được sử dụng, V8 đánh dấu chúng là nóng. Mã nóng sau đó được chuyển đổi thành mã máy hiệu quả và được CPU tiêu thụ.

Điều gì sẽ xảy ra nếu tối ưu hóa thất bại? Trình biên dịch khử tối ưu hóa mã và để trình thông dịch thực thi các byte bản gốc.

Bytecodes so với mã máy

Nhưng tại sao V8 không sử dụng mã máy nhanh hơn trực tiếp? Willn giới thiệu các byte trung gian làm chậm toàn bộ quá trình?

Về mặt lý thuyết, vâng. Nhưng đó không phải là toàn bộ câu chuyện.

Thật thú vị, đó chính xác là cách nhóm V8 ban đầu thiết kế động cơ JavaScript. Ở độ tuổi của V8, các bước như sau:

  1. V8 biên dịch các tập lệnh cho AST và phạm vi.
  2. Một trình biên dịch biên dịch AST và phạm vi vào mã máy.
  3. V8 phát hiện một số mã máy được sử dụng thường xuyên và đánh dấu chúng là nóng.
  4. Một trình biên dịch khác tối ưu hóa các mã nóng của các mã nóng với các mã máy được tối ưu hóa.
  5. Nếu tối ưu hóa thất bại, trình biên dịch sẽ chạy quá trình khử tối ưu hóa.

Mặc dù ngày nay, cấu trúc V8 V8 phức tạp hơn, ý tưởng cơ bản vẫn giữ nguyên.

Tuy nhiên, nhóm V8 giới thiệu các byte khi động cơ phát triển. Tại sao? Bởi vì sử dụng mã máy dọc theo mang lại một số rắc rối.

1. Mã máy đòi hỏi một lượng bộ nhớ lớn

Động cơ V8 được lưu trữ mã máy tuân thủ trong bộ nhớ để sử dụng lại chúng khi tải trang.

Khi được biên dịch vào mã máy, JavaScript 10K có thể thổi vào mã máy 20m. Đó là khoảng 2.000 lần không gian bộ nhớ lớn hơn.

Làm thế nào về kích thước của các byte trong cùng một trường hợp? Đó là khoảng 80k. Bytecodes vẫn còn lớn hơn so với JavaScript ban đầu, nhưng nó nhỏ hơn mã máy tương ứng của nó.

Ngày nay, người ta thường thấy các tệp JavaScript trên 1M. Tiêu thụ bộ nhớ 2G cho mã máy không phải là một ý tưởng tốt.

Nhờ giảm kích thước, một trình duyệt có thể lưu trữ tất cả các byte được biên dịch, bỏ qua tất cả các bước trước đó và thực hiện trực tiếp chúng.

2. Mã máy không phải lúc nào cũng nhanh hơn các mã byte

Mã máy mất nhiều thời gian hơn để biên dịch, mặc dù nó đang chiếu sáng nhanh về mặt thực thi.

Bytecodes cần một thời gian ngắn hơn để biên dịch, nhưng sự đánh đổi là bước thực hiện chậm hơn. Một thông dịch viên cần phải giải thích bytecodes trước khi thực hiện chúng.

Khi chúng ta đo cả hai tùy chọn từ đầu đến cuối, cái nào nhanh hơn?

Nó phụ thuộc.

Nghệ thuật đang tìm kiếm sự cân bằng giữa hai tùy chọn này trong khi phát triển một trình thông dịch mạnh mẽ và trình biên dịch tối ưu hóa thông minh cho các mã byte.

Đánh lửa, phiên dịch V8 sử dụng, là người nhanh nhất trên thị trường.

Trình biên dịch tối ưu hóa trong V8 là Turbofan nổi tiếng, biên dịch các mã máy được tối ưu hóa cao từ byte.

3. Mã máy làm tăng sự phức tạp trong phát triển

CPU khác nhau có thể có các cấu trúc khác nhau. Mỗi người chỉ có thể hiểu một loại mã máy. Có rất nhiều thiết kế cấu trúc bộ xử lý trên thị trường. Đến tên một vài:

  • CÁNH TAY
  • ARM64
  • X64
  • S397
  • Và nhiều hơn nữa…

Nếu trình duyệt chỉ sử dụng mã máy, nó cần phải chăm sóc rất nhiều trường hợp riêng biệt. Là một nhà phát triển, chúng tôi biết rằng, không phải là một thực tiễn tốt bằng trực giác.

Chúng ta cần một bản tóm tắt.

Bytecodes là bản tóm tắt giữa JavaScript và CPU. Bằng cách giới thiệu các byte trung gian, nhóm V8 sẽ giảm khối lượng công việc để biên dịch mã máy. Trong khi đó, nó giúp V8 di chuyển đến các nền tảng mới một cách dễ dàng.

Takeaways

Đặt mọi thứ lại với nhau, bây giờ chúng ta có thể thấy một phiên bản hoàn thành về cách Chrome V8 hoạt động từ chế độ xem cấp cao.

Tài nguyên và tài liệu tham khảo

  • Cách thức hoạt động của JavaScript: Bên trong động cơ V8 + 5 Mẹo về cách viết mã được tối ưu hóa
  • Động cơ JavaScript V8 giải thích | Hacker trưa
  • Tài liệu V8
  • Danh sách Bytecodes V8
  • Trục khuỷu từ mặt đất lên
  • Tài nguyên V8

Động cơ JavaScript hoạt động như thế nào?

Động cơ JavaScript hoạt động như thế nào? Công cụ JavaScript hoạt động trên mã nguồn JavaScript và đặt nó và sau đó thực thi việc biên dịch cho các hướng dẫn nhị phân (mã máy) dễ dàng hiểu được bởi CPU.works on the JavaScript source code and puts it and then executes the compilation to binary instructions (machine code) that are easily understandable by the CPU.

Tại sao động cơ V8 JavaScript nhanh?

Khi lần đầu tiên thực hiện mã JavaScript, V8 tận dụng toàn bộ mã hóa trực tiếp dịch JavaScript được phân tích cú pháp vào mã máy mà không có bất kỳ chuyển đổi nào.Điều này cho phép nó bắt đầu thực thi mã máy rất nhanh.V8 leverages full-codegen which directly translates the parsed JavaScript into machine code without any transformation. This allows it to start executing machine code very fast.

JavaScript chạy trên động cơ nào?

V8 từ Google là công cụ JavaScript được sử dụng nhiều nhất.Google Chrome và nhiều trình duyệt dựa trên crom khác sử dụng nó, cũng như các ứng dụng được xây dựng với CEF, electron hoặc bất kỳ khung nào khác nhúng crom.Sử dụng khác bao gồm nút.Hệ thống thời gian chạy của JS và Deno. is the most used JavaScript engine. Google Chrome and the many other Chromium-based browsers use it, as do applications built with CEF, Electron, or any other framework that embeds Chromium. Other uses include the Node. js and Deno runtime systems.

Tại sao nó được gọi là động cơ V8 JavaScript?

Chrome V8 là một công cụ JavaScript, có nghĩa là nó thực thi mã JavaScript.Ban đầu, JavaScript được viết để được thực hiện bởi các trình duyệt web.Chrome V8, hoặc chỉ V8, có thể thực thi mã JavaScript trong hoặc ngoài trình duyệt, điều này làm cho kịch bản phía máy chủ có thể.it executes JavaScript code. Originally, JavaScript was written to be executed by web browsers. Chrome V8, or just V8, can execute JavaScript code either within or outside of a browser, which makes server-side scripting possible.