ASCOMInitiative / ASCOMRemote

The ASCOM REST based Remote Driver Server and Remote Access Clients
GNU General Public License v3.0
57 stars 16 forks source link

assuming .net serialization/deserialzation for binary transfers #11

Closed hollanderic closed 5 years ago

hollanderic commented 5 years ago

Currently the code assumes that binary transfers were serialized on by a windows .net device. I have been working on a few alpaca native devices along with a python library for creating alpaca devices. The binary transfer mode for imagearray (imagearraybinary) is really critical as serializing/deserializing large images in json is very resource/time intensive on both ends of the link.

Right now the binary mode assumes BinaryFormatter was used to serialize the image, which is a tough dependency for non-windows devices which may want to provide an alpaca device.

https://github.com/ASCOMInitiative/ASCOMRemote/blob/master/Remote%20Client%20Local%20Server/RemoteClientDriver.cs#L748

Peter-Simpson commented 5 years ago

Hi Eric,

I agree, BinaryFormatter was my first attempt at improving performance for Camera.ImageArray and I knew that it was MS only from the outset, nonetheless it did prove the hand-off mechanic. Due to the experimental nature of the performance improvements, I stopped committing further changes to the public master branch and instead undertook further tests through a local development branch.

At Ray Gralak's suggestion I've implemented a base64 encoding hand-off mechanic where the image array is converted into bytes, which are then base64 encoded. This approach is even faster than BinaryFormatter, transferring a 4000x3000 single plane image in under 2 seconds when both the remote client and the remote server are running on the same Windows instance.

The Remote Server has been trialed from a Python client by Michael Fulbright, whose application uses standard libraries to decode the base64 string and then reconstruct the integer image array. He has reported his experiences here: Python and ASCOM Remote and here: ASCOM Developer Forum

I'm just finalising the code for a further production release and have removed the experimental binaryformatter support in favour of the more efficient and more widely supported base64 encoding approach.

To use the base64 hand-off mechanic your client needs to set a header: base64handoff = true

If the Remote Server supports base64 hand-off, it will return a small JSON response containing a header: base64handoff = true together with fields indicating the array element type (int16, int32 or double), the array rank and the sizes of the array dimensions 0, 1 and 2 (please ignore dimension 2 for a 2D array).

The large base64 string can then be retrieved from a new device property: imagearraybase64 and decoded before re-constructing the array using the dimensions and element type returned in the small JSON response. On my system I found transfer was faster when setting a content-type header: Content-Type = image/tiff as opposed to Content-Type = text/plain although Michael found it made no difference. I would be interested to know whether this makes a difference in your environment.

The latest version of ASCOM Remote with base64 hand-off support is here: ASCOM Remote.

Regards, Peter

hollanderic commented 5 years ago

base64 makes a lot of sense. I will try out that build in the near future. I noticed there aren't any development branches on github, is the source (along with development branches) hosted elsewhere? Looking through the github master branch is the only way I discovered the binary version of the transfer.(Edit: somehow I didn't notice the other branches until just now)

Interesting about the transfer speeds with different Content-type versions. Depending on what was being used on the client side for serving http, i guess it is possible that compression could be negotiated for text/plain. For these large text files I noticed that there can be more latency associated with compressing the data than the actual transfer, especially if more aggressive compression is attempted. When compressing for the imagearraybinary handler, using a compression level of 9 resulted in the GET taking ~7 seconds to complete, whereas only compressing to a level of 1 completed the GET in a little over 1 second.

Just curious, have you considered transferring the image as a tiff (with Content-type = image/tiff) as a convenient way around the serialization problem? In my python tests I added a handler (imagearraytiff) for doing this as a convenience to get quick image previews into a browser.

Thanks for the context and the links, Eric

Peter-Simpson commented 5 years ago

Hi Eric,

I also found that uncompressed transfer was quickest for local devices, it may be beneficial over a slow connection though. That’s a good point about compression possibly being negotiated for text/plain, I’ll be sure to check that out.

My latest changes are on the “develop” branch, which you can examine through the github branches link shown below.

We recognise that ImageArray is no longer the best way of moving images around and are consulting with camera manufacturers on alternate way sof transferring images, formats such as TIFF or FITS may do the trick. Hopefully this will result in a new, more useful interface.

Regards, Peter

From: Eric Holland notifications@github.com Reply to: ASCOMInitiative/ASCOMRemote reply@reply.github.com Date: Wednesday, 2 October 2019 at 16:29 To: ASCOMInitiative/ASCOMRemote ASCOMRemote@noreply.github.com Cc: Peter Simpson peter@peterandjill.co.uk, Comment comment@noreply.github.com Subject: Re: [ASCOMInitiative/ASCOMRemote] assuming .net serialization/deserialzation for binary transfers (#11)

base64 makes a lot of sense. I will try out that build in the near future. I noticed there aren't any development branches on github, is the source (along with development branches) hosted elsewhere? Looking through the github master branch is the only way I discovered the binary version of the transfer.

Interesting about the transfer speeds with different Content-type versions. Depending on what was being used on the client side for serving http, i guess it is possible that compression could be negotiated for text/plain. For these large text files I noticed that there can be more latency associated with compressing the data than the actual transfer, especially if more aggressive compression is attempted. When compressing for the imagearraybinary handler, using a compression level of 9 resulted in the GET taking ~7 seconds to complete, whereas only compressing to a level of 1 completed the GET in a little over 1 second.

Just curious, have you considered transferring the image as a tiff (with Content-type = image/tiff) as a convenient way around the serialization problem? In my python tests I added a handler (imagearraytiff) for doing this as a convenience to get quick image previews into a browser.

Thanks for the context and the links, Eric

— You are receiving this because you commented. Reply to this email directly, view it on GitHub, or mute the thread.