Về Áp Lực Bộ Nhớ, Tranh Chấp Khóa và Thiết Kế Hướng Dữ Liệu
Tôi ở đây để kể cho bạn nghe một câu chuyện về hiệu suất. Gần đây, tôi đã chạm trán với Áp Lực Bộ Nhớ và Tranh Chấp Khóa. Mất một lúc tôi mới nhận ra chúng. Truyền thuyết kể rằng nó chỉ xảy ra trong các hệ thống cấp thấp, khó hiểu, nhưng tôi ở đây để bác bỏ truyền thuyết đó. Trong quá trình tìm hiểu, tôi rất vui khi sửa một lỗi khá buồn cười trong một luồng cấp cao hơn: thật may mắn, để hoàn thiện mọi thứ, chúng ta thậm chí còn có một món quà ngọt ngào! Câu chuyện này cũng là một cái cớ để giới thiệu cho bạn về Thiết Kế Hướng Dữ Liệu, và để cho thấy nó đã cải thiện thời gian thực thi tới 98,7% và thông lượng tới 7718,5% như thế nào. Tôi tin rằng chúng ta có tất cả các thành phần cho một câu chuyện hấp dẫn. Hãy bắt tay vào và chúc ngon miệng!
Vào một buổi sáng tươi đẹp…
Trong khi bật Dygma Defy của tôi, mở khóa máy tính và kiểm tra tin nhắn từ các đồng nghiệp, tôi đột nhiên bắt gặp tin nhắn này: Có ai cũng gặp phải tình trạng danh sách phòng bị đóng băng không? À vâng, từ nhiều năm nay, tôi đã làm việc cho Element để phát triển Matrix Rust SDK. Nếu ai đó cần viết một ứng dụng khách hoặc bot Matrix hoàn chỉnh, hiện đại, đa nền tảng và nhanh chóng, thì SDK này là một lựa chọn tuyệt vời. SDK này bao gồm nhiều crate. Một số crate ở rất thấp trong ngăn xếp và không nhằm mục đích được các nhà phát triển sử dụng trực tiếp, chẳng hạn như matrix_sdk_crypto. Một số khác ở cao hơn trong ngăn xếp — cao nhất là dành cho Giao Diện Người Dùng (UI) với matrix_sdk_ui. Mặc dù có một chút chủ quan, nhưng nó được thiết kế để cung cấp các tính năng chất lượng cao mà mọi người mong đợi trong một ứng dụng khách Matrix hiện đại. Một trong những tính năng này là Danh Sách Phòng. Danh Sách Phòng là nơi người dùng dành nhiều thời gian trong một ứng dụng nhắn tin (cùng với Timeline, tức là tin nhắn của phòng). Một số kỳ vọng cho thành phần này:
- Cực nhanh
- Liệt kê tất cả các phòng
- Tương tác với các phòng (mở, đánh dấu là chưa đọc, v.v.)
- Lọc các phòng
- Sắp xếp các phòng
Hãy tập trung vào phần mà chúng ta quan tâm hôm nay: Sắp xếp các phòng. Danh Sách Phòng không chứa… phòng. Nó thực sự cung cấp một luồng các cập nhật về các phòng; chính xác hơn là một Stream. Điều này có nghĩa là gì? Luồng này tạo ra một vectơ các "diff" của các phòng. Tôi đang viết một loạt bài về lập trình phản ứng — bạn có thể quan tâm để đọc thêm về nó. Nếu không, đây là những gì bạn cần biết. Loại VectorDiff đến từ crate eyeball-im, ban đầu được tạo ra cho Matrix Rust SDK như một nền tảng vững chắc cho lập trình phản ứng. Nó trông như thế này:
pub enum VectorDiff<T> { Append { values: Vector<T>, }, Clear, PushFront { value: T, }, PushBack { value: T, }, PopFront, PopBack, Insert { index: usize, value: T, }, Set { index: usize, value: T, }, Remove { index: usize, }, Truncate { length: usize, }, Reset { values: Vector<T>, }, }
Nó đại diện cho một thay đổi trong ObservableVector. Nó giống như một Vec, nhưng người ta có thể đăng ký các thay đổi và sẽ nhận được… à… VectorDiff!
Loại Danh Sách Phòng hợp nhất một số luồng thành một luồng duy nhất đại diện cho danh sách các phòng. Ví dụ, hãy tưởng tượng phòng ở chỉ mục 3 nhận được một tin nhắn mới. "Xem trước" của nó (sự kiện mới nhất được hiển thị bên dưới tên phòng, ví dụ: Alice: Xin chào!) thay đổi. Ngoài ra, Danh Sách Phòng sắp xếp các phòng theo "mức độ gần đây" của chúng (thời gian một cái gì đó xảy ra trong phòng). Và vì "xem trước" đã thay đổi, "mức độ gần đây" của nó cũng thay đổi, có nghĩa là phòng được sắp xếp và định vị lại. Sau đó, chúng ta mong đợi luồng của Danh Sách Phòng tạo ra:
VectorDiff::Set { index: 3, value: new_room }vì "xem trước" mới,VectorDiff::Remove { index: 3 }để xóa phòng… ngay sau đó làVectorDiff::PushFront { value: new_room }để chèn phòng lên đầu Danh Sách Phòng.
Cơ chế lập trình phản ứng này đã được chứng minh là cực kỳ hiệu quả.
Le Comte
Tôi đã thực hiện phép tính của mình: kích thước của VectorDiff<Room> là 72 byte (chủ yếu là vì Room chứa một Arc trên loại struct thực). Điều này khá nhỏ cho một bản cập nhật. Không chỉ nó mang lại một dấu chân bộ nhớ nhỏ, mà nó còn vượt qua ranh giới FFI khá dễ dàng, giúp dễ dàng ánh xạ sang các ngôn ngữ khác như Swift hoặc Kotlin — các ngôn ngữ cung cấp các thành phần UI, như SwiftUI hoặc Jetpack Compose. Tuyệt đối! Đây là hai thành phần UI phổ biến, nơi VectorDiff ánh xạ trực tiếp đến các hoạt động cập nhật thành phần List của chúng. Chúng thực sự (đáng chú ý) khá giống nhau1.
Bạn luôn là một người bạn đồng hành thú vị, cảm ơn bạn. Hãy quay lại vấn đề của chúng ta: "Đóng băng" có nghĩa là gì đối với Danh Sách Phòng? Nó có nghĩa là Danh Sách Phòng chỉ đơn giản là… trống rỗng, vide, vacía, vuoto, خلو… à, bạn hiểu ý tôi rồi đấy.
Danh Sách Phòng có thể bị đóng băng do đâu? Chúng ta có những lựa chọn nào?
Le Factotum
Sẽ là một niềm vinh hạnh lớn nếu bạn cho phép tôi hỗ trợ bạn trong nhiệm vụ này. Đồng bộ hóa mạng không chạy đúng cách, do đó gây ấn tượng về một Danh Sách Phòng bị đóng băng? Hmm, không, mọi thứ hoạt động như mong đợi ở đây. Hơn nữa, dữ liệu cục bộ sẽ được hiển thị. "Luồng nguồn" được sử dụng bởi Danh Sách Phòng không tạo ra các bản cập nhật dự kiến? Không, mọi thứ hoạt động tốt. Việc "hợp nhất các luồng" bị hỏng vì một số lý do? Không, có vẻ ổn. Việc lọc các luồng? Đã lâu không đụng đến.
Góc nhìn từ cộng đồng
Hãy là người đầu tiên thêm một góc nhìn hữu ích để mạch đọc này trở nên sâu hơn.