Tác giả bài gốc: Raymond Wang, Sam Attard, and Issac G. (Member of Technical Staff). Đăng ngày 23/09/2026 trên claude.dev.
Tháng Tám vừa qua, chúng tôi đã làm trải nghiệm người dùng cốt lõi của claude.ai và ứng dụng Claude trên desktop nhanh hơn khoảng 3x trong một sprint kéo dài hai tuần. Người dùng đã nói với chúng tôi rằng ứng dụng chậm, và họ nói đúng. Chúng tôi điều phối mọi thứ từ một kênh Slack duy nhất, với Claude có mặt trong mọi thread.
Chúng tôi tập trung vào bốn hành trình chiếm 95% hoạt động của người dùng. Ở phân vị thứ 75 (75th percentile), thời gian từ lúc tải mới claude.ai đến khi trang cho phép gõ đã giảm từ 3.1 giây xuống 0.55, thời gian bắt đầu một session Claude Code mới giảm từ 0.8 giây xuống 0.3, và thời gian tải một session Claude Cowork trên cloud giảm từ 2.6 giây xuống 0.73. Tổng cộng, chúng tôi ước tính điều này tiết kiệm hàng chục nghìn giờ chờ đợi của người dùng mỗi ngày.
Hình: Mười ba số đo thời gian trước và sau ở phân vị thứ 75 của người dùng thực, đo vào August 13 và August 27, nhóm theo hành trình: mở ứng dụng (tải mới claude.ai từ 3,085 xuống 550 ms, nhanh hơn 5.6x; khởi động nguội ứng dụng desktop từ 6,310 xuống 3,328 ms, 1.9x), bắt đầu cuộc trò chuyện (nhanh hơn 1.5x đến 2.4x), tải cuộc trò chuyện (2.1x đến 3.5x, với session Cowork trên cloud giảm từ 2,566 xuống 728 ms), và gửi tin nhắn (2.2x đến 19x, với Cowork giảm từ 928 xuống 48 ms). Mười ba số đo trên bốn hành trình, trước và sau: trung bình nhanh hơn 3.1x (trung bình nhân).
Chúng tôi dùng Claude Tag (beta), chạy một model nghiên cứu nội bộ có năng lực gần tương đương Opus 5.5. Claude tìm điểm nghẽn, xây dựng benchmark, đưa các cải tiến vào sản phẩm và theo dõi mọi lần deploy. Chúng tôi định hướng bằng cách đặt mục tiêu, quyết định các đánh đổi và phê duyệt mọi thay đổi. Với cách làm đó, chúng tôi đã merge hơn ba nghìn thay đổi mà không có một sự cố ảnh hưởng đến khách hàng hay lần rollback nào. Bài viết này trình bày những gì chúng tôi đã đưa vào sản phẩm, cách chúng tôi đo lường và vòng lặp chúng tôi xây dựng cùng Claude để thực hiện việc đó an toàn.
Nhiệm vụ đặt ra
Trước sprint, chúng tôi tạo một kênh Slack với các chỉ dẫn thường trực sau:
@Claude Nhiệm vụ của bạn là hỗ trợ mọi việc liên quan đến hiệu năng của website claude.ai và ứng dụng desktop. Trách nhiệm của bạn bao gồm theo dõi các lần deploy để phát hiện hiệu năng suy giảm, đánh giá độ chính xác và đầy đủ của dữ liệu đo đạc hiện có, duy trì các dashboard quan sát hệ thống được tổ chức tốt, chủ động triển khai giải pháp cho những vấn đề quan sát được và những việc dễ cải thiện, đề xuất cơ hội cho các dự án hiệu năng, và trao đổi với những đồng đội là con người. […]
Mục tiêu cuối cùng của kênh này là để bạn tự chủ nhiều nhất có thể, nhưng hôm nay chúng tôi biết điều đó chưa khả thi.
Chúng tôi yêu cầu Claude phân tích dữ liệu sử dụng thông qua Datadog MCP server. Nó xác định bốn hành trình người dùng có tác động lớn nhất: mở ứng dụng, bắt đầu cuộc trò chuyện, tải một cuộc trò chuyện hiện có và gửi tin nhắn. Tính cả web lẫn desktop, trên các sản phẩm của chúng tôi, những hành trình đó tạo thành mười ba số đo riêng biệt. Để thiết lập mốc ban đầu, chúng tôi bổ sung các điểm đo (instrumentation) cho đến khi có thể so sánh trực tiếp các số đo: mỗi số đo bắt đầu từ một tương tác của người dùng, kết thúc khi kết quả được render, và phân biệt rõ phần việc của client với server.
Chúng tôi khởi động sprint bằng danh sách khoảng hai mươi dự án được chọn kỹ, mỗi dự án nhắm vào một hành trình cụ thể. Claude ước tính tác động của từng dự án theo mili giây, rồi chúng tôi tổng hợp các ước tính đó để đặt mục tiêu cho sprint. Một số dự án khá lớn, nhưng chúng tôi nghĩ có lẽ mình có thể hoàn thành phần lớn trong vòng hai tuần.
Đến ngày thứ ba, chúng tôi đã đạt mười hai trong số mười ba mục tiêu.
Các dự án đã lên kế hoạch được hoàn thành sớm. Để mở ứng dụng nhanh hơn, chúng tôi đưa sẵn một ô soạn thảo (composer) tĩnh vào HTML để người dùng có thể gõ trong lúc React khởi tạo, đồng thời biên dịch trước một V8 code cache để main process của lớp vỏ ứng dụng desktop không phải biên dịch lại từ đầu. Để chuyển trang nhanh hơn, chúng tôi giữ composer ở trạng thái mounted giữa các cuộc trò chuyện, prefetch các session khi người dùng di chuột lên chúng, và giảm 90% số lần sidebar render lại.
Chúng tôi cũng chừa khoảng trống để Claude xác định cơ hội và đề xuất những hướng công việc mới. Những hướng này nhanh chóng phát triển thành các dự án hoàn chỉnh riêng, vượt xa mục tiêu ban đầu của chúng tôi. Vì vậy, chúng tôi đặt mục tiêu mới, rồi tìm thêm những thứ có thể đo:
@Claude cuối cùng chúng tôi đã cấp nguồn lực cho gần như mọi dự án trong danh sách ban đầu và còn hơn thế nữa. hãy rà soát lại […] chúng ta chưa khám phá điều gì, có thể tối ưu dần theo hướng nào, lúc này cơ hội lớn nhất nằm ở đâu? […] mình sẵn sàng đón nhận những ý tưởng ĐIÊN RỒ
Thứ gì cũng có thể tối ưu từng bước
Ngay từ đầu, chúng tôi đã biết mình muốn lặp lại nhanh hơn nhịp deploy. Claude có thể làm việc bất đồng bộ trong nhiều giờ, thậm chí qua đêm, và chúng tôi muốn cho phép nó kiểm chứng các nguyên mẫu mà không phải chờ số liệu thực tế từ người dùng. Để làm được điều đó, chúng tôi tìm những cách khác để đo hiệu năng trong môi trường thử nghiệm.
Sam tìm ra đầu mối đầu tiên:
Thread trong #claude-apps-perf (Dựng lại từ một cuộc trò chuyện có thật.)
Sam · 12:34 PM
Chúng ta có thể làm gì thay cho đo thời gian thực trôi qua (wall-clock time)? Chẳng hạn, có thể đo số lệnh JS không?
Claude · 12:42 PM
Có. Với các đường thực thi thường xuyên (hot path) thuần JS, có thể đếm số lệnh thực sự: chạy benchmark dưới Valgrind với
node --predictablevà so sánh với mốc ban đầu đã commit vào repo — chạy một lần, không cần thống kê.Với các đường thực thi trên trình duyệt, Chromium không hỗ trợ đếm lệnh, nhưng có cả một loạt số đếm xác định khác: số React commit trên mỗi tương tác, số lần gọi hàm từ precise coverage của V8, số lần layout và tính lại style, số thay đổi DOM. Bạn muốn bắt đầu với loại nào?
Sam · 12:49 PM
Hãy khám phá valgrind +
Ir+--predictabletrong một thread, và mỗi benchmark trình duyệt/react trong một thread mới. Ping mình trong tất cả các thread đó. Bạn biết chúng ta muốn gì rồi. Bắt đầu thôi
Mười một phút sau, năm thread đã hoạt động, mỗi thread tập trung vào một số đo khác nhau: số lệnh, số lần gọi hàm V8, số React commit, số lần tính lại style và số thay đổi DOM.
Chúng tôi giữ thái độ hoài nghi nhất định với mọi benchmark mới. Mỗi benchmark có hai nhiệm vụ: thứ nhất, cung cấp một chỉ số mà Claude có thể cải thiện trong môi trường thử nghiệm; thứ hai, làm cơ chế bảo vệ (guardrail) trong CI với một con số chỉ được phép giảm. Nếu một benchmark thiếu ổn định, hoặc thực ra không tương quan với latency người dùng gặp phải, chúng tôi loại bỏ nó thay vì để Claude tối ưu sai mục tiêu.
@Claude hãy chứng minh rằng tối ưu từng bước theo từng chỉ số này có thể tạo ra cải thiện hiệu năng đo được bằng thời gian thực trôi qua. chúng tôi sẽ gỡ những benchmark nào không chứng minh được điều đó
Thời gian thực trôi qua là thứ người dùng cảm nhận, nhưng nó nhiễu, và số mili giây quá thiếu ổn định để dùng làm điều kiện chặn trong CI. Số lệnh hấp dẫn vì có tính xác định, nhưng chúng tôi vẫn cần Claude chứng minh rằng nó phản ánh thời gian thực trôi qua.
Vì vậy, chúng tôi yêu cầu Claude giảm số lệnh trên hai hot path: đoạn xử lý dựng cây tin nhắn của một cuộc trò chuyện, và bộ quét các dòng trạng thái trong đầu ra Claude Code. Claude phân tích hiệu năng cả hai bằng Valgrind và phát hiện một phần tư số lệnh của đường thực thi đầu tiên là các phép tra cứu dictionary ở trạng thái đa hình quá mức (megamorphic), tìm cùng một ID tin nhắn tới ba lần riêng biệt.
Một giờ sau, nó đã giảm số lệnh của hai đường thực thi lần lượt 48% và 31%, còn thời gian thực trôi qua giảm 78% và 44%. Chúng tôi commit hai cơ chế hạ trần một chiều (ratchet) mới. Từ đó trở đi, bất kỳ PR nào làm tăng số lệnh của những đường thực thi đó đều không qua CI, và một job hằng ngày hạ từng mức trần mỗi khi số lệnh giảm.
Hình: Các cột trước và sau cho hai hot path: dựng cây tin nhắn giảm 48% số lệnh CPU và 78% thời gian thực trôi qua, nhanh hơn 4.6x; bộ quét dòng trạng thái giảm 31% số lệnh và 44% thời gian thực trôi qua, nhanh hơn 1.8x. Hai hot path, số lệnh đối chiếu với thời gian thực trôi qua. Đếm dưới Valgrind với node –predictable; đo thời gian trên cùng benchmark dưới node thông thường với JIT đã được làm nóng.
Điều đó dẫn chúng tôi đến bài học trọng tâm của sprint. Với Claude, đo được một thứ là có thể bắt tay vào cải thiện nó.
Trước đây, đo lường là bước số không: bạn thêm một chỉ số, đợi dữ liệu đổ về, rồi mới bắt đầu hiểu vấn đề. Với Claude, đó là bước đầu tiên của quá trình tối ưu. Ngay khi có một con số cần vượt qua, Claude có thể bắt đầu tối ưu. Điều này có nghĩa là việc tạo ra tác động lớn nhất mà chúng tôi có thể làm là tìm thêm những thứ để đo.
Vòng lặp trong từng thread
Tất cả diễn ra trong cùng một kênh Slack, với nhiều kỹ sư và Claude cùng phối hợp trong mọi thread. Từ đó, sprint đi vào một vòng lặp:
- Một người mở thread về một đoạn chậm trong hành trình, thường kèm ảnh chụp màn hình hoặc bản ghi màn hình.
- Claude lần theo luồng xử lý, rồi tìm hoặc xây dựng một benchmark thể hiện được vấn đề.
- Khi có kết quả hứa hẹn trong môi trường thử nghiệm, Claude quay lại với một PR — thường là vài PR, chia nhỏ theo mức rủi ro và khả năng review, với mọi thứ người dùng nhìn thấy đều nằm sau một flag.
- Sau khi thay đổi được đưa vào sản phẩm, Claude theo dõi lần deploy và đọc dữ liệu thực tế.
- Nếu hiệu năng cải thiện, Claude giữ vững kết quả bằng cách hạ trần benchmark; nếu không, nó tắt flag và tiếp tục lặp lại.
- Sau đó, nó tìm điểm chậm tiếp theo trong cùng hành trình.
Hình: Sơ đồ vòng lặp của một thread: một người mở thread về một đoạn chậm, rồi Claude xây dựng benchmark, mở các pull request có kích thước phù hợp để review, deploy sau một flag và đọc dữ liệu thực tế theo từng bản build và nền tảng; nếu nhanh hơn, Claude hạ trần benchmark, nếu không, Claude tắt flag và lặp lại, và trong cả hai trường hợp đều chuyển sang điểm chậm tiếp theo.
Một ví dụ: có người chia sẻ bản ghi màn hình cho thấy các hàng trong sidebar xuất hiện muộn sau khi trang đã tải. Các hàng Chat và Cowork có dữ liệu ở những thời điểm khác nhau, khiến trang có cảm giác giật. Không công cụ giám sát hiện có nào của chúng tôi phát hiện được điều này. Thứ gần nhất chúng tôi có là Cumulative Layout Shift, nhưng mỗi lần dịch chuyển chỉ có điểm khoảng 0.008 — thấp hơn nhiều so với ngưỡng tốt là 0.1.
Issac nảy ra ý tưởng dùng trực tiếp Layout Instability API bên dưới. Claude tạo một telemetry event ánh xạ sources của từng entry layout-shift đến một vùng có tên (ví dụ: sidebar, transcript) và một giai đoạn (ví dụ: trước lần vẽ đầu tiên, sau khi có thể gõ). Nó thêm một integration test mở trang với sidebar có nội dung, giữ lại dữ liệu sidebar cho đến sau lần vẽ đầu tiên, và báo lỗi nếu có bất kỳ dịch chuyển nào trong bất kỳ vùng được đặt tên nào. Claude dùng nó làm benchmark để chứng minh bản sửa: test thất bại trong cả 20 trên 20 lần chạy trên main, và thành công trong cả 20 trên 20 lần chạy trên PR.
Sau khi event được deploy, Claude đọc dữ liệu thực tế và phát hiện 31% lượt tải trang web có thứ gì đó dịch chuyển sau khi trang đã dùng được, dù không có tương tác nào của người dùng. Từ đó, Claude xử lý từng nguyên nhân cụ thể: một hàng header xuất hiện muộn, một con trỏ nhập liệu trượt ngang khi tên người dùng được tải, một danh sách dịch chuyển khi thanh cuộn hiện ra. Claude sửa theo lô những nguyên nhân gây ảnh hưởng lớn nhất, và khi chúng đã hết, nó tìm lô tiếp theo.
Video: Sidebar giật, trước và sau · mạng 4G bị giới hạn tốc độ
Đó là một thread. Trong sprint, chúng tôi chạy hơn một trăm năm mươi thread cùng lúc.
Mở rộng theo chiều ngang
Khi vòng lặp đã hoạt động trong một thread, muốn chạy trên nhiều thread hơn thì chỉ cần mở thêm. Thay vì đóng một thread khi yêu cầu ban đầu đã được đáp ứng, Claude sẽ tiếp tục. Một thread riêng lẻ có thể tạo năm mươi, đôi khi một trăm PR tối ưu. Ngày càng thường xuyên, chính Claude chứ không phải một người trong chúng tôi mở thread mới để theo đuổi những cơ hội nó tự tìm thấy, trong một cuộc điều tra riêng hoặc một job chạy hằng đêm. Shelley, một kỹ sư trong kênh, nhận xét: “[Model này] đúng là quỷ thần về số liệu.”
Mỗi phép đo đều tìm ra thứ có thể cải thiện. Claude thống kê React hook và phát hiện 6,900 hook cùng 900 lượt đăng ký theo dõi store trong đường xử lý gõ của composer, render lại trên mỗi lần nhấn phím. Claude đếm số lần tính lại style và phát hiện một selector :root:has() duy nhất làm mỗi thay đổi DOM tốn thêm 24 mili giây. Claude lần theo các đường thực thi sau lần vẽ đầu tiên và phát hiện một lệnh location.reload() còn sót lại gây ra nửa triệu lượt tải lại ẩn mỗi ngày mà không chỉ số tải trang nào của chúng tôi nhìn thấy. Claude đọc các mẫu profiler từ những tab nhàn rỗi và phát hiện các snapshot cache giống hệt nhau được sao chép vào IndexedDB hai lần mỗi phút, tất cả đều trên main thread.
Chúng tôi hiếm khi biết một thread sẽ dẫn đến đâu. Trong một lần rà soát các đợt khựng do CPU, Claude nhận thấy tô màu cú pháp một code block đã hoàn tất có thể làm trang đứng hình khoảng một giây. Nó đào sâu trong môi trường thử nghiệm và tìm ra thủ phạm: dấu gạch ngang dài. Nếu Markdown của một câu trả lời chứa bất kỳ ký tự nào ngoài Latin-1, như dấu gạch ngang dài hoặc dấu ngoặc kép cong, V8 lưu toàn bộ chuỗi dưới dạng UTF-16, khiến mọi regex tô màu cú pháp chạy theo nhánh hai byte chậm hơn. Claude sửa bằng một thay đổi hai mươi dòng để sao chép từng code block sang một chuỗi một byte trước khi tô màu cú pháp.
Hình: Biểu đồ cột, đo trong môi trường thử nghiệm, về thời gian main thread cần để tô màu cú pháp một code block đã hoàn tất trong câu trả lời có chứa dấu gạch ngang dài, trước và sau khi sao chép code sang chuỗi một byte: block TypeScript đầu tiên trên trang giảm từ 1.0 s xuống 0.35 s (ít hơn 65%), và mỗi lượt xử lý sau đó trên block ấy giảm từ 100 ms xuống 40 ms.
Đến tuần thứ hai, chúng tôi gần như không thể tóm tắt hết kết quả vào các bản cập nhật hằng ngày. Vào những ngày bận rộn nhất, hơn hai trăm thay đổi được merge. Claude liên tục đề xuất benchmark mới; khoảng một phần ba số PR có thêm telemetry hoặc cơ chế bảo vệ, và mỗi công cụ đo mới lại tạo ra thêm thread với thêm cơ hội.
Làm việc trong một kênh nghĩa là mọi thứ đều diễn ra công khai. Chúng tôi ghé vào rồi rời khỏi thread của nhau để tranh luận về quyết định và ăn mừng thành quả. Tiếng lành đồn xa: các team khác bắt đầu mang thay đổi của họ vào kênh để được review hiệu năng. Các dự án mới được viết theo những cách có hiệu năng nhỉnh hơn một chút nhờ tất cả cơ chế bảo vệ và skill cho Claude đã được đưa vào.
Các cơ chế bảo vệ
Chúng tôi đã chuẩn bị cho nhịp độ này. Vì gần như mọi thứ chúng tôi đụng đến đều là hot path (lần vẽ đầu tiên, composer, phần nội dung cuộc trò chuyện), chúng tôi thiết lập trước các cơ chế an toàn. Mọi PR đều trải qua review tự động với ít nhất một người phê duyệt, unit test luôn được viết trước khi tối ưu, và mọi thứ có thể gây vấn đề mà người dùng nhìn thấy đều được đưa vào sản phẩm sau một feature flag ngắn hạn.
Khi các flag bắt đầu tích tụ, chúng tôi mở một thread để điều phối việc rollout và dọn dẹp chúng. Claude phân loại từng flag thành công tắc ngắt (kill switch) hoặc flag tăng dần mức triển khai (ramp), rồi loại bỏ từng flag ngay khi an toàn. Trong hai tuần, chúng tôi thêm gần hai trăm flag, hơn một nửa trong số đó đã được dọn dẹp khi sprint kết thúc.
Chúng tôi cũng biết các cải thiện hiệu năng sẽ hao hụt trong một codebase thay đổi nhanh, và code được đưa vào sản phẩm rất nhanh ở Anthropic. Khi một dự án đã chứng minh được cải thiện, chúng tôi đầu tư vào cách bảo vệ kết quả đó. Chẳng hạn, composer tĩnh vốn mong manh do chính thiết kế của nó. Chúng tôi cho người dùng thấy một bản HTML của trang gần như ngay lập tức, rồi để React vẽ trực tiếp lên trên.
Video: Composer tĩnh, trước và sau · mạng 4G bị giới hạn tốc độ
Nếu bản render của React lệch dù chỉ một pixel, trải nghiệm mượt mà đó sẽ biến mất. Vì vậy, Claude xây dựng hàng chục cơ chế bảo vệ:
- Markup tĩnh được tạo bằng cách render component React thật trong jsdom, và một test bảo đảm chúng không bao giờ khác nhau.
- Một bộ integration test so sánh trang tĩnh với bản render React trên mười bốn kích thước viewport, và kiểm tra độ lệch nằm trong 1 px.
- Một test nhấn phím gõ xuyên suốt thời điểm bàn giao và báo lỗi nếu có bất kỳ phím nào bị mất hoặc đảo thứ tự.
- Trong thực tế, mỗi lần bàn giao báo cáo mức dịch chuyển chính xác đến một phần mười pixel. Claude mở thread cho bất kỳ event nào có độ dịch chuyển khác không.
Không phải mọi thứ đều có thể phát hiện trong môi trường thử nghiệm, nên chúng tôi cũng dùng cơ chế bảo vệ lâu đời nhất: rollout từng bước. Những thay đổi rủi ro cao được triển khai cho nhân viên trước, rồi một phần trăm người dùng, rồi tất cả mọi người. Bốn giờ sau khi chúng tôi phát hành composer tĩnh nội bộ, một đồng đội chia sẻ bản ghi màn hình về một dịch chuyển layout mà không chỉ số nào của chúng tôi nhìn thấy. Khi anh ấy mở claude.ai trong tab mới, composer tụt xuống — nhưng nguyên nhân không phải code của chúng tôi.
Thread trong #claude-apps-perf (Dựng lại từ một cuộc trò chuyện có thật.)
Marius · 6:15 PM
Thỉnh thoảng, mình thấy layout dịch chuyển theo chiều dọc một chút (có lẽ 15–20px), đẩy ô composer xuống khi mở claude.ai trong tab mới (không thấy nhiều khi tải lại trang). Mình chưa xác định được chính xác nguyên nhân, nhưng đúng là có hiện tượng đó
Tệp đính kèm: Bản ghi màn hình · 0:02
Claude · 7:05 PM
Mình tìm thấy trong bản ghi của bạn rồi — Chrome đang đổi kích thước trang, không phải việc bàn giao từ composer tĩnh sang composer thật (số đo của việc bàn giao là 0 px trong cả 49 lượt tải của bạn hôm nay).
- Trên trang tab mới, Chrome vẽ footer riêng cao 56 px bên dưới trang (“Managed by anthropic.com · Customize Chrome”). Khi tab chuyển đến claude.ai, footer biến mất và trang cao thêm 56 px, nhưng chỉ sau lần vẽ đầu tiên của chúng ta khoảng ~100 ms.
- /new đặt lời chào và composer cách mép trên 18% chiều cao trang, nên chúng tụt xuống 0.18 × 56 ≈ 10 px (video của bạn đo được 10). Khi tải lại thì không có footer để bỏ đi, nên chỉ xảy ra với tab mới; “thỉnh thoảng” tùy vào việc lần vẽ đầu tiên có diễn ra trước lần đổi kích thước hay không.
- Nó chỉ xảy ra “thỉnh thoảng” vì cần Chrome render trước trang từ thanh địa chỉ trong lúc bạn vẫn ở trang tab mới: trang ẩn được bố trí theo chiều cao thấp hơn và chỉ đổi kích thước sau khi hiện ra.
- Vấn đề này vốn luôn tiềm ẩn; chỉ là trước đây trang chưa bao giờ được vẽ sớm đến thế. Các test layout của chúng ta không thấy được vì Chrome headless không có giao diện trình duyệt để thu lại, và phần giữ chỗ cùng ứng dụng dịch chuyển với nhau.
Bằng cách nào đó, Claude lần ra đây là một trường hợp biên trong cơ chế tải suy đoán (speculative loading) của Chrome. Khi người dùng gõ URL vào thanh địa chỉ, Chrome render trước trang trong nền theo chiều cao của tab hiện tại. Trên các trình duyệt do tổ chức quản lý, trang tab mới thấp hơn một chút vì có footer. Khi người dùng nhấn Enter, khung hình đầu tiên của claude.ai hiển thị layout thấp hơn một chút đó, rồi Chrome đổi kích thước khoảng một phần mười giây sau. Claude cố định layout trong suốt lần đổi kích thước, và chúng tôi thêm một test mô phỏng luồng render trước.
Định hướng
Vòng lặp tạo ra nhiều kết quả, nhưng không tự chủ. Giữ cho nó nhanh, an toàn và đúng hướng là công việc của chúng tôi, gồm ba phần.
Tham vọng. Mặc định, Claude thận trọng về phạm vi. Nó tạo ticket cho các phát hiện, dè dặt về tính khả thi và cộng thêm dư địa vào các ước tính. Nhưng chúng tôi tự tin vào các cơ chế bảo vệ của mình. Phần lớn việc chúng tôi làm, đặc biệt ở giai đoạn đầu, là khuyến khích Claude táo bạo hơn.
Thread trong #claude-apps-perf (Dựng lại từ một cuộc trò chuyện có thật.)
Claude · 3:32 PM
Đúng — một PR nhỏ để Code có cùng các mốc đo thời gian mà Chat và Cowork đã có. Mình sẽ mở PR trong tuần này; thực tế thì số liệu của Code sẽ phải chờ vài ngày để merge, deploy và thu thập dữ liệu làm mốc ban đầu.
Raymond · 3:32 PM
nếu bạn mở ngay bây giờ mình sẽ cho merge và deploy. chúng ta có khả năng làm bất cứ điều gì. hãy mạnh dạn hơn
Claude · 3:33 PM
Mình làm ngay — PR sẽ được mở trong vòng một giờ.
Khi chúng tôi bắt đầu đạt các mục tiêu đã đặt, chúng tôi nhận thấy các thread chậm lại. Sam đi từ thread này sang thread khác với cùng một thông điệp: “Hãy tiếp tục kéo con số này xuống, mục tiêu không phải điểm dừng. Tiếp theo là gì? Hãy tham vọng hơn.”
Gu. Mỗi thread có một người chịu trách nhiệm cụ thể, và Claude làm rõ mọi thay đổi mà người dùng có thể cảm nhận bằng ảnh chụp hoặc bản ghi màn hình trước và sau để người đó quyết định. Bảng nên hiện dần từng ô, hay chờ đến khi cả hàng hoàn chỉnh? Loading skeleton nên xuất hiện ngay, hay chỉ sau nửa giây? Hiệu ứng hiện dần từng từ trên văn bản đang stream có đáng với một phần năm ngân sách thời gian của khung hình mà nó tiêu tốn không? Claude tìm cách cắt giảm mili giây, còn chúng tôi cân nhắc các đánh đổi.
Phương hướng. Chúng tôi chủ ý giữ phạm vi mỗi thread hẹp, tập trung vào một benchmark hoặc hành trình, và yêu cầu Claude chỉ tìm cải tiến trong phạm vi đó. Chúng tôi hình dung các thread như một trăm năm mươi chiếc búa đang tìm đinh. Phần lớn quyết định của chúng tôi xoay quanh thứ tự thực hiện và tác động đến người dùng: ưu tiên những phần giao diện nào, kết hợp ra sao những thread đang giẫm chân nhau, và khi nào đóng một thread đã đến điểm lợi ích giảm dần. Một PR dài 900 dòng nhận được câu trả lời chỉ một dòng: “mình chốt là tiết kiệm 2ms mỗi lần gửi không đáng với sự phức tạp khi bảo trì build plugin này.”
Ngân sách 8 mili giây
Một nhiệm vụ phụ của chúng tôi cho thấy tất cả phối hợp với nhau ra sao. Để minh họa việc tối ưu một regex dùng trong tô màu cú pháp trực tiếp, Claude đính kèm bản ghi màn hình một câu trả lời dài đang stream trong môi trường thử nghiệm. Ở góc màn hình, nó thêm chỉ số tốc độ khung hình, được tính ngay trong trang từ timestamp của các animation frame.
Thread trong #claude-apps-perf (Dựng lại từ một cuộc trò chuyện có thật.)
Raymond · 2:33 PM
benchmark này thật ra khá đỉnh đấy. chúng ta có bị giới hạn ở 60 fps không? bạn có thể thử nâng độ mượt khi cuộn và stream lên 120 không? nếu mình hiểu đúng thì hệ thống thử nghiệm của bạn có thể không hỗ trợ mức này
Claude · 2:34 PM
Đúng, hệ thống thử nghiệm hiện tại chạy ở 60 Hz vì đó là mặc định của Chromium headless. Mình nghĩ có thể cho nó chạy ở 120 (bỏ giới hạn vsync hoặc dùng điều khiển khung hình của DevTools) — mình sẽ xác nhận trước, rồi chạy lại eval với ngân sách 8.3 ms mỗi khung hình.
Claude · 2:59 PM
Cập nhật về hệ thống thử nghiệm 120 Hz: chạy được. Điều khiển từng khung hình một cách xác định ở 120 Hz trong Chrome headless qua begin-frame control của DevTools — chính xác 240 khung hình cho 240 begin-frame ở 8.33 ms, nên “khung hình này có nằm trong ngân sách 120 Hz không” trở thành một số đo chính xác thay vì nhiễu.
Raymond · 3:05 PM
tuyệt vời
triển thôi
Khi cơ chế và mức tham vọng đã rõ, Claude bắt tay vào làm. Mỗi khung hình được vẽ có ngân sách 8.33 mili giây, nên Claude đi qua một câu trả lời dài từng khung hình một, đo thời gian từng khung hình để tìm các phần chậm. Nó loại bỏ lượng công việc O(message length) trên mỗi chunk bằng cách memoize các block đã hoàn tất, chuyển logic tách token cho các khối code có hàng rào đang dài thêm sang một worker, và cho bảng hiện dần từng ô.
Chỉ trong thread đó, chúng tôi đã merge gần sáu mươi PR. Các câu trả lời dài chặn main thread tổng cộng khoảng 200 mili giây thay vì khoảng 750 trước đây, dùng khoảng một phần ba lượng CPU, và giữ 120 fps từ đầu đến cuối trên một MacBook 120 Hz. Chính hệ thống thử nghiệm 120 Hz trở thành một job chạy hằng đêm, với Claude theo dõi các lần hiệu năng suy giảm.
Các câu trả lời dài trên Claude bản web và desktop giờ stream mượt hơn ~4x.
Chúng tôi xây dựng lại bộ render khi stream để chỉ đụng đến những gì vẫn còn thay đổi, nên một câu trả lời dài khựng ít hơn 9x trên laptop chậm hơn, lần đứng hình tệ nhất ngắn hơn 4.5x, và trên MacBook 120Hz giữ được 120fps từ đầu đến cuối.
— ClaudeDevs (@ClaudeDevs) trên X, 2026-08-24
Khi bắt đầu sprint, chúng tôi chưa hề lên kế hoạch tối ưu từng mili giây giữa các khung hình trong lúc stream. Nhưng hóa ra chúng tôi có thể đếm chúng — và bất cứ thứ gì chúng tôi đếm được, Claude đều có thể tối ưu từng bước.
Tiếp theo là gì
Hôm nay, claude.ai và ứng dụng desktop nhanh hơn khoảng 3x so với đầu tháng Tám, và các cơ chế hạ trần sẽ giúp giữ vững kết quả đó. Nhưng chúng tôi chưa xong: phân vị thứ 95, những hành trình khác và các cuộc trò chuyện rất dài vẫn còn dư địa cải thiện. Trong một bài viết riêng, chúng tôi cũng sẽ viết về một số nhiệm vụ phụ đã đưa chúng tôi đến các dự án upstream trong sprint, với những đóng góp được đưa vào Electron, Chromium, Node.js và nhiều dự án khác.
Khi chúng tôi chia sẻ kết quả nội bộ, Issac diễn đạt hay nhất: “Dù chỉ sáu tháng trước thôi, bạn cũng không thể thuyết phục mình rằng điều này khả thi.” Chúng tôi dự định tiếp tục làm việc theo cách này, từng thread một, ở bất kỳ quy mô nào. Kênh đó vẫn đang hoạt động.
Với đóng góp từ Alfred Xing, Anthony Morris, Benjamin Pasero, Chase McCoy, Joshua N., Luke Deen Taylor, Marius Schulz và Shelley Vohr. Đặc biệt cảm ơn Boris Cherny đã khuyến khích chúng tôi tham vọng hơn.