Bỏ qua đến nội dung chính
Về trang chủ
tools-cli Tech 6 phút đọc

JavaScriptCore Bùng Nổ Với Đa Luồng Bộ Nhớ Chia Sẻ Nhờ PR #249 Của Bun WebKit! 💥

Một pull request đột phá của Jarred Sumner (cha đẻ Bun) đang thử nghiệm tích hợp đa luồng bộ nhớ chia sẻ thực sự vào JavaScriptCore, hứa hẹn hiệu suất vượt trội so với Web Workers truyền thống.

Tier 1 · nguồn 99% độ tin cậy Auto-priority
Nguồn gốc github.com

🔥 Đột Phá: Đa Luồng Bộ Nhớ Chia Sẻ Thực Sự Trong JavaScriptCore (Bun WebKit PR #249) 🚀

Jarred Sumner, người sáng lập runtime JavaScript Bun, đã mở một pull request (PR) mang tính cách mạng – oven-sh/WebKit #249 – triển khai tính năng đa luồng bộ nhớ chia sẻ thực sự (experimental true shared-memory multi-threading) trong JavaScriptCore (JSC). JSC là công cụ đang cung cấp sức mạnh cho Apple Safari và chính Bun. 🚀

Đây là một sự thay đổi lớn so với Web Workers tiêu chuẩn hoặc worker threads của Node.js/Bun. Các giải pháp hiện tại sử dụng các vùng nhớ (heap) hoàn toàn cô lập, yêu cầu quá trình chuyển đổi/giải chuyển đổi dữ liệu (Structured Clone) chậm chạp thông qua postMessage, và giao tiếp bằng cách truyền thông điệp. Ngược lại, PR WebKit #249 giới thiệu bộ nhớ chia sẻ trực tiếp: nhiều luồng chạy trên một vùng nhớ duy nhất được chia sẻ. Điều này hứa hẹn một bước nhảy vọt về hiệu suất và khả năng đồng bộ hóa. 💥

1. Đa Luồng Thực Sự so với Web Workers Truyền Thống

Điểm khác biệt cốt lõi có thể được tóm tắt như sau:

| Tính năng | Web Workers Tiêu chuẩn | Luồng Bộ nhớ Chia sẻ của WebKit #249 | |---------------------|---------------------------------------------------------|-----------------------------------------------------------------| | Mô hình bộ nhớ | Vùng nhớ độc lập (không có đối tượng chia sẻ) | Vùng nhớ chia sẻ (các luồng truy cập cùng đối tượng) | | Chia sẻ dữ liệu | Structured Clone / Sao chép (chuyển đổi chậm) | Chia sẻ tham chiếu trực tiếp (không sao chép, tức thì) | | Phạm vi toàn cục| Các phạm vi toàn cục riêng biệt | Một Realm duy nhất được chia sẻ (globalThis, Array, Object.prototype, và biểu đồ module được chia sẻ) | | Định danh đối tượng| x instanceof Foo thất bại trên các đối tượng đã sao chép | x instanceof Foo vẫn đúng giữa các luồng | | API | postMessage | new Thread(fn, ...args) / Atomics / Lock / Condition |

2. Kiến Trúc Kỹ Thuật & Tầm Nhìn của Filip Pizlo

Việc triển khai này là sự hiện thực hóa trực tiếp từ nghiên cứu của Filip Pizlo năm 2017, "Concurrent JavaScript: It Can Work!", được công bố trên blog chính thức của WebKit. Các cơ chế kiến trúc cốt lõi bao gồm:

* Thực thi JIT song song (Không Khóa Toàn Cục): Các luồng JavaScript song song thực thi qua cả bốn cấp biên dịch JIT (LLInt, Baseline, DFG, FTL) mà không yêu cầu khóa trình thông dịch toàn cục (GIL). Điều này mở ra khả năng tận dụng tối đa các lõi CPU. * Bộ thu gom rác (GC) an toàn đồng thời: Các đối tượng được cấp phát trên một vùng nhớ chia sẻ, và bộ thu gom rác được thiết kế để theo dõi các tham chiếu trên nhiều luồng một cách đồng thời mà không gây ra xung đột. * Giới hạn luồng và hạn chế đối tượng: Để ngăn chặn các điều kiện tranh chấp (race conditions) hoặc truy cập đồng thời không an toàn, nhà phát triển có thể sử dụng Thread.restrict(obj) để "gắn" một đối tượng vào luồng hiện tại. Bất kỳ truy cập nào từ luồng khác sẽ kích hoạt lỗi ConcurrentAccessError. Đây là một cơ chế an toàn quan trọng để quản lý trạng thái chia sẻ. 🚧

3. Các API Đồng Bộ Hóa Mới

Để cho phép phối hợp an toàn giữa các luồng, PR này giới thiệu một số nguyên thủy đa luồng tiêu chuẩn trực tiếp vào runtime của JavaScript:

Lock (Khóa)

Một mutex lock không đệ quy. * lock.hold(() => { ... }): Chạy callback trong khi giữ khóa. * await lock.asyncHold(async () => { ... }): Giữ khóa bất đồng bộ, không chặn luồng chính.

Condition (Biến Điều Kiện)

Cho phép các luồng "đỗ" và chờ tín hiệu. * cond.wait(lock): Nhả khóa, đỗ luồng, và giành lại khóa khi được đánh thức. * cond.asyncWait(lock): Tương đương nhưng không chặn. * cond.notify(): Đánh thức một luồng đang đỗ. * cond.notifyAll(): Đánh thức tất cả các luồng đang đỗ.

ThreadLocal (Biến Cục Bộ Theo Luồng)

Cung cấp lưu trữ cục bộ theo luồng, nơi .value hoàn toàn độc nhất cho mỗi luồng.

Atomics Mở Rộng

Mở rộng Atomics không chỉ cho SharedArrayBuffer mà còn cho các thuộc tính đối tượng thông thường: * Atomics.load(obj, "k") * Atomics.store(obj, "k", val) * Atomics.add(obj, "k", val) * Atomics.compareExchange(obj, "k", expected, replacement) (sử dụng SameValueZero)

4. Cơ Chế Xử Lý Promise & Thao Tác Bất Đồng Bộ Giữa Các Luồng

Việc quản lý các thao tác bất đồng bộ trong môi trường đa luồng là cực kỳ phức tạp. PR này giải quyết vấn đề đó như sau:

* Thực thi phản ứng trên luồng giải quyết: Nếu Luồng A đăng ký .then() hoặc await trên một promise, callback của microtask sẽ chạy trên bất kỳ luồng nào thực sự giải quyết (resolve hoặc reject) promise đó. Điều này đảm bảo tính nhất quán. * Bảo toàn AsyncLocalStorage (ALS): Ngữ cảnh của ALS được ghi lại theo cấu trúc cho mỗi phản ứng tại thời điểm đăng ký. Khi callback được thực thi (ngay cả khi nó được di chuyển sang một luồng khác), nó vẫn quan sát đúng ngữ cảnh ALS ban đầu. * Phân tách hàng đợi Microtask: Mỗi luồng duy trì và xử lý hàng đợi microtask riêng của mình để ngăn chặn sự xen kẽ các tác vụ từ các luồng khác. 🔄

5. Tình Trạng Hiện Tại của Pull Request

Hiện tại, PR này vẫn đang trong giai đoạn thử nghiệm và phát triển (work-in-progress). JavaScript song song đã có thể thực thi và tất cả các bài kiểm tra trong bộ kiểm tra luồng đều vượt qua thành công. 🎉 Tuy nhiên, trước khi có thể được hợp nhất hoặc sẵn sàng cho sản xuất, nó yêu cầu: 1. Dọn dẹp Thread-Sanitizer (TSan) để giải quyết các điều kiện tranh chấp còn lại trong các nội bộ của engine C++. 2. Fuzzing (kiểm thử ngẫu nhiên) để đảm bảo an toàn tuyệt đối. 3. Đánh giá hiệu năng (benchmarking) vì một bài kiểm tra hiện đang vượt quá ngân sách thời gian.

PR này đóng vai trò là bằng chứng về khái niệm, chứng minh rằng JavaScript đa luồng bộ nhớ chia sẻ không chỉ khả thi mà còn có thể đạt được hiệu suất cao. Cộng đồng đang rất mong chờ những bước tiến tiếp theo! 🚀✨

Đã đọc hết tin tools-cli hiện có.