Compare performances of gRPC server streaming and pagination of unary RPC

There are some cases that we wanna fetch all records that are matching with a certain condition from an other gRPC server. In these cases, there are at least 2 possible solutions to implement it, by gRPC server streaming or pagination. In this post, in order to check the benefit of the performance of gRPC server streaming over pagination, running benchmarks for the both of pagination and server streaming, and checked the performances.

Summaries of a result and analysis

Result wasn’t very good, and it might be better to run benchmarks on multiple machines and have more data with faster queries.

  • Contrary to expectations that using server streaming has better performances, the performance wasn’t improved under benchmark environment.
    • It might be because the benchmark environment was local machine and it couldn’t check the advantages of gRPC multiplexing responses.
  • Not surprisingly, if a gRPC server fetches records concurrently only on server streaming, it has significant advantages. And this might be the most important advantage for server streaming against pagination.
    • For pagination, a client side has to implement concurrent logics because the number of data that can be fetched by one request is limited. However, in many cases, pagination needs the previous result to get the data for next pagination request, like next token. So it’s hard to implement concurrent logics.
    • For server streaming, all of logics are is on a server side. Because a server can control the logics and how many data they can reply to the client, it’s easier to optimze.

Details

Benchmark environments

  • Run MySQL server as a docker container, and gRPC servers locally
  • In MySQL, there are 110K records.
  • Get multiple responses from gRPC RPCs to fetch all data that are matching with a condition
  • Fetch 1000 items at once for one query of pagination, and one response of gRPC server streaming
  • Run tests 10 times. One test took too much time so couldn’t increase more.
  • gRPC servers and clients are implemented in Golang.

Benchmark implementation details

  • From MySQL, a gRPC server fetches records by the query SELECT * FROM users WHERE name LIKE '%${keyword}%' ORDER BY id DESC LIMIT {$limit} OFFSET ${offset}.
  • In order to enable concurrency on gRPC server streaming, a gRPC server runs the query to fetch the total count SELECT COUNT(1) AS count FROM users WHERE name LIKE '%${keyword}%'.
    • For pagination, it runs only on the 1st request for pagination.
  • The proto for pagination and server streaming RPCs are here.
  • The details of codes are

Benchmark result

The case when 18K records are fetched


mysql root@127.0.0.1:test> select count(1) from users where name like '%ff%' limit 5;
+----------+
| count(1) |
+----------+
| 18081    |
+----------+
1 row in set
Time: 0.926s
> go test -v -bench=. -benchtime=10x -benchmem -cpuprofile=cpu.out -memprofile=mem.out ./user
goos: darwin
goarch: amd64
pkg: github.com/at-ishikawa/at-ishikawa.github.io/examples/golang/grpc/user
BenchmarkPaginateUsers
BenchmarkPaginateUsers-16             10        5729014144 ns/op        15748736 B/op     222302 allocs/op
BenchmarkStreamUsers
BenchmarkStreamUsers/concurrency_=_1
BenchmarkStreamUsers/concurrency_=_1-16                       10        5767206314 ns/op        15387366 B/op     219532 allocs/op
BenchmarkStreamUsers/concurrency_=_10
BenchmarkStreamUsers/concurrency_=_10-16                      10        2086846980 ns/op        15504884 B/op     219983 allocs/op
BenchmarkStreamUsers/concurrency_=_100
BenchmarkStreamUsers/concurrency_=_100-16                     10        1954722516 ns/op        15444297 B/op     219882 allocs/op
PASS
ok      github.com/at-ishikawa/at-ishikawa.github.io/examples/golang/grpc/user  171.140s

The case when 1039K records are fetched

In this case, the benchmark couldn’t run even 5 times, so run the test only once.

mysql root@127.0.0.1:test> select count(1) from users where name like '%e%' limit 5;
+----------+
| count(1) |
+----------+
| 1039693  |
+----------+
1 row in set
Time: 0.936s
> go test -v -bench=. -benchmem -cpuprofile=cpu.out -memprofile=mem.out ./user
goos: darwin
goarch: amd64
pkg: github.com/at-ishikawa/at-ishikawa.github.io/examples/golang/grpc/user
BenchmarkPaginateUsers
BenchmarkPaginateUsers-16              1        191732946675 ns/op      889266160 B/op  12768022 allocs/op
BenchmarkStreamUsers
BenchmarkStreamUsers/concurrency_=_1
BenchmarkStreamUsers/concurrency_=_1-16                        1        189976218377 ns/op      865303704 B/op  12596571 allocs/op
BenchmarkStreamUsers/concurrency_=_10
BenchmarkStreamUsers/concurrency_=_10-16                       1        41810204876 ns/op       870448160 B/op  12613615 allocs/op
BenchmarkStreamUsers/concurrency_=_100
BenchmarkStreamUsers/concurrency_=_100-16                      1        39546694589 ns/op       870049200 B/op  12618855 allocs/op
PASS
ok      github.com/at-ishikawa/at-ishikawa.github.io/examples/golang/grpc/user  463.391s

