Created
December 1, 2025 05:44
-
-
Save devops-school/7b69d2f33d972b9b71911033a37eeae9 to your computer and use it in GitHub Desktop.
DOTNET: RPC with GRPC and REST and its Performance Impact
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| using System.Diagnostics; | |
| using System.Net.Http.Json; | |
| using Grpc.Net.Client; | |
| using RpcPerfDemo.Grpc; | |
| // Simple POCO matching REST response shape | |
| public class RestPerfResponse | |
| { | |
| public int Id { get; set; } | |
| public string Name { get; set; } = string.Empty; | |
| public List<int> Values { get; set; } = new(); | |
| public long ProcessedAtTicks { get; set; } | |
| } | |
| class Program | |
| { | |
| // Adjust if your server prints a different URL on startup | |
| private const string ServerAddress = "https://localhost:5001"; | |
| private const int Iterations = 1000; | |
| static async Task Main(string[] args) | |
| { | |
| Console.WriteLine("=== RPC Performance Demo: REST vs gRPC ==="); | |
| Console.WriteLine($"Server address: {ServerAddress}"); | |
| Console.WriteLine($"Total requests per style: {Iterations}"); | |
| Console.WriteLine(); | |
| // 1. Test REST (JSON) | |
| await RunRestBenchmark(); | |
| Console.WriteLine(); | |
| // 2. Test gRPC (Protobuf) | |
| await RunGrpcBenchmark(); | |
| Console.WriteLine(); | |
| Console.WriteLine("Done."); | |
| } | |
| private static async Task RunRestBenchmark() | |
| { | |
| using var httpClient = new HttpClient { BaseAddress = new Uri(ServerAddress) }; | |
| // Warm-up | |
| Console.WriteLine("Warming up REST endpoint..."); | |
| var warmupResponse = await httpClient.GetAsync("/rest/perf"); | |
| warmupResponse.EnsureSuccessStatusCode(); | |
| // Measure payload size of one response | |
| var sampleContent = await warmupResponse.Content.ReadAsStringAsync(); | |
| var restPayloadBytes = System.Text.Encoding.UTF8.GetByteCount(sampleContent); | |
| Console.WriteLine($"Sample REST JSON payload size: {restPayloadBytes} bytes"); | |
| Console.WriteLine("Running REST benchmark..."); | |
| var sw = Stopwatch.StartNew(); | |
| for (int i = 0; i < Iterations; i++) | |
| { | |
| var response = await httpClient.GetAsync("/rest/perf"); | |
| response.EnsureSuccessStatusCode(); | |
| // We don't actually use the data, just ensure it's read | |
| _ = await response.Content.ReadAsStringAsync(); | |
| } | |
| sw.Stop(); | |
| var totalMs = sw.Elapsed.TotalMilliseconds; | |
| var avgMs = totalMs / Iterations; | |
| Console.WriteLine($"REST total time: {totalMs:F2} ms for {Iterations} requests"); | |
| Console.WriteLine($"REST avg per request: {avgMs:F4} ms"); | |
| } | |
| private static async Task RunGrpcBenchmark() | |
| { | |
| // gRPC requires HTTP/2 – HTTPS endpoint from ASP.NET Core is fine | |
| using var channel = GrpcChannel.ForAddress(ServerAddress); | |
| var client = new PerfService.PerfServiceClient(channel); | |
| // Warm-up | |
| Console.WriteLine("Warming up gRPC endpoint..."); | |
| var warmupResponse = await client.GetDataAsync(new PerfRequest | |
| { | |
| Id = 1, | |
| Name = "Warmup" | |
| }); | |
| // Measure Protobuf payload size | |
| var grpcPayloadBytes = warmupResponse.CalculateSize(); | |
| Console.WriteLine($"Sample gRPC Protobuf payload size: {grpcPayloadBytes} bytes"); | |
| Console.WriteLine("Running gRPC benchmark..."); | |
| var sw = Stopwatch.StartNew(); | |
| for (int i = 0; i < Iterations; i++) | |
| { | |
| var response = await client.GetDataAsync(new PerfRequest | |
| { | |
| Id = i, | |
| Name = "Test-" + i | |
| }); | |
| // No need to use result; just ensure call completes | |
| } | |
| sw.Stop(); | |
| var totalMs = sw.Elapsed.TotalMilliseconds; | |
| var avgMs = totalMs / Iterations; | |
| Console.WriteLine($"gRPC total time: {totalMs:F2} ms for {Iterations} requests"); | |
| Console.WriteLine($"gRPC avg per request: {avgMs:F4} ms"); | |
| } | |
| } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment