pagespeed-quest
Version:
A framework for efficient web front-end speed improvement
89 lines • 6.64 kB
JavaScript
import { Transform } from 'stream';
export class ThrottlingLog {
ms;
bytes;
}
export class Throttle {
flushIntervalMs;
limitBytes;
currentBytes = 0;
interval;
logs = [];
constructor(limitBytes, flushIntervalMs) {
this.limitBytes = limitBytes;
this.flushIntervalMs = flushIntervalMs ?? 100;
}
static fromMbps(mbps, flushIntervalMs) {
const bytesPerSec = (mbps * 1024 * 1024) / 8;
const limitBytes = Math.floor((bytesPerSec * flushIntervalMs) / 1000);
return new Throttle(limitBytes, flushIntervalMs);
}
computeCapacity() {
const consumed = Math.min(this.currentBytes, this.limitBytes);
const carryover = this.currentBytes - consumed;
return { consumed, carryover };
}
start() {
this.interval = setInterval(() => {
const c = this.computeCapacity();
this.logs.push({
ms: Date.now(),
bytes: c.consumed,
});
this.currentBytes = c.carryover;
}, this.flushIntervalMs);
}
stop() {
if (this.interval)
clearInterval(this.interval);
}
checkAndStack(bytes) {
if (!this.interval)
throw new Error('Throttle is not started');
if (this.currentBytes >= this.limitBytes) {
return false;
}
this.currentBytes += bytes;
return true;
}
simpleReport(unitMs = 1000) {
const bySec = new Map();
for (const log of this.logs) {
const unit = Math.floor(log.ms / unitMs);
if (!bySec.has(unit))
bySec.set(unit, 0);
bySec.set(unit, bySec.get(unit) + log.bytes);
}
const values = Array.from(bySec.values());
const maxBytesPerUnit = Math.max(...values);
const avgBytesPerUnit = Math.floor(values.reduce((a, b) => a + b, 0) / bySec.size) / 1024 / 1024;
return {
maxBytesPerUnit,
avgBytesPerUnit,
};
}
}
export class ThrottlingTransform extends Transform {
throttle;
retryIntervalMs;
constructor(throttle, retryIntervalMs) {
super();
this.throttle = throttle;
this.retryIntervalMs = retryIntervalMs;
}
_transform(chunk, _, done) {
if (this.throttle.checkAndStack(chunk.length)) {
this.push(chunk);
done();
return;
}
const interval = setInterval(() => {
if (this.throttle.checkAndStack(chunk.length)) {
clearInterval(interval);
this.push(chunk);
done();
}
});
}
}
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidGhyb3R0bGluZy5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uL3NyYy90aHJvdHRsaW5nLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLE9BQU8sRUFBRSxTQUFTLEVBQXFCLE1BQU0sUUFBUSxDQUFBO0FBRXJELE1BQU0sT0FBTyxhQUFhO0lBQ3hCLEVBQUUsQ0FBUTtJQUNWLEtBQUssQ0FBUTtDQUNkO0FBRUQsTUFBTSxPQUFPLFFBQVE7SUFDbkIsZUFBZSxDQUFTO0lBQ3hCLFVBQVUsQ0FBUztJQUNuQixZQUFZLEdBQUcsQ0FBQyxDQUFBO0lBQ2hCLFFBQVEsQ0FBaUM7SUFDekMsSUFBSSxHQUFvQixFQUFFLENBQUE7SUFFMUIsWUFBWSxVQUFrQixFQUFFLGVBQXdCO1FBQ3RELElBQUksQ0FBQyxVQUFVLEdBQUcsVUFBVSxDQUFBO1FBQzVCLElBQUksQ0FBQyxlQUFlLEdBQUcsZUFBZSxJQUFJLEdBQUcsQ0FBQTtJQUMvQyxDQUFDO0lBRUQsTUFBTSxDQUFDLFFBQVEsQ0FBQyxJQUFZLEVBQUUsZUFBd0I7UUFDcEQsTUFBTSxXQUFXLEdBQUcsQ0FBQyxJQUFJLEdBQUcsSUFBSSxHQUFHLElBQUksQ0FBQyxHQUFHLENBQUMsQ0FBQTtRQUM1QyxNQUFNLFVBQVUsR0FBRyxJQUFJLENBQUMsS0FBSyxDQUFDLENBQUMsV0FBVyxHQUFHLGVBQWUsQ0FBQyxHQUFHLElBQUksQ0FBQyxDQUFBO1FBQ3JFLE9BQU8sSUFBSSxRQUFRLENBQUMsVUFBVSxFQUFFLGVBQWUsQ0FBQyxDQUFBO0lBQ2xELENBQUM7SUFFRCxlQUFlO1FBQ2IsTUFBTSxRQUFRLEdBQUcsSUFBSSxDQUFDLEdBQUcsQ0FBQyxJQUFJLENBQUMsWUFBWSxFQUFFLElBQUksQ0FBQyxVQUFVLENBQUMsQ0FBQTtRQUM3RCxNQUFNLFNBQVMsR0FBRyxJQUFJLENBQUMsWUFBWSxHQUFHLFFBQVEsQ0FBQTtRQUM5QyxPQUFPLEVBQUUsUUFBUSxFQUFFLFNBQVMsRUFBRSxDQUFBO0lB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