I guess you have some issues serving heavy lifting large fetch and clone requests with REST API and write traffic on the same JVM process.
We made good experience running a separate gerrit replica process with access to the same git directory containing the repositories (e.g. by symlinking
the gerrit primary git folder to the git folder of the replica colocated on the same host. Then block fetch and clone requests on the Gerrit primary process
and serve them only from the gerrit replica process. This way you have more control over which resources are spent on heavy fetch and clone requests
and which ones are used for REST API and queries. Then use parallelGC Java garbage collector for the replica and G1GC or even better generational zgc
(for that upgrade to gerrit 3.11 and Java 21) for the gerrit primary to optimize throughput for long running git requests on the replica and
responsiveness on the gerrit primary. Routing http requests can be automated using load balancer e.g. haproxy. For ssh use different ports to access
primary or replica.
I think your thread pools are too large for the available compute resources.
sshd.threads should be at most 2 x number of cores.
Typically most of the performance issues are caused by the largest repositories,
watch out for requests on repos larger than 1GB.
Do you have repos containing large binary files ?
Do you run git gc on a regular schedule ?
Create a couple of thread dumps on the server while you observe slow requests,
this should give you some idea where the long runners spend time.
Also you can use tracing to get detailed performance traces.