We’d like to be able to upload data to a server with as little performance impact on our application as possible and I see an opportunity to do this with the new JsonUtility and UnityWebRequest, given that they’re implemented natively. The goal is to take a serializable C# object and send it to a web server with as few C# heap allocations as possible, preferably none, but just avoiding the payload allocation will be a big step. I believe the current APIs are almost there, they just need a couple of tweaks.
I’ll start with the ultimate API for us, which would be simple but I recognize that there are some things about it you probably won’t like.
void UnityWebRequest.Post(string uri, object obj, DownloadHandler handler, System.Action<long/* status code /, string/ error */> onDone);
Serializes the object with JsonUtility, POSTs it to the url and calls the provided callback with the result without any C# heap allocations. The error string is only allocated when an error occurs.
So I’ll also provide a few suggestions to tweak the current APIs in less drastic ways.
The new JSON serialization API goes a long way towards eliminating allocations and could be entirely allocation-free with a simple change to the API.
I suggest adding the following overloads to the JsonUtility.ToJson method.
int JsonUtility.ToJson(object obj, bool prettyPrint, byte[ ] buffer, int offset, int maxOutputBytes);
with corresponding *Async versions. The output should be UTF8 encoded. Returns 0 if the buffer is not large enough.
A System.IO.Stream API would also be welcome of course.
This will allow an application to reuse C# buffers for storing the JSON data, allowing it to be sent over the network or serialized to disk without any allocations.
The UnityWebRequest API should provide a way of supplying POST and header data from byte[ ] or char[ ] arrays with an offset and count.
Could be as simple as adding an overload to Post
UnityWebRequest UnityWebRequest.Post(string uri, byte[ ] buffer, int offset, int count);
But another thing that would be great would be to replace or build upon the UploadHandler API to be able to supply an array with offset and count. Would mean it has to be opened up for extension by users too.
The current byte[ ] data property API requires an allocation for each upload. I suggest replacing with/adding
- System.IO.Stream API for reading data, allowing streaming off files too.
- virtual byte[ ] GetData(out int offset, out int byteCount); – could fallback to the current property API if it returns null.
With these changes I’d be able to POST arbitrary C# objects and only allocate the UnityWebRequest and AsyncOperation on the heap.