-1

I have a reference type which contains raw image data in unmanaged memory. It's clear how to store the metadata (width, height) using SerializationInfo, but what is the best way to store a BLOB?

The only thing I can see is using Convert.ToBase64String which requires a whole bunch of copying. Is there a more straightforward way?

Ben Voigt
  • 277,958
  • 43
  • 419
  • 720

1 Answers1

2

Update: There is a much better way of handling this!

What you need to do is look at the StreamingContext passed in to GetObjectData, the StreamingContext.State property can tell you what kind of serialization is happening. If you get passed the state Clone or CrossAppDomain you may be able to reuse the existing handles you have to the unmanaged blob and just pass the handle pointers in to the SerializationInfo object.


You will need to do a bunch of copying no matter what you choose, but Convert.ToBase64String is unnecessary, you can just serialize the managed byte[] you would have passed in to Convert.ToBase64String and that should be fine.


I do not know if there is any special case efficency's for byte[], however all Seralizations get turned in to a byte stream during the transfer process. So by encoding in Base64 you are going to be doing

  1. Read your unmanaged blob and convert it to a managed byte[]
  2. Convert your byte[] in to a string via ToBase64String (increasing the size by a factor of 4/3 due to the encoding)
  3. Pass the encoded string with a tag name in to the SerializationInfo
  4. Pass the rest of the metadata in to the SerializationInfo with their respetive tags
  5. The serializer takes all of the tag+object combos and turns them in to a byte stream to be passed on to the destination
  6. The deserializer takes the byte stream and turns it back in to a collection of tags and objects
  7. You get your string back using the same tag name
  8. You get your metadata back using the tags you saved them under.
  9. Convert the string back in to a byte[] via FromBase64String
  10. Convert the byte[] back in to the unmanaged binary blob.

If you never encode to a string and just pass the byte[] in as the object to the SerializationInfo object the steps are pretty much the same, it just does not have that 4/3 size increase of the datablob to encode the binary data as text.

  1. Read your unmanaged blob and convert it to a managed byte[]
  2. Pass the byte[] with a tag name in to the SerializationInfo
  3. Pass the rest of the metadata in to the SerializationInfo with their respetive tags
  4. The serializer takes all of the tag+object combos and turns them in to a byte stream to be passed on to the destination
  5. The deserializer takes the byte stream and turns it back in to a collection of tags and objects
  6. You get your byte[] back using the same tag name
  7. You get your metadata back using the tags you saved them under.
  8. Convert the byte[] back in to the unmanaged binary blob.

So I guess the "optimization" is transmitting as a byte[] has the benefit of not increasing the amount of data you have to transmit to the desearizer.

Scott Chamberlain
  • 124,994
  • 33
  • 282
  • 431
  • That's unfortunate. Is `byte[]` special-cased for efficiency, do you know, or is it going to store the metadata followed by each individual element as a separate item? Is there any other easy way to just stash a few objects between runs of the program? – Ben Voigt Nov 17 '13 at 03:13
  • I added a extensive update to answer the first part of your question. For your 2nd question it depends on what your goal is: simplest implementation, minimum size, human readable, cross platform support, cross .NET framework version support? (if the answer to the last one is "no" then [`BinaryFormmater`](http://msdn.microsoft.com/en-us/library/system.runtime.serialization.formatters.binary.binaryformatter%28v=vs.110%29.aspx) may be the "easiest" solution)? – Scott Chamberlain Nov 17 '13 at 03:41
  • @BenVoigt I was not thinking earlier, Yes any kind of object that is passed in to [this overload](http://msdn.microsoft.com/en-us/library/vstudio/skf8dbad.aspx) of `AddValue(` ***could*** have optimizations. What will happen is it will call `GetObjectData()` on the object that is passed in and the nested searlizer does whatever optimizations it chooses to do (So it is up to the seralizer for `Array` to determine if there is any optimizations or not) – Scott Chamberlain Nov 17 '13 at 03:48
  • One thing you should also consid,er If you serialize to a `byte[]` and you then pass your searialization stream on to a `XMLSearalizer` it will encode the `byte[]` files as hexidecimal, which would be much more inefficient in size than the Base64 encoding, so maybe Base64 could be better. – Scott Chamberlain Nov 17 '13 at 04:01
  • That's what I suspected. Although I was worried it might be even worse, e.g. comma-separated list of decimal-encoded values. – Ben Voigt Nov 17 '13 at 04:09