Các trình duyệt phân tích javascript trên mỗi trang tải?


190

Các trình duyệt (IE và Firefox) có phân tích các tệp javascript được liên kết mỗi khi trang làm mới không?

Họ có thể lưu trữ các tệp, vì vậy tôi đoán họ sẽ không cố tải xuống mỗi lần, nhưng vì mỗi trang về cơ bản là riêng biệt, tôi hy vọng họ sẽ xé bất kỳ mã cũ nào và phân tích lại.

Điều này là không hiệu quả, mặc dù hoàn toàn dễ hiểu, nhưng tôi tự hỏi liệu các trình duyệt hiện đại có đủ thông minh để tránh bước phân tích cú pháp trong các trang web hay không. Tôi đang nghĩ về các trường hợp một trang web sử dụng thư viện javascript, như ExtJS hoặc jQuery, v.v.


4
2c của tôi: Tôi cảm thấy lợi ích về hiệu suất của các tệp Javascript được phân tích bộ đệm là quá nhỏ để điều này trở thành một tối ưu hóa có ý nghĩa.
Itay Maman

2
Từ điểm chuẩn của tôi, nó thực sự có thể quan trọng. Ví dụ, thời gian tải jQuery là khoảng 30ms (trên máy tính để bàn nhanh), trong đó 20% chỉ phân tích mã thành một đại diện thực thi và phần còn lại đang thực thi nó, tức là khởi tạo đối tượng jQuery trong trường hợp này. Nếu bạn đang sử dụng điện thoại di động và bạn sử dụng hai hoặc ba thư viện, độ trễ này có thể có liên quan, vì việc thực thi JavaScript đang bị chặn và về cơ bản trang này trống cho đến khi mọi tập lệnh JS được tải trong bộ nhớ.
djjeck

Câu trả lời:


338

Đây là những chi tiết mà tôi đã có thể đào lên. Điều đáng chú ý đầu tiên là mặc dù JavaScript thường được coi là được giải thích và chạy trên máy ảo, nhưng điều này thực sự không đúng với các trình thông dịch hiện đại, có xu hướng biên dịch nguồn trực tiếp thành mã máy (ngoại trừ IE).


Chrome: Động cơ V8

V8 có bộ đệm tổng hợp. Cửa hàng này đã biên dịch JavaScript bằng cách sử dụng hàm băm của nguồn cho tối đa 5 bộ sưu tập rác. Điều này có nghĩa là hai đoạn mã nguồn giống hệt nhau sẽ chia sẻ một mục bộ đệm trong bộ nhớ bất kể chúng được bao gồm như thế nào. Bộ đệm này không bị xóa khi các trang được tải lại.

Nguồn


Cập nhật - 19/03/2015

Nhóm Chrome đã phát hành chi tiết về các kỹ thuật mới của họ để phát trực tuyến và bộ đệm ẩn JavaScript .

  1. Tập lệnh truyền phát

Script streaming tối ưu hóa việc phân tích cú pháp các tệp JavaScript. [...]

Bắt đầu từ phiên bản 41, Chrome phân tích cú pháp async và hoãn lại các tập lệnh trên một luồng riêng biệt ngay khi quá trình tải xuống bắt đầu. Điều này có nghĩa là phân tích cú pháp có thể hoàn thành chỉ một phần nghìn giây sau khi quá trình tải xuống kết thúc và kết quả là các trang tải nhanh hơn 10%.

  1. Bộ nhớ đệm mã

Thông thường, công cụ V8 biên dịch JavaScript của trang mỗi lần truy cập, biến nó thành hướng dẫn mà bộ xử lý hiểu. Mã được biên dịch này sau đó sẽ bị loại bỏ khi người dùng điều hướng khỏi trang vì mã được biên dịch phụ thuộc nhiều vào trạng thái và ngữ cảnh của máy tại thời điểm biên dịch.

Chrome 42 giới thiệu một kỹ thuật nâng cao về lưu trữ bản sao mã được biên dịch cục bộ để khi người dùng quay lại trang, các bước tải xuống, phân tích cú pháp và biên dịch đều có thể được bỏ qua. Trên tất cả các lần tải trang, điều này cho phép Chrome tránh khoảng 40% thời gian biên dịch và tiết kiệm pin quý giá trên thiết bị di động.


Opera: Động cơ Carakan

Trong thực tế, điều này có nghĩa là bất cứ khi nào một chương trình tập lệnh sắp được biên dịch, có mã nguồn giống với chương trình khác đã được biên dịch gần đây, chúng tôi sử dụng lại đầu ra trước đó từ trình biên dịch và bỏ qua hoàn toàn bước biên dịch. Bộ đệm này khá hiệu quả trong các tình huống duyệt web điển hình trong đó một trang tải trang sau trang từ cùng một trang, chẳng hạn như các bài báo khác nhau từ một dịch vụ tin tức, vì mỗi trang thường tải cùng một thư viện tập lệnh, đôi khi rất lớn.

Do đó, JavaScript được lưu trữ trên các trang tải lại, hai yêu cầu cho cùng một tập lệnh sẽ không dẫn đến việc biên dịch lại.

