Vì sao vẫn nhanh trên một chiếc laptop bình thường.
Màn hình giao dịch rất nặng: lịch sử dài, tick không ngừng, nhiều biểu đồ trên một trang. TradeCanvas chỉ làm đúng phần việc mỗi khung hình cần, trên luồng chính, không có code của bên thứ ba. Trang này cho thấy cách làm, và những chỗ vẫn đang được cải thiện.
Đang phát triển: engine đã đủ nhanh để dùng thật, nhưng chưa nhanh như nó sẽ đạt được. Phần cuối liệt kê những việc chúng tôi biết còn phải làm.
Gói nhỏ, phụ thuộc một chiều
Mỗi gói chỉ phụ thuộc vào các gói bên dưới. Không có code nào ngoài TradeCanvas chạy trong trang của bạn: các component framework nhận React, Vue hoặc Svelte làm peer, còn bộ vẽ WebGL là một chunk riêng, chỉ tải khi có biểu đồ cần đến.
0 thư viện bên thứ ba khi chạy
Đường đi của một tick
Một mức giá từ feed của bạn lên đến màn hình trong một khung hình. Mỗi tầng chỉ xử lý phần đã thay đổi.
- 1Feed của bạn
DataAdapterWebSocket, REST, một công ty chứng khoán: bất cứ thứ gì có lịch sử và luồng dữ liệu. - 2Quản lý luồng
StreamManagerNạp lịch sử trước rồi mới chạy trực tiếp. Phản hồi của yêu cầu cũ bị bỏ; feed im lặng bị phát hiện trong vòng 30 giây. - 3Gom tick
TickAggregatorTick vào một bộ đệm vòng 1.000 phần tử và được gộp vào nến của khung thời gian. - 4Chỉ báo
IndicatorEngineTính lại từ nến cuối, không phải từ đầu chuỗi. - 5Viewport
ViewportChỉ duyệt các nến đang hiện; thang giá chỉ lấy từ chúng. - 6Vòng vẽ
RenderLoopBao nhiêu tick đến đi nữa, cảnh cũng chỉ vẽ tối đa một lần mỗi khung hình. - 7Canvas 2D hoặc WebGL
RenderEngineHai canvas, thêm một canvas GPU bên dưới khi bật WebGL.
Một tick chỉ tốn một nến, không phải cả lịch sử
Khi tick làm thay đổi nến cuối, mỗi chỉ báo tính tiếp từ nến đó (và vài nến trước mà công thức cần nhìn lại) thay vì tính lại cả chuỗi. Nếu các nến nó nhớ không còn khớp, nó quay về tính lại toàn bộ, nên không bao giờ bỏ sót một lần sửa dữ liệu.
Khoảng 20 chỉ báo có hàm cập nhật tăng dần riêng, và 31 chỉ báo khác dựng trên một lớp nền tính tiếp từng điểm. Chỉ báo đọc đường của chỉ báo khác cũng tính tiếp được.
Khi thu nhỏ: mỗi pixel một cột
Khi nến hẹp hơn một pixel, vẽ từng cây là phí công mà mắt không thấy. Nến, thanh OHLC, high-low và khối lượng được vẽ thành mỗi pixel một cột, với giá mở đầu tiên, giá cao nhất, giá thấp nhất và giá đóng cuối cùng của các nến bên dưới. Đường và vùng giữ khoảng hai điểm mỗi pixel (LTTB); đường và dải chỉ báo vẽ một đoạn cho mỗi cột pixel.
- nến đang hiện
- 313
- nến mỗi pixel
- 0,39
- hình được vẽ
- 313
Một nến không bao giờ hẹp hơn một phần tư pixel CSS, nên biểu đồ chứa một triệu nến khi thu nhỏ hết cỡ chỉ hiện tối đa khoảng bốn nến mỗi pixel: khoảng 6.400 nến trên biểu đồ rộng 1.600 px. Bài đo một triệu nến đo việc kéo qua phần còn lại.
Hai canvas, nên rê chuột gần như không tốn gì
Cảnh chính (lưới, chuỗi giá, chỉ báo, hình vẽ, lệnh) nằm trên một canvas; đường chữ thập, chú giải, nhãn trục và đồng hồ đếm ngược nằm trên một canvas mỏng phía trên. Rê chuột chỉ vẽ lại canvas trên cùng. Dữ liệu mới vẽ lại cảnh chính một lần, ở khung hình kế tiếp.
Mỗi canvas toàn kích thước khiến trình duyệt phải trộn thêm một lớp mỗi khung hình, nên engine giữ số canvas ít nhất: canvas phụ cho phần chỉ vẽ được bằng 2D chỉ tồn tại khi có thứ cần đến nó.
WebGL bằng cách ghi lại, không phải viết lại
Biểu đồ vẽ bằng các lệnh Canvas 2D. Khi bật WebGL, các lệnh đó đi qua một bộ ghi, biến path, fill và stroke thành lệnh GPU theo điểm ảnh thiết bị. Thứ gì GPU không vẽ y hệt được thì ở lại Canvas 2D, đúng thứ tự, nên hình ảnh như nhau dù vẽ bằng cách nào.
- path, fill và stroke
- nến, khối lượng và lưới vẽ theo instancing
- chuỗi giá trong một Float32Array, sáu số mỗi nến; một tick chỉ ghi lại phần đuôi
- chữ
- ảnh và pattern
- bóng đổ, filter, vùng cắt lạ
- mọi bước sau bước đầu tiên GPU không nhận
renderer: 'auto'xin trình duyệt một context không bị cảnh báo hiệu năng lớn, nên máy nào chạy WebGL bằng phần mềm sẽ giữ Canvas 2D.- Tối đa 8 biểu đồ trên một trang giữ context WebGL (
setMaxWebGLCharts); các biểu đồ còn lại xếp hàng chờ và vẽ bằng Canvas 2D. - Nếu GPU làm mất context, biểu đồ tiếp tục bằng Canvas 2D và dựng lại trên WebGL khi context quay về.
- Nến được làm tròn về đúng điểm ảnh thiết bị theo cùng một quy tắc trong shader và trên CPU, nên cả hai bộ vẽ đặt nến lên cùng các điểm ảnh.
Làm cho máy yếu
- Mặc định Canvas 2DWebGL là tuỳ chọn cho đến khi được đo trên nhiều thiết bị hơn. Trên card tích hợp với tỉ lệ điểm ảnh cao, nút thắt là khâu ghép lớp của trình duyệt chứ không phải khâu vẽ.
- Mỗi khung hình một lần đổi kích thướcCác sự kiện đổi kích thước được gộp lại mỗi khung hình một lần, và kích thước không đổi thì không làm gì.
- Lịch sử theo trangNến cũ hơn được tải 500 nến một lần khi bạn kéo về quá khứ, mỗi lần một yêu cầu, và giãn thời gian thử lại sau khi lỗi.
- Không chớp màn hình tảiLớp phủ đang tải đợi 200 ms, nên đổi mã nhanh thì không bị chớp.
- Nhẹ để tải vềBiểu đồ không giao diện nặng 176 KB sau gzip, widget đầy đủ 315 KB, bộ vẽ WebGL thêm 18 KB khi dùng.
- Bảng giá nhảy tại chỗBảng giá bo-grid gộp tick thành một lần cập nhật mỗi khung hình và chỉ vẽ lại những ô đã đổi.