Compare throughput against jsmpp and Cloudhopper on one sink
Test / lint (pull_request) Successful in 21s
Test / test (18) (pull_request) Successful in 29s
Test / test (20) (pull_request) Successful in 29s
Test / test (22) (pull_request) Successful in 30s
Test / test (24) (pull_request) Successful in 29s
Test / test (26) (pull_request) Successful in 29s
Mirror / push (push) Has been cancelled
Test / lint (pull_request) Successful in 21s
Test / test (18) (pull_request) Successful in 29s
Test / test (20) (pull_request) Successful in 29s
Test / test (22) (pull_request) Successful in 30s
Test / test (24) (pull_request) Successful in 29s
Test / test (26) (pull_request) Successful in 29s
Mirror / push (push) Has been cancelled
This commit is contained in:
@@ -62,6 +62,36 @@ Against real peers, same driver, window 50, 20,000 messages:
|
||||
| Jasmin 0.10 | 2,207 | 0 |
|
||||
| SMPPSim 3.0.0 | — | 19,000 of 20,000 |
|
||||
|
||||
## Against the other client libraries
|
||||
|
||||
Same sink, same 100,000 single-segment messages, same host. This is the comparison that means
|
||||
something: every client is measured pushing into *our* server, so the server's work is common to all
|
||||
three and only the client differs.
|
||||
|
||||
```bash
|
||||
docker compose -f compose.yaml -f benchmarks/compose.jsmpp.yaml up -d --build
|
||||
docker compose -f compose.yaml -f benchmarks/compose.jsmpp.yaml run --rm node \
|
||||
node benchmarks/peer-load.ts --driver=http://jsmpp:8080 --count=100000 --concurrency=50
|
||||
```
|
||||
|
||||
| Window | this library | jsmpp 3.0.3 | Cloudhopper 5.0.10 |
|
||||
| --- | --- | --- | --- |
|
||||
| 10 | 25,358 | 30,771 | 27,945 |
|
||||
| 50 | 38,675 | 40,934 | 32,384 |
|
||||
| 200 | 40,046 | 42,105 | 25,497 |
|
||||
|
||||
**We are slowest at the default window**, which is the setting most callers will ever run — 25,358
|
||||
against jsmpp's 30,771. That is the throughput work worth doing, and it is worth doing there.
|
||||
|
||||
Two things the table does not show. This library does it on one event loop where both Java peers
|
||||
spend one OS thread per in-flight request, which is why Cloudhopper falls off at 200 threads and we
|
||||
do not. And all three are pushing into the same Node sink, whose own cost is in every number, so the
|
||||
differences between clients are compressed rather than exaggerated here.
|
||||
|
||||
Kannel is absent deliberately: it is a gateway rather than a client library, wired here as an ESME
|
||||
that forwards from its own spool, so loading it would measure its HTTP frontend and queue rather
|
||||
than an SMPP client. The number would not belong in this table.
|
||||
|
||||
Jasmin routes and persists where the sink does neither, so the gap is not an efficiency ratio
|
||||
between two comparable things — what it establishes is that this library is not the bottleneck
|
||||
against a production SMSC, by more than an order of magnitude. SMPPSim's store fills at roughly a
|
||||
|
||||
@@ -0,0 +1,25 @@
|
||||
x-log-limits: &log-limits
|
||||
logging:
|
||||
driver: json-file
|
||||
options:
|
||||
max-file: "3"
|
||||
max-size: 20m
|
||||
|
||||
# The peer dials the host it was given at build time, "node", so the sink answers under that name.
|
||||
services:
|
||||
cloudhopper:
|
||||
build: ./interop-tests/peers/cloudhopper
|
||||
image: interop-cloudhopper-load:5.0.10-ae6485a
|
||||
command: ["node", "2775"]
|
||||
<<: *log-limits
|
||||
healthcheck:
|
||||
test: ["CMD-SHELL", "bash -c 'exec 3<>/dev/tcp/127.0.0.1/8080'"]
|
||||
interval: 1s
|
||||
retries: 30
|
||||
timeout: 2s
|
||||
|
||||
node:
|
||||
command: ["node", "benchmarks/smsc-sink.ts"]
|
||||
environment:
|
||||
NPM_CONFIG_CACHE: /tmp/npm-cache
|
||||
PORT: "2775"
|
||||
@@ -0,0 +1,25 @@
|
||||
x-log-limits: &log-limits
|
||||
logging:
|
||||
driver: json-file
|
||||
options:
|
||||
max-file: "3"
|
||||
max-size: 20m
|
||||
|
||||
# The peer dials the host it was given at build time, "node", so the sink answers under that name.
|
||||
services:
|
||||
jsmpp:
|
||||
build: ./interop-tests/peers/jsmpp
|
||||
image: interop-jsmpp-load:3.0.3-a24db96
|
||||
command: ["node", "2775"]
|
||||
<<: *log-limits
|
||||
healthcheck:
|
||||
test: ["CMD-SHELL", "bash -c 'exec 3<>/dev/tcp/127.0.0.1/8080'"]
|
||||
interval: 1s
|
||||
retries: 30
|
||||
timeout: 2s
|
||||
|
||||
node:
|
||||
command: ["node", "benchmarks/smsc-sink.ts"]
|
||||
environment:
|
||||
NPM_CONFIG_CACHE: /tmp/npm-cache
|
||||
PORT: "2775"
|
||||
@@ -0,0 +1,33 @@
|
||||
/**
|
||||
* Drives a peer's HTTP control surface through the same load the local driver runs, so the number
|
||||
* that comes back is that library's own rate against our sink rather than ours against theirs.
|
||||
*/
|
||||
function arg(name: string, fallback: string): string {
|
||||
const found = process.argv.find(one => one.startsWith(`--${name}=`));
|
||||
|
||||
return found === undefined ? fallback : found.slice(name.length + 3);
|
||||
}
|
||||
|
||||
const driver = arg('driver', 'http://jsmpp:8080');
|
||||
const count = arg('count', '20000');
|
||||
const concurrency = arg('concurrency', '50');
|
||||
|
||||
async function call(path: string): Promise<unknown> {
|
||||
const response = await fetch(`${driver}${path}`);
|
||||
|
||||
return response.json();
|
||||
}
|
||||
|
||||
// Cloudhopper's window defaults to 1 and is set at bind, so threads alone would serialise it.
|
||||
const bound = await call(`/bind?systemId=bench&password=benchpw&windowSize=${concurrency}`);
|
||||
|
||||
if (typeof bound !== 'object' || bound === null || !('ok' in bound) || bound.ok !== true) {
|
||||
process.stdout.write(`${JSON.stringify({ bind: bound })}\n`);
|
||||
process.exit(1);
|
||||
}
|
||||
|
||||
const loaded = await call(`/load?count=${count}&concurrency=${concurrency}`);
|
||||
|
||||
process.stdout.write(`${JSON.stringify(loaded)}\n`);
|
||||
|
||||
await call('/unbind');
|
||||
Reference in New Issue
Block a user