Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Upload/Download performance with gRPC #1186

Closed
VasilSirakov opened this issue Feb 2, 2021 · 4 comments
Closed

Upload/Download performance with gRPC #1186

VasilSirakov opened this issue Feb 2, 2021 · 4 comments
Labels
question Further information is requested

Comments

@VasilSirakov
Copy link

VasilSirakov commented Feb 2, 2021

After doing some benchmarks between gRPC and REST (both .NET 5) for an upload and download functionality, the following results were obtained: REST had 2 to 3 times better performance for both upload and download than gRPC. Different sized chunks were used but none made any difference on the overall performance of gRPC when compared to REST. The benchmarks pulled data from memory in order to isolate the performance of both REST and gRPC from the data access latency.

Eventually the conclusion that was drawn was that the protobuf serialization of each DownloadResponse is taking up most of the time of gRPC's streaming especially for larger byte strings ( > 1MB). REST on the other hand, simply has an input/output stream in the request/response and doesn't serialize the data it transfers.

My question is, is there anything that can be done to improve the performance of gRPC when streaming files or is this not a great use-case for gRPC as a whole? I have come across some blog posts about using a custom marshaller but implementing it seems like a challenge and I do not know if/how it would resolve my problem.

Below is the very simple proto contract used for a streamed download.

rpc DownloadFile(DownloadRequest) returns (stream DownloadResponse);

message DownloadRequest {
    string FileId = 1;
}

message DownloadResponse {
    bytes FileChunk = 1;
}
@VasilSirakov VasilSirakov added the question Further information is requested label Feb 2, 2021
@JamesNK
Copy link
Member

JamesNK commented Feb 3, 2021

What do you mean by REST? REST usually that means JSON, and there is no streaming. I'm guessing that means the bytes being base64 encoded into one JSON response and the server returns that? I'm surprised that that would be faster than gRPC.

@VasilSirakov
Copy link
Author

VasilSirakov commented Feb 3, 2021

I am most certainly miswording it when I am saying REST. What I mean is writing bytes to the output stream of the response of a GET request. I'll give a code example:

[HttpGet]
[Route("file/{id}")]
public async Task File(Guid fileId)
{
    var fileData = manager.GetFileData();
    
    await this.HttpContext.Response.StartAsync();
    
    await foreach (var chunk in fileData)
    {
        await this.HttpContext.Response.Body.WriteAsync(chunk);
    }
    
    await this.HttpContext.Response.CompleteAsync();
}

I am not sure yet if this is the proper way of implementing this yet but in my benchmarks it had a much faster performance than writing those same chunks to the IServerStreamWriter in the gRPC service, namely:

var fileData = manager.GetFileData();

await foreach (var chunk in fileData)
{
    var response = new DownloadResponse
    {
        FileChunk = ByteString.CopyFrom(chunk),
    };
    
    await responseStream.WriteAsync(response);
}

@JamesNK
Copy link
Member

JamesNK commented Feb 3, 2021

Writing raw bytes will always be faster and more efficent than gRPC. gRPC involves serializing and deserializing messages. That requires allocating buffers and copying bytes multiple times for each chunk of data.

@VasilSirakov
Copy link
Author

Indeed, as I was suspecting, there probably isn't much to be done here in order to improve the performance. I was hoping this wasn't the case such that I could use solely gRPC throughout my application. Anyways, thank you for the input!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
question Further information is requested
Projects
None yet
Development

No branches or pull requests

2 participants