2009-11-04 35 views
13

Một chuỗi được nối tiếp phân cấp nhị phân 128 of đôi, chiếm 50 MB không gian. Đang tuần tự hóa mảng 128³ struct s với hai trường đôi chiếm 150 MB và hơn 20 giây để xử lý.Các lựa chọn thay thế nhị phân

Có các lựa chọn thay thế đơn giản nhanh nào có thể tạo ra các tệp nhỏ gọn không? Kỳ vọng của tôi là các ví dụ trên sẽ chiếm 16 và 32 MB, tương ứng và dưới hai giây để xử lý. Tôi đã xem xét protobuf-net, nhưng nó xuất hiện rằng nó thậm chí không hỗ trợ struct mảng.

PS: Tôi xin lỗi vì đã phạm sai lầm khi ghi kích thước tệp. Chi phí không gian thực tế với BinaryFormatter không lớn.

Trả lời

4

Nối tiếp có nghĩa là siêu dữ liệu được thêm vào để dữ liệu có thể được giải phóng an toàn, đó là nguyên nhân gây ra chi phí. Nếu bạn serialize dữ liệu cho mình mà không cần bất kỳ siêu dữ liệu, bạn kết thúc với 16 MB dữ liệu:

foreach (double d in array) { 
    byte[] bin = BitConverter.GetBytes(d); 
    stream.Write(bin, 0, bin.Length); 
} 

Điều này tất nhiên có nghĩa là bạn phải deserialize dữ liệu cho mình thêm:

using (BinaryReader reader = new BinaryReader(stream)) { 
    for (int i = 0; i < array.Length; i++) { 
     byte[] data = reader.ReadBytes(8); 
     array[i] = BitConverter.ToDouble(data, 0); 
    } 
} 
7

Nếu bạn sử dụng một BinaryWriter thay vì một Serializer bạn sẽ nhận được kích thước mong muốn (mimimal).
Tôi không chắc chắn về tốc độ, nhưng hãy thử.

Trên hệ thống của tôi viết 32MB mất chưa đến 0,5 giây, bao gồm Mở và Đóng luồng.

Bạn sẽ phải viết riêng cho vòng của bạn để viết dữ liệu, như thế này:

struct Pair 
{ 
    public double X, Y; 
} 

static void WritePairs(string filename, Pair[] data) 
{ 
    using (var fs = System.IO.File.Create(filename)) 
    using (var bw = new System.IO.BinaryWriter(fs)) 
    { 
     for (int i = 0; i < data.Length; i++) 
     { 
      bw.Write(data[i].X); 
      bw.Write(data[i].Y); 
     } 
    } 
} 

static void ReadPairs(string fileName, Pair[] data) 
{ 
    using (var fs = System.IO.File.OpenRead(fileName)) 
    using (var br = new System.IO.BinaryReader(fs)) 
    { 
     for (int i = 0; i < data.Length; i++) 
     { 
      data[i].X = br.ReadDouble(); 
      data[i].Y = br.ReadDouble(); 
     } 
    } 
} 
+2

Manual serialization thực sự có thể rất nhanh chóng và nhỏ gọn, nhưng nó cũng là dễ bị lỗi và tốn thời gian để viết. Tôi mong đợi một số chi phí, nhưng với BinaryFormatter nó thường là không hợp lý. –

+0

Bạn có thể làm cho nó thân thiện hơn một chút với generics và/hoặc giao diện. Nhưng bắt đầu thêm meta và bạn sẽ nhanh chóng tiếp cận chi phí của Formatters. –

+0

Phát hiện trên Henk. BinaryFormatter sẽ làm việc với chỉ là về * bất cứ điều gì *. Bạn nên mong đợi hiệu suất tốt hơn từ một cái gì đó không chính xác những gì bạn cần và * chỉ * những gì bạn cần. –

2

Đây là chi tiết của một bình luận nhưng đó là cách quá nhiều cho một ... Tôi không có thể tái tạo kết quả của bạn. Có, tuy nhiên, một số chi phí bổ sung với cấu trúc.

