Browse Source

make socket saturation take request-per-seconds into account to avoid starvation when lots of timeouts happen

v4
Mathias Buus 5 years ago
parent
commit
0199773e69
  1. 1
      index.js
  2. 15
      lib/io.js
  3. 1
      package.json

1
index.js

@ -25,6 +25,7 @@ class DHT extends EventEmitter {
this.bootstrapped = false
this.destroyed = false
this.concurrency = 16
this.concurrencyRPS = 50
this.socket = opts.socket || dgram.createSocket('udp4')
this.id = randomBytes(32)
this.inflightQueries = 0

15
lib/io.js

@ -2,6 +2,7 @@ const { Message, Holepunch, TYPE } = require('./messages')
const blake2b = require('./blake2b')
const peers = require('ipv4-peers')
const sodium = require('sodium-universal')
const speedometer = require('speedometer')
const QUERY = Symbol('QUERY')
const UPDATE = Symbol('UPDATE')
@ -28,6 +29,7 @@ class IO {
this._ticking = false
this._tickInterval = setInterval(this._ontick.bind(this), 750)
this._rotateInterval = setInterval(this._onrotate.bind(this), 300000)
this._speed = speedometer()
socket.on('message', this._onmessage.bind(this))
}
@ -120,6 +122,10 @@ class IO {
}
}
_saturated () {
return this._speed(0) >= this._ctx.concurrencyRPS && this.inflight.length >= this._ctx.concurrency
}
_finish (rid, err, val, peer) {
const req = this._requests[rid]
if (!req) return
@ -135,7 +141,7 @@ class IO {
req.callback(err, val, peer, req.message, req.peer, type)
while (this._pending.length && this.inflight.length < this._ctx.concurrency) {
while (this._pending.length && !this._saturated()) {
const { message, peer, callback } = this._pending.shift()
this._requestImmediately(message, peer, callback)
}
@ -143,7 +149,7 @@ class IO {
_request (message, peer, callback) {
// Should we wait to send?
if (this._pending.length || (this.inflight.length >= this._ctx.concurrency)) {
if (this._pending.length || this._saturated()) {
this._pending.push({ message, peer, callback })
} else {
this._requestImmediately(message, peer, callback)
@ -154,6 +160,8 @@ class IO {
const rid = message.rid = this._free()
const buffer = Message.encode(message)
this._speed(1)
const req = {
rid,
index: this.inflight.length,
@ -189,7 +197,8 @@ class IO {
const req = this.inflight[i]
if (req.timeout === 2 && ++req.tries < TRIES) {
this._retry(req)
if (this._saturated()) req.tries--
else this._retry(req)
continue
}

1
package.json

@ -28,6 +28,7 @@
"k-bucket": "^5.0.0",
"protocol-buffers-encodings": "^1.1.0",
"sodium-universal": "^2.0.0",
"speedometer": "^1.1.0",
"stream-collector": "^1.0.1",
"time-ordered-set": "^1.0.1",
"xor-distance": "^2.0.0"

Loading…
Cancel
Save