Vẽ vời dăm ba cái lộ trình lèo tèo lên Google Maps thì dễ như ăn kẹo (trivial). Nhưng bắt phải vẽ cùng lúc (simultaneously) 100,000 cái lộ trình lịch sử của các chuyến xe, nhồi thêm đống ma trận Điểm xuất phát-Đích đến (Origin-Destination matrices), lại còn kẹp thêm ba cái hàng rào ảo H3 (dynamic H3 geofences) biến thiên liên tục thì sao? Lúc đó, bạn buộc phải quăng gánh nặng tính toán từ cái CPU còm cõi của trình duyệt (browser’s CPU) sang cho con GPU gánh vác nhờ vào phép thuật WebGL.
Answer-first: Cấm tuyệt đối (Do not use) việc xài Mapbox GL JS gốc rễ (native) để hì hục render mấy cái mỏ dữ liệu siêu to khổng lồ và biến thiên liên tục (massive, dynamic datasets). Việc đâm đầu đi chỉnh sửa DOM hoặc mấy cái nguồn dữ liệu gốc của Mapbox (standard Mapbox sources) tới hàng ngàn lần mỗi giây sẽ tát cho cái trình duyệt đơ cứng ngắc. Cái trò chuẩn chỉ trong ngành (industry standard) là phải cặp bài trùng deck.gl kẹp với MapboxOverlay. Vị cứu tinh này trao quyền cho Deck.gl quăng thẳng (render directly) dữ liệu thô vào mặt GPU mà vẫn đảm bảo ăn khớp nhịp nhàng hoàn hảo (perfectly synchronizing) với cái camera di chuyển của Mapbox.
1. Mấy Cái Bẫy GeoJSON và Đường Đa Tuyến (Polyline Traps)
Khi cái API Golang của bạn ói ra một cái lộ trình moi được từ Graphhopper, nó thường mang hình hài của một cái “Đường Đa Tuyến Đã Mã Hóa” (Encoded Polyline). Đa số mấy anh frontend ngây thơ sẽ vớ ngay cục thư viện @mapbox/polyline để cắm đầu đi giải mã (decode) nó.
Mẹo hack hiệu năng (The Performance Hack): Trò giải mã polyline bằng Javascript sẽ chặn họng (blocks) cái Luồng Chính (Main Thread). Chiêu khôn ngoan nhất (smartest approach) là hãy kẹp cái biến points_encoded=false vào ngay cái cục request quăng cho backend Graphhopper. Nó sẽ ói ra thẳng luôn một cục GeoJSON LineString nguyên thủy (raw). Bạn chỉ việc lấy cái đó đút thẳng vào mồm Deck.gl hoặc Mapbox mà không phải mòn mỏi cày ải thêm dù chỉ một dòng code giải mã (decoding logic).
Cái Lỗi Ngược Đời Thứ Tự Tọa Độ (Coordinate Order Bug): Nếu bạn lỡ vác tay ra giải mã cái polyline, cái mảng (array) nó ói ra sẽ có dạng [Vĩ độ (Latitude), Kinh độ (Longitude)]. Ngặt cái nỗi, Mapbox với GeoJSON tụi nó bảo thủ khắt khe bắt ép (strictly require) phải là [Kinh độ, Vĩ độ]. Nếu bạn não cá vàng quên lộn ngược (reverse) lại cái mảng, cái lộ trình của bạn sẽ bỗng nhiên bơi lội tung tăng lọt thỏm ngay giữa rốn Thái Bình Dương.
2. Gánh Khối Lượng Hiển Thị Khổng Lồ Với Deck.gl
Để gánh được mấy mỏ dữ liệu khổng lồ (massive datasets), hãy móc cái MapboxOverlay ra kẹp thêm cái bùa interleaved: true. Chiêu này sẽ chích thẳng Deck.gl chui vào trong cái không gian WebGL (WebGL context) của Mapbox, cho phép mấy cái lộ trình của bạn lẩn khuất ngon ơ phía sau mớ nhãn văn bản (text labels) hay các tòa nhà 3D của Mapbox.
Hoạt Hình Tua Nhanh (Time-lapse Animations - Đỉnh chóp 60 FPS)
Để biến hóa hoạt hình (animate) cho 100,000 chiếc xe lướt qua một khoảng thời gian 24 giờ, một bạn dev non nớt (junior developer) khéo sẽ bợ cái lệnh setInterval kẹp với data.filter() để hì hục cập nhật cái mảng từng khung hình một (every frame). Trò này sẽ tiễn cái thẻ trình duyệt (browser tab) về nơi chín suối ngay tắp lự.
Chiêu của dân Senior là xài cái bùa DataFilterExtension. Bạn hốt nguyên cục dữ liệu 24 tiếng ném thẳng vào mồm bộ nhớ GPU đúng một lần duy nhất (exactly once). Nấp bên trong cái vòng lặp hoạt hình (animation loop - xài requestAnimationFrame), bạn chỉ việc nhúc nhích đúng một cái biến duy nhất của Shader (“Shader Uniform” - tên là filterRange). Con GPU sẽ ngay lập tức tàn nhẫn vứt xó (discards) hết mọi đỉnh (vertices) lọt ra ngoài khung thời gian, mang lại những thước phim hoạt hình 60 FPS mượt mà như bôi mỡ (buttery smooth).
Vẽ Mấy Cái Lục Giác H3 Khỏi Lo Bệnh Phình To (Bloat)
Khi cần múa may mấy cái lưới H3 (kiểu như tô màu các vùng mật độ tài xế), cấm tiệt việc nặn mấy cái đa giác GeoJSON (GeoJSON polygons) từ trên backend. Một cái lưới bọc nguyên thành phố bằng GeoJSON sức mấy cũng phải phình to cỡ 50MB.
Thay vào đó, chỉ được phép ném về đúng cái chuỗi ID 15 ký tự của H3 (ví dụ: 8928308280fffff). Dưới mặt trận frontend, hãy móc cái lớp H3HexagonLayer của Deck.gl ra xài. Cục thư viện này sẽ vác mấy cái hàm toán học của shaders ra nặn thành cái hình lục giác hoàn hảo ngay trên mặt con GPU, cứu vớt (saving) tận 99% băng thông mạng (network bandwidth) quý giá của bạn.
Để gánh được hàng triệu lượt vã truy vấn bản đồ và lưới H3 từ đám client mà không làm cái backend nghẹt thở (bottlenecking), ta buộc phải chơi trò Caching Ngữ Nghĩa (Semantic Caching) xài Redis. Khám phá cái tuyệt kỹ kiến trúc này tại Phần 6: Gom Nhóm Vị Trí Với Uber H3 & Caching Ngữ Nghĩa (Semantic Caching) Bằng Redis.
Hỏi Nhanh Đáp Gọn (FAQ): Gỡ Lỗi WebGL & Mapbox
parameters: { polygonOffset: true, polygonOffsetFactor: -1 } vào trong cái layer Deck.gl của bạn. Trò lừa đảo này sẽ dắt mũi cái bộ đệm chiều sâu (depth buffer) của GPU phải ưu tiên cái layer của bạn mà chả cần vặn vẹo gì tới độ cao vật lý (physical height) của nó.WebGL Context Lost (Đứt bóng không gian WebGL) rồi. Lỗi này giáng xuống khi cái Hệ điều hành (OS) nó lôi cổ thu hồi lại cái mảng nhớ GPU (ví dụ: khi lão user táy máy cắm thêm cái màn 4K mới hay con GPU nó cạn kiệt sạch VRAM do ráng nuốt mớ dữ liệu quá khổ). Cái cục ứng dụng React/Vue nhà bạn BẮT BUỘC phải dỏng tai lên vểnh nghe (listen) cái sự kiện webglcontextlost và ngoan ngoãn nhẹ nhàng (gracefully) khởi động lại (reload) ba cái cục Mapbox với Deck.gl để tỉnh lại (recover).