Nguồn


Firefox: Công cụ SpiderMonkey

SpiderMonkey sử dụng Nanojitlàm back-end gốc, trình biên dịch JIT. Quá trình biên dịch mã máy có thể xem tại đây . Nói tóm lại, nó xuất hiện để biên dịch lại các tập lệnh khi chúng được tải. Tuy nhiên, nếu chúng ta xem xét kỹ hơn các phần bên trong, Nanojitchúng ta sẽ thấy rằng trình giám sát cấp cao hơn jstracer, được sử dụng để theo dõi quá trình biên dịch có thể chuyển qua ba giai đoạn trong quá trình biên dịch, mang lại lợi ích cho Nanojit:

Trạng thái ban đầu của màn hình theo dõi là giám sát. Điều này có nghĩa là spidermonkey đang diễn giải mã byte. Mỗi khi spidermonkey diễn giải mã byte nhảy lùi, màn hình sẽ ghi chú số lần giá trị bộ đếm chương trình đích (PC) đã được nhảy lên. Con số này được gọi là số lần truy cập cho PC. Nếu số lần truy cập của một PC cụ thể đạt đến giá trị ngưỡng, mục tiêu được coi là nóng.

Khi màn hình quyết định một PC mục tiêu đang nóng, nó sẽ tìm kiếm một đoạn mã băm để xem liệu có một đoạn nào giữ mã riêng cho PC đích đó hay không. Nếu nó tìm thấy một đoạn như vậy, nó chuyển sang chế độ thực thi. Nếu không, nó chuyển sang chế độ ghi.

Điều này có nghĩa là đối với hotcác đoạn mã, mã gốc được lưu trữ. Có nghĩa là sẽ không cần phải biên dịch lại. Điều không rõ ràng là các phần gốc được băm này được giữ lại giữa các lần làm mới trang. Nhưng tôi sẽ cho rằng họ là. Nếu ai có thể tìm thấy bằng chứng hỗ trợ cho điều này thì tuyệt vời.

EDIT : Nó được chỉ ra rằng nhà phát triển Mozilla Boris Zbarsky đã tuyên bố rằng Gecko không nhớ cache biên soạn kịch bản chưa . Lấy từ câu trả lời SO này .


Safari: JavaScriptCore / SquirelFish Engine

Tôi nghĩ rằng câu trả lời tốt nhất cho việc thực hiện này đã được đưa ra bởi người khác .

Hiện tại chúng tôi không lưu bộ đệm mã byte (hoặc mã gốc). Đó là một
tùy chọn mà chúng tôi đã xem xét, tuy nhiên, hiện tại, việc tạo mã là một
phần không đáng kể trong thời gian thực hiện JS (<2%), vì vậy chúng tôi hiện không theo đuổi
điều này.

Điều này được viết bởi Maciej Stachowiak , nhà phát triển chính của Safari. Vì vậy, tôi nghĩ rằng chúng ta có thể coi điều đó là đúng.

Tôi không thể tìm thấy bất kỳ thông tin nào khác nhưng bạn có thể đọc thêm về các cải tiến tốc độ của SquirrelFish Extremecông cụ mới nhất tại đây hoặc duyệt mã nguồn ở đây nếu bạn cảm thấy phiêu lưu.


IE: Công cụ Luân xa

Không có thông tin hiện tại nào liên quan đến Công cụ JavaScript (Chakra) của IE9 trong lĩnh vực này. Nếu ai biết bất cứ điều gì, xin vui lòng bình luận.

Điều này khá không chính thức, nhưng đối với việc triển khai công cụ cũ hơn của IE, Eric Lippert ( một nhà phát triển MS của JScript ) nói trong một bài trả lời blog ở đây rằng:

JScript Classic hoạt động giống như một ngôn ngữ được biên dịch theo nghĩa là trước khi bất kỳ chương trình JScript Classic nào chạy, chúng tôi hoàn toàn kiểm tra cú pháp mã, tạo một cây phân tích đầy đủ và tạo mã byte. Sau đó, chúng tôi chạy mã byte thông qua trình thông dịch mã byte. Theo nghĩa đó, JScript là mỗi bit được "biên dịch" như Java. Sự khác biệt là JScript không cho phép bạn kiên trì hoặc kiểm tra mã byte độc ​​quyền của chúng tôi . Ngoài ra, mã byte là cấp độ cao hơn nhiều so với mã byte JVM - ngôn ngữ mã byte JScript Classic ít hơn một tuyến tính của cây phân tích cú pháp, trong khi mã byte JVM rõ ràng được dự định hoạt động trên máy ngăn xếp mức thấp.

Điều này cho thấy rằng mã byte không tồn tại theo bất kỳ cách nào và do đó mã byte không được lưu trữ.


10
+1, viết xuất sắc. Tuy nhiên, liên quan đến Firefox, vui lòng xem câu hỏi StackOverflow này , nơi Nhà phát triển Mozilla, Boris Zbarsky giải thích rằng Gecko hiện không làm điều này.
cha0site