2024

Back to Top ↑

2023

Follow Kubernetes the Hard way

4 minute read

This article was written by just following Kelsey Hightower’s Kubernetes Hardway document to understand Kubernetes internal architecture.

Gcp Billing Analyze

less than 1 minute read

There are a few documents to manage billing data in BigQuery Attribution of committed use discount fees and credits How to export to BigQuery Structur...

Prometheus Metrics Overview on Grafana

1 minute read

In this post, some variables defined in Grafana are used for Prometheus metrics, including $__rate_interval: This article describes the benefit of this va...

Use Google Secret Manager in a GKE cluster

3 minute read

There are an awesome article about the options to use the Google Secret Manager and their pros and cons. In this article, use Secrets Store CSI Driver by fol...

Working around MySQL lock metadata

2 minute read

There are multiple documents about innodb locks on MySQL 5.7: InnoDB locking Locks Set by Different SQL Statements in InnoDB Using InnoDB Transaction ...

Upgrade Windows 10 to Windows 11

3 minute read

I used to use Windows 11, but for some reasons, the OS stopped working and I needed to clean-install it from Windows 10 from windows recovery environment.

Back to Top ↑

2022

MySQL backup and restore

1 minute read

In this article, explain how to backup MySQL database using Percona Xtrabackup. There are two binaries, innobackupex and xtrabackup. innobackupex is a wrappe...

tmux

1 minute read

Basic configuration

Back to Top ↑

2021

MySQL Replication

1 minute read

This configuration is for the version 5.7 and it’s minimum configuration in the official document.

jq cheetsheet

less than 1 minute read

jq is used to parse JSON result, format and output on the cli.

Compare static site generator

less than 1 minute read

There are many web sites to compare static site generator, but they miss some explanations that require to me. For some people, these features are important ...

Back to Top ↑

2020

Getting Started with Kubernetes Deployment

less than 1 minute read

The deployment is many use cases and in this page, they’re not described. For the details for those use cases or the concept of deployment, see official page.

Overview about MySQL Lock

2 minute read

This document is written for MySQL 5.7, so these contents may be not correct for other versions.

MySQL Performance

2 minute read

This document is written for MySQL 5.7, so these contents may be not correct for other versions. In this page, performance_schema is mainly discussed.

Git hooks

less than 1 minute read

Configurations

gitHub pages

3 minute read

Getting Started See Official tutorial for detail steps.

Gitconfig

1 minute read

Configuration The detail for gitconfig is written in official page.

git cli

less than 1 minute read

Written in March 2020.

MySQL Tuner

less than 1 minute read

MySQL Tuner tool This is a tool to review a configuration for MySQL server.

kubectl cheetsheet

less than 1 minute read

Collect recent error logs If the logs are outputted by zap, error messages are aggregated by checking level = error. This log does not work very well if the ...

Introduction to GCP Cloud endpoints

less than 1 minute read

The Cloud endpoint is actually the NGINX proxy which offers the following features on GCP. Authentication and validation Logging and monitoring in GCP

HTTP/2 for Go

1 minute read

http package in golang supports HTTP/2 protocols. It’s automatically configured.

Back to Top ↑

2019

Terraform overview

1 minute read

Basic concepts There are some basic components for terraform.

Protocol Buffers for Go with Gadgets

less than 1 minute read

gogo/protobuf is the library to store some extensions from golang/protobuf in this repository. There are some useful packages that golang/protobuf does not p...

Introduction to GCP Cloud CDN

less than 1 minute read

Target upstream services Cloud CDN can have only GCP load balancer as the upstream services. And GCP load balancer can configure one of followings for backen...

Getting Started with Google closure library

less than 1 minute read

Some JavaScript library depends on Google Closure. If you need to understand the behavior of such a library, you have to know closure. The official document ...

Back to Top ↑