thử nghiệm của tôi:

------------------------------------------------------------------------------- 
Testing array of structs 

Size of double: 8 
Size of doubles.bin: 16777244 
Size per array item: 8 
Milliseconds to serialize: 143 
------------------------------------------------------------------------------- 
------------------------------------------------------------------------------- 
Testing array of structs 

Size of dd struct: 16 
Size of structs.bin: 52428991 
Size per array item: 25 
Milliseconds to serialize: 9678 
------------------------------------------------------------------------------- 

Code:

using System; 
using System.Collections.Generic; 
using System.Text; 
using System.Runtime.Serialization; 
using System.Runtime.Serialization.Formatters.Binary; 
using System.IO; 
using System.Diagnostics; 

namespace ConsoleApplication5 
{ 
    class Program 
    { 
     static void Main(string[] args) 
     { 
      TestDoubleArray(); 
      TestStructArray(); 
     } 

     private static void TestStructArray() 
     { 

      Stopwatch stopWatch = new Stopwatch(); 
      stopWatch.Start(); 

      dd[] d1 = new dd[2097152]; 
      BinaryFormatter f1 = new BinaryFormatter(); 
      f1.Serialize(File.Create("structs.bin"), d1); 

      stopWatch.Stop(); 

      Debug.WriteLine("-------------------------------------------------------------------------------"); 
      Debug.WriteLine("Testing array of structs"); 
      Debug.WriteLine(""); 
      Debug.WriteLine("Size of dd struct: " + System.Runtime.InteropServices.Marshal.SizeOf(typeof(dd)).ToString()); 
      FileInfo fi = new FileInfo("structs.bin"); 
      Debug.WriteLine("Size of structs.bin: " + fi.Length.ToString()); 
      Debug.WriteLine("Size per array item: " + (fi.Length/2097152).ToString()); 
      Debug.WriteLine("Milliseconds to serialize: " + stopWatch.ElapsedMilliseconds); 
      Debug.WriteLine("-------------------------------------------------------------------------------"); 
     } 

     static void TestDoubleArray() 
     { 
      Stopwatch stopWatch = new Stopwatch(); 
      stopWatch.Start(); 

      double[] d = new double[2097152]; 
      BinaryFormatter f = new BinaryFormatter(); 
      f.Serialize(File.Create("doubles.bin"), d); 

      stopWatch.Stop(); 

      Debug.WriteLine("-------------------------------------------------------------------------------"); 
      Debug.WriteLine("Testing array of structs"); 
      Debug.WriteLine(""); 
      Debug.WriteLine("Size of double: " + sizeof(double).ToString()); 
      FileInfo fi = new FileInfo("test.bin"); 
      Debug.WriteLine("Size of doubles.bin: " + fi.Length.ToString()); 
      Debug.WriteLine("Size per array item: " + (fi.Length/2097152).ToString()); 
      Debug.WriteLine("Milliseconds to serialize: " + stopWatch.ElapsedMilliseconds); 
      Debug.WriteLine("-------------------------------------------------------------------------------"); 
     } 

     [Serializable] 
     struct dd 
     { 
      double a; 
      double b; 
     } 
    } 
} 
+0

Cảm ơn bạn đã sửa. Lỗi của tôi. Chi phí không gian không lớn lắm. Tuy nhiên, thời gian serializer vẫn rất quan trọng. –

+0

Giống như tôi đã nhận xét về bài viết của Henk, bạn đang kinh doanh khái quát hóa và tiêu chuẩn hóa (BinaryFormatter) cho tốc độ của một lớp chuyên môn thực hiện một nhiệm vụ của nó ** rất tốt **. –

+0

Có vẻ như tôi đang giao dịch với tốc độ quá nhiều - một mức độ lớn vượt quá một lượng hợp lý. Nó không phải mất nhiều thời gian để tạo ra mã trong câu trả lời của Henk Holterman. –