Serialization optimization

  • Thread starter Thread starter guy1976
  • Start date Start date
G

guy1976

Hi

I have an object :

[Serializable]
public class Buffer
{
private int length;
private IntPtr buffer;
}


The buffer field is allocated from an unmanaged memory (via a COM
object).

What I'd like to do, is to serialize this object w/o needing to
convert the IntPtr to byte[] (in the GetObjectData method), the
reasons are :
1. To ease on the GC (reduce allocations/sec and induced GC/sec )
2. buffer can be very large (128KB)
3. Reduce Marshal.Copy


Any idea how?
I was thinking on memory pool, but there is a constrain that this
object is transfered via remoting, and I cannot waist b/w for sending
un-used data.


Thanks
Guy.
 
I have an object :

[Serializable]
public class Buffer
{
private int length;
private IntPtr buffer;
}


The buffer field is allocated from an unmanaged memory (via a COM
object).

What I'd like to do, is to serialize this object w/o needing to
convert the IntPtr to byte[] (in the GetObjectData method), the
reasons are :
1. To ease on the GC (reduce allocations/sec and induced GC/sec )
2. buffer can be very large (128KB)
3. Reduce Marshal.Copy


Any idea how?

You can efficiently access unmanaged memory by using unsafe code to access a
pointer directly ("unsafe { byte* p = (byte*) buffer.ToPointer(); }"), which
eliminates the need for copying.

You can use the StreamingContext.State property to determine what you're
remoting to. If you're remoting in the same process (that is, between
AppDomains), you could choose not to copy/serialize the buffer at all, but
instead remote the pointer directly. Be aware that this is contrary to the
usual semantics of serialization if the receiver changes the contents of the
memory, as the sender isn't isolated from this.

Between local processes, you can remote file mapping handles (as created by
CreateFileMapping()). You can use permissions to restrict the accessibility
in this case, preventing remote clients from changing the passed buffer
(this is still contrary to the serialization semantics, just in a different
way).

These solutions are all less intuitive and less safe than simply remoting
the bytes, so make sure you're not optimizing prematurely. In particular,
reducing remoting as much as possible is more effective than making the
remoting itself more efficient, so only tackle the second if you've
sufficiently tackled the first.
 
I have an object :
[Serializable]
public class Buffer
{
        private int length;
        private IntPtr buffer;
}
The buffer field is allocated from an unmanaged memory (via a COM
object).
What I'd like to do, is to serialize this object w/o needing to
convert the IntPtr to byte[] (in the GetObjectData method), the
reasons are :
1. To ease on the GC (reduce allocations/sec and induced GC/sec )
2. buffer can be very large (128KB)
3. Reduce Marshal.Copy
Any idea how?

You can efficiently access unmanaged memory by using unsafe code to access a
pointer directly ("unsafe { byte* p = (byte*) buffer.ToPointer(); }"), which
eliminates the need for copying.

You can use the StreamingContext.State property to determine what you're
remoting to. If you're remoting in the same process (that is, between
AppDomains), you could choose not to copy/serialize the buffer at all, but
instead remote the pointer directly. Be aware that this is contrary to the
usual semantics of serialization if the receiver changes the contents of the
memory, as the sender isn't isolated from this.

Between local processes, you can remote file mapping handles (as created by
CreateFileMapping()). You can use permissions to restrict the accessibility
in this case, preventing remote clients from changing the passed buffer
(this is still contrary to the serialization semantics, just in a different
way).

These solutions are all less intuitive and less safe than simply remoting
the bytes, so make sure you're not optimizing prematurely. In particular,
reducing remoting as much as possible is more effective than making the
remoting itself more efficient, so only tackle the second if you've
sufficiently tackled the first.


1.How will the byte* elimite the copying?
2.I'm doing remoting between two computers
3.I must optimize because GC is working too much
 
I have an object :
[Serializable]
public class Buffer
{
private int length;
private IntPtr buffer;
}
The buffer field is allocated from an unmanaged memory (via a COM
object).
What I'd like to do, is to serialize this object w/o needing to
convert the IntPtr to byte[] (in the GetObjectData method), the
reasons are :
1. To ease on the GC (reduce allocations/sec and induced GC/sec )
2. buffer can be very large (128KB)
3. Reduce Marshal.Copy
Any idea how?
You can efficiently access unmanaged memory by using unsafe code to access a
pointer directly ("unsafe { byte* p = (byte*) buffer.ToPointer(); }"), which
eliminates the need for copying.

You can use the StreamingContext.State property to determine what you're
remoting to. If you're remoting in the same process (that is, between
AppDomains), you could choose not to copy/serialize the buffer at all, but
instead remote the pointer directly. Be aware that this is contrary to the
usual semantics of serialization if the receiver changes the contents of the
memory, as the sender isn't isolated from this.

Between local processes, you can remote file mapping handles (as created by
CreateFileMapping()). You can use permissions to restrict the accessibility
in this case, preventing remote clients from changing the passed buffer
(this is still contrary to the serialization semantics, just in a different
way).

These solutions are all less intuitive and less safe than simply remoting
the bytes, so make sure you're not optimizing prematurely. In particular,
reducing remoting as much as possible is more effective than making the
remoting itself more efficient, so only tackle the second if you've
sufficiently tackled the first.

1.How will the byte* elimite the copying?

It will eliminate copying in those cases where you would access the bytes
but not store them somewhere else. For .GetObjectData(), it's of little to
no use because you can't serialize individual bytes (well, you can, you just
don't want to) and you can't really use a more efficient representation than
a byte array either
2.I'm doing remoting between two computers

Then you have no choice but to remote the data as copied bytes.
3.I must optimize because GC is working too much

How do you know what's "too much"? I'm skeptical. If you need to copy a lot
of data every second, you need to copy a lot of data every second. You can't
optimize away your core function.

Consider not remoting "buffer". Remote byte arrays directly instead. This
way you are at least sure that the bytes are only copied once to a managed
object -- every subsequent remoting call (if there is more than one) can
simply take the byte array.

Consider ways to eliminate the remoting altogether (you don't have to use
remoting, even if it's convenient -- you could stream the bytes directly
over a socket, for example). Consider ways to make the individual remoting
packets smaller (less than 85 KB will avoid the Large Object Heap) or larger
(so there are less allocations).

Beyond this general advice, it's hard to say anything. There is no magic bullet.
 
Back
Top