mirror of
https://github.com/LBRYFoundation/lbry-sdk.git
synced 2025-08-23 17:27:25 +00:00
153 lines
4.2 KiB
Dart
153 lines
4.2 KiB
Dart
import 'dart:async';
|
|
import 'dart:io';
|
|
import 'dart:convert';
|
|
|
|
|
|
class LoadRequest {
|
|
final String host;
|
|
final int port;
|
|
final Map payload;
|
|
Completer completer;
|
|
Stopwatch timer;
|
|
Socket socket;
|
|
|
|
bool get isDone => completer.isCompleted;
|
|
int get elapsed => timer.elapsedMilliseconds;
|
|
|
|
LoadRequest(this.host, this.port, this.payload);
|
|
|
|
LoadRequest start() {
|
|
completer = Completer();
|
|
timer = Stopwatch()..start();
|
|
completer.future.whenComplete(() => timer.stop());
|
|
try {
|
|
Socket.connect(this.host, this.port).then((socket) {
|
|
this.socket = socket;
|
|
utf8.decoder.bind(socket).listen((r) {
|
|
if (r.contains('"jsonrpc": "2.0", "result": ')) {
|
|
socket.close();
|
|
completer.complete();
|
|
}
|
|
}, onError: (e) {print(e); completer.complete();});
|
|
try {
|
|
socket.write(jsonEncode(payload) + '\n');
|
|
} catch (exception, stackTrace) {
|
|
print(exception);
|
|
print(stackTrace);
|
|
completer.complete();
|
|
}
|
|
}, onError: (e) {print(e);completer.complete();});
|
|
} catch (exception, stackTrace) {
|
|
print(exception);
|
|
print(stackTrace);
|
|
completer.complete();
|
|
}
|
|
return this;
|
|
}
|
|
}
|
|
|
|
typedef bool LoadTickCallback(ClientLoadGenerator load_generator, ClientLoadDataPoint stats);
|
|
|
|
class ClientLoadGenerator {
|
|
Timer _timer;
|
|
|
|
final String host;
|
|
final int port;
|
|
final LoadTickCallback tickCallback;
|
|
int load = 1;
|
|
Map query;
|
|
List<LoadRequest> backlog = [];
|
|
|
|
ClientLoadGenerator(this.host, this.port, {this.tickCallback, this.query}) {
|
|
if (query == null) {
|
|
query = {
|
|
'id': 1,
|
|
'method': 'blockchain.claimtrie.resolve',
|
|
'params': ['one', 'two', 'three']
|
|
};
|
|
}
|
|
}
|
|
|
|
start() {
|
|
var previous = spawn_requests();
|
|
backlog = <LoadRequest>[];
|
|
_timer = Timer.periodic(Duration(seconds: 1), (t) {
|
|
var stat = ClientLoadDataPoint(t.tick);
|
|
backlog.removeWhere((r) {
|
|
if (r.isDone) stat.addCatchup(r);
|
|
return r.isDone;
|
|
});
|
|
for (var f in previous) {
|
|
if (f.isDone) {
|
|
stat.addSuccess(f);
|
|
} else {
|
|
backlog.add(f);
|
|
}
|
|
}
|
|
stat.backlog = backlog.length;
|
|
stat.load = load;
|
|
stat.close();
|
|
if (tickCallback(this, stat)) {
|
|
previous = spawn_requests();
|
|
} else {
|
|
stop();
|
|
}
|
|
});
|
|
}
|
|
|
|
stop() {
|
|
_timer.cancel();
|
|
for (var remaining in backlog) {
|
|
remaining?.socket?.close();
|
|
}
|
|
}
|
|
|
|
List<LoadRequest> spawn_requests() {
|
|
var requests = <LoadRequest>[];
|
|
for (var _ in Iterable.generate(load)) {
|
|
requests.add(LoadRequest(this.host, this.port, this.query).start());
|
|
}
|
|
return requests;
|
|
}
|
|
|
|
}
|
|
|
|
class ClientLoadDataPoint {
|
|
final int tick;
|
|
int success = 0;
|
|
int errored = 0;
|
|
int backlog = 0;
|
|
int catchup = 0;
|
|
int _success_total = 0;
|
|
int avg_success = 0;
|
|
int _catchup_total = 0;
|
|
int avg_catchup = 0;
|
|
int load = 0;
|
|
|
|
ClientLoadDataPoint(this.tick);
|
|
ClientLoadDataPoint.empty(): this(0);
|
|
|
|
addSuccess(LoadRequest r) {
|
|
success++; _success_total += r.elapsed;
|
|
}
|
|
|
|
addCatchup(LoadRequest r) {
|
|
catchup++; _catchup_total += r.elapsed;
|
|
}
|
|
|
|
close() {
|
|
avg_success = _success_total > 0 ? (_success_total/success).round() : 0;
|
|
avg_catchup = _catchup_total > 0 ? (_catchup_total/catchup).round() : 0;
|
|
}
|
|
|
|
}
|
|
|
|
|
|
generate_load() {
|
|
var runs = 1;
|
|
ClientLoadGenerator('localhost', 50001, tickCallback: (t, stats) {
|
|
print("run ${runs}: ${stats.load} load, ${stats.success} success, ${stats.backlog} backlog");
|
|
t.load = (runs < 4 ? t.load*2 : t.load/2).round();
|
|
return runs++ < 10;
|
|
}).start();
|
|
}
|