Tôi đang xây dựng cơ sở dữ liệu đồ chơi trong C# để tìm hiểu thêm về trình biên dịch, trình tối ưu hóa và công nghệ lập chỉ mục.Tệp không đồng bộ IO trong .Net
Tôi muốn duy trì tính song song tối đa giữa các yêu cầu (ít nhất là đọc) để đưa các trang vào vùng đệm, nhưng tôi nhầm lẫn về cách tốt nhất để thực hiện điều này trong .NET.
Dưới đây là một số tùy chọn và những vấn đề tôi đã đi qua với nhau:
Sử dụng
System.IO.FileStream
vàBeginRead
phương phápTuy nhiên, vị trí trong tập tin không phải là một cuộc tranh cãi để
BeginRead
, nó là tài sản củaFileStream
(được đặt thông qua phương thứcSeek
), vì vậy tôi chỉ có thể phát hành một yêu cầu cùng một lúc và phải khóa luồng trong thời gian. (Hoặc là tôi? Tài liệu không rõ ràng về những gì sẽ xảy ra nếu tôi chỉ giữ khóa giữa các cuộc gọiSeek
vàBeginRead
nhưng phát hành nó trước khi gọiEndRead
. Có ai biết không?) Tôi biết cách thực hiện việc này, tôi không chắc chắn đó là cách tốt nhất.Dường như có một cách khác, tập trung xung quanh cấu trúc
System.Threading.Overlapped
và P \ Gọi hàmReadFileEx
trong kernel32.dll.Thật không may, có rất nhiều mẫu, đặc biệt là trong các ngôn ngữ được quản lý. Tuyến đường này (nếu nó có thể được thực hiện để làm việc ở tất cả) dường như cũng liên quan đến phương pháp
ThreadPool.BindHandle
và các chủ đề hoàn thành IO trong hồ bơi thread. Tôi có ấn tượng rằng đây là cách bị xử phạt đối phó với kịch bản này dưới cửa sổ, nhưng tôi không hiểu nó và tôi không thể tìm thấy một điểm vào tài liệu đó là hữu ích cho người không chủ động.Cái gì khác?
Trong một nhận xét, jacob gợi ý tạo một
FileStream
mới cho mỗi lần đọc trong chuyến bay.Đọc toàn bộ tệp vào bộ nhớ.
Điều này sẽ hoạt động nếu cơ sở dữ liệu nhỏ. Các codebase là nhỏ, và có rất nhiều khác không hiệu quả, nhưng cơ sở dữ liệu chính nó không phải là. Tôi cũng muốn chắc chắn rằng tôi đang làm tất cả các sổ sách kế toán cần thiết để đối phó với một cơ sở dữ liệu lớn (mà hóa ra lại là một phần lớn của sự phức tạp: phân trang, phân loại bên ngoài, ...) và tôi lo lắng nó có thể là quá dễ dàng để vô tình lừa.
Sửa
Làm rõ lý do tại sao tôi nghi ngờ với giải pháp 1: tổ chức một khóa duy nhất tất cả các cách từ BeginRead để EndRead có nghĩa là tôi cần phải chặn bất cứ ai muốn bắt đầu một đọc chỉ vì đọc khác đang được tiến hành. Điều đó cảm thấy sai, bởi vì các chủ đề bắt đầu đọc mới có thể (nói chung) để làm một số công việc nhiều hơn trước khi kết quả trở nên có sẵn. (Trên thực tế, chỉ cần viết điều này đã khiến tôi nghĩ ra một giải pháp mới, tôi đặt câu trả lời mới.)
Đây là một ý kiến hay. Bạn cũng có thể tránh phân bổ byte mới [] s (và đập khối đối tượng lớn) bằng cách phân bổ trước chúng theo khối lớn khi bạn tạo (hoặc phát triển) vùng đệm. –
Ngoài ra, bây giờ tôi không biết về GetQueuedCompletionStatus (hoặc đọc qua nó bằng cách nào đó), điều này có thể giải thích lý do tại sao những nỗ lực của tôi tại thất bại này. Đã đến lúc đọc thêm. –