2010-09-06 19 views
6

Tôi sử dụng BinaryReader (MemoryStream(MyByteArray)) để đọc các bản ghi có kích thước biến đổi và xử lý tất cả chúng trong bộ nhớ. Điều này hoạt động tốt miễn là luồng tối ưu của tôi, nằm trong mảng, nhỏ hơn khoảng 1,7 GB. Sau đó (đó là kích thước tối đa của một số nguyên trong hệ thống 64-bit của tôi), bạn không thể tạo ra một khoảng trống lớn hơn, mặc dù tôi có đủ bộ nhớ thực. Vì vậy, giải pháp của tôi đã được đọc bytestream và chia nó thành nhiều mảng byte. Tuy nhiên, bây giờ tuy nhiên, tôi không thể "đọc" qua các ranh giới mảng byte, và, vì dữ liệu của tôi ở định dạng biến, tôi không thể đảm bảo rằng mảng byte luôn kết thúc trên toàn bộ bản ghi. Quay lại đầu trangĐọc từ một MemoryStream lớn trong C#

Đây phải là vấn đề phổ biến đối với những người xử lý các tập dữ liệu rất lớn và vẫn có nhu cầu về tốc độ.

Làm cách nào để xử lý sự cố này?

+0

Bạn nên ngăn chặn rằng một mảng byte có kích thước này được tải vào bộ nhớ để bắt đầu. Không phải là nó có thể thực hiện một giải pháp streaming, nơi bạn chỉ tải các phần của mảng vào bộ nhớ (một bộ đệm)? Bạn có cần quyền truy cập ngẫu nhiên vào các byte này không? Hoặc bạn có thể sử dụng giải pháp chuyển tiếp chỉ nơi bạn có thể đọc luồng từ đầu đến cuối trong khi xử lý luồng (và không cần nhìn lại). Mảng byte này đến từ đâu? Tệp, dịch vụ web, ...? –

Trả lời

4

Chỉnh sửa: Đọc những điều cơ bản, tôi nhận ra rằng các tệp được ánh xạ trên bộ nhớ có thể chậm hơn I/O thông thường để truy cập tuần tự.

Các bạn đã thử một cái gì đó như thế này:

var stream = new FileStream("data", 
    FileMode.Open, 
    FileAccess.Read, 
    FileShare.Read, 
    16 * 1024, 
    FileOptions.SequentialScan) 

var reader = new BinaryReader(stream); 

Nếu dữ liệu của bạn nằm trong một file và bạn có thể sử dụng .NET 4.0 xem xét sử dụng MemoryMappedFile.

Sau đó, bạn có thể sử dụng MemoryMappedViewStream để nhận luồng hoặc sử dụng MemoryMappedViewAccessor để nhận giao diện giống như BinaryReader.

+1

Có. Tôi đã thử rằng - tiếc là MemoryMappedFiles là rất chậm thực sự. – ManInMoon

2

Đối với các luồng quá lớn, bạn không nên thử đổ nó trong MemoryStream - sử dụng những thứ như FileStream thay vào đó và nói trực tiếp vào đĩa. Bộ đệm sẵn có thường đủ, hoặc bạn có thể tinh chỉnh điều này với những thứ như BufferedStream (nhưng tôi hiếm khi cần đến - nhưng sau đó, tôi có xu hướng bao gồm bộ đệm xử lý dữ liệu của riêng mình).

Bạn cũng có thể xem xét những thứ như nén hoặc dữ liệu dày đặc, và serializers thiết kế để hoạt động bằng cách luồng hồ sơ thay vì tạo ra toàn bộ một đồ thị cùng một lúc (mặc dù kể từ khi bạn đề cập đến BinaryReader, bạn có thể đã được làm điều này cao tay, vì vậy đây có thể không phải là một vấn đề).

+0

Có. Nó được nén - wuite một cách hiệu quả và tôi unserialise nó với logic của riêng tôi. Nhưng việc đọc từ đĩa quá chậm. Tất cả - Tôi sử dụng xử lý song song của datafile khổng lồ này và có nó trên đĩa sẽ cuase tất cả các loại tranh chấp. – ManInMoon

+0

Sử dụng một bộ nhớStrea, tất cả trong bộ nhớ - hoạt động hoàn hảo cho tôi - ngoại trừ bây giờ dữ liệu của tôi đã phát triển nhanh hơn kích thước tối đa trọng lượng này. – ManInMoon

+0

Tôi hy vọng bạn đã đọc xong 300 email đầu tiên, nếu không thì không có món tráng miệng (SO) cho bạn! –