Cảm ơn, tôi đã thấy rằng trong các chuyến đi của mình nhưng không thể tìm thấy bất kỳ bằng chứng hỗ trợ nào khác. Tôi sẽ chỉnh sửa câu trả lời với nó.
Jivings

1
Lưu ý rằng những gì đã nói về IE đã được nói vào năm 2003: Bản phát hành đầu tiên của công cụ
JS9

Ngoài ra, Opera lưu trữ mã byte của JS hơn là chỉ tải lại. (Tuy nhiên, mã máy được tạo không được lưu vào bộ đệm).
gsnedder

2
@Jivings Lấy những điều trên làm nguồn. (Tôi là một trong những người trong nhóm Carakan.)
gsnedder

12

Opera làm điều đó, như đã đề cập trong câu trả lời khác. ( nguồn )

Firefox (công cụ SpiderMonkey) không lưu trữ mã byte. ( nguồn )

WebKit (Safari, Konqueror) không lưu trữ mã byte. ( nguồn )

Tôi không chắc chắn về IE [6/7/8] hoặc V8 (Chrome), tôi nghĩ IE có thể thực hiện một số loại bộ đệm trong khi V8 thì không. IE là nguồn đóng nên tôi không chắc, nhưng trong V8, nó có thể không có ý nghĩa đối với mã "được biên dịch" trong bộ đệm vì chúng biên dịch thẳng vào mã máy.


1
IE6 hầu như chắc chắn sẽ không. IE9 có thể, nhưng tôi không có bất kỳ bằng chứng nào. Biên dịch JS có khả năng không được lưu trữ ở bất cứ đâu vì nó thường khá lớn.
gsnedder

@gsnedder: Tôi không chắc chắn về mặt kỹ thuật IE8 không thể làm điều đó, có vẻ như nó quá biên dịch thành mã byte (không chính thức nhưng đóng), vì vậy không có lý do kỹ thuật nào để không lưu trữ bộ đệm đó. IE9 dường như thêm một JIT để biên dịch thành mã gốc.
cha0site

2
Bytecode đã được IE sử dụng cho chương trình đào tạo mãi mãi. Không có gì mới trong IE8. Nó chỉ đơn thuần là được cung cấp cho một thông dịch viên, hiệu suất của trình thông dịch chậm hơn nhiều so với thời gian phân tích, nó hoàn toàn không liên quan. IE9 có một công cụ JS hoàn toàn mới (từ đầu), vì vậy không có gì xảy ra giữa hai.
gsnedder

3

Theo như tôi biết, chỉ có Opera lưu trữ JavaScript được phân tích cú pháp. Xem phần "Bộ nhớ đệm chương trình" tại đây .


cảm ơn, bạn có nhiều chi tiết hơn về gia đình trình duyệt khác không?
ajreal

2

Không có gì đáng để Google Dart giải quyết vấn đề này một cách rõ ràng thông qua "Ảnh chụp nhanh" - mục tiêu là tăng tốc thời gian khởi tạo và tải thời gian bằng cách tải phiên bản mã được chuẩn bị trước.

InfoQ có một bài viết tốt @ http://www.infoq.com/articles/google-dart


0

Tôi nghĩ rằng câu trả lời đúng sẽ là "không phải lúc nào cũng vậy." Theo những gì tôi hiểu, cả trình duyệt và máy chủ đều đóng vai trò quyết định những gì được lưu trữ. Nếu bạn thực sự cần tải lại các tệp mỗi lần, thì tôi nghĩ bạn sẽ có thể định cấu hình tệp đó từ bên trong Apache (ví dụ). Tất nhiên, tôi cho rằng trình duyệt của người dùng có thể được cấu hình để bỏ qua cài đặt đó, nhưng điều đó có thể không xảy ra.

Vì vậy, tôi sẽ tưởng tượng rằng trong hầu hết các trường hợp thực tế, các tệp javascript được lưu trong bộ nhớ cache, nhưng được diễn giải lại một cách linh hoạt mỗi khi trang tải.


0

Trình duyệt chắc chắn sử dụng bộ nhớ đệm nhưng có, các trình duyệt phân tích cú pháp JavaScript mỗi khi làm mới trang. Bởi vì bất cứ khi nào một trang được trình duyệt tải, nó sẽ tạo ra 2 cây 1. Cây liên tục và cây 2.render.

Cây render này bao gồm các thông tin về bố cục trực quan của các yếu tố dom. Vì vậy, bất cứ khi nào một trang tải, javascript được phân tích cú pháp và bất kỳ thay đổi động nào của javascript sẽ như định vị phần tử dom, hiển thị / ẩn phần tử, phần tử thêm / xóa sẽ khiến trình duyệt tạo lại cây kết xuất. Nhưng các broswers hiện đại như FF và chrome xử lý nó hơi khác nhau, chúng có khái niệm kết xuất tăng dần, do đó, bất cứ khi nào có sự thay đổi động của js như đã đề cập ở trên, nó sẽ chỉ khiến các phần tử đó hiển thị và sơn lại.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.