Skip to content

Commit eb77f13

Browse files
committed
Remove dynamic timeout overhead
1 parent f7cac8f commit eb77f13

File tree

1 file changed

+21
-70
lines changed

1 file changed

+21
-70
lines changed

src/js/msp.js

Lines changed: 21 additions & 70 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,3 @@
1-
import GUI from "./gui.js";
21
import CONFIGURATOR from "./data_storage.js";
32
import { serial } from "./serial.js";
43

@@ -58,9 +57,9 @@ const MSP = {
5857
packet_error: 0,
5958
unsupported: 0,
6059

61-
MIN_TIMEOUT: 200,
62-
MAX_TIMEOUT: 2000,
63-
timeout: 200,
60+
MIN_TIMEOUT: 1, // Very fast timeout
61+
MAX_TIMEOUT: 200, // Upper bound for retries
62+
timeout: 1, // Start with 1ms
6463

6564
last_received_timestamp: null,
6665
listeners: [],
@@ -71,10 +70,9 @@ const MSP = {
7170
cli_output: [],
7271
cli_callback: null,
7372

74-
// Add retry configuration
75-
MAX_RETRIES: 10,
73+
// Simplified retry configuration
74+
MAX_RETRIES: 10, // Fixed retry limit
7675
MAX_QUEUE_SIZE: 50,
77-
MIN_RETRIES: 3, // Minimum retries when queue is healthy
7876

7977
read(readInfo) {
8078
if (CONFIGURATOR.virtualMode) {
@@ -409,12 +407,12 @@ const MSP = {
409407

410408
const requestObj = {
411409
code,
412-
requestKey, // Add the unique key to the request object
410+
requestKey,
413411
requestBuffer: bufferOut,
414412
callback: callback_msp,
415413
callbackOnError: doCallbackOnError,
416414
start: performance.now(),
417-
attempts: 0, // Initialize retry counter
415+
attempts: 0,
418416
};
419417

420418
// Track only the first outstanding request for a given key
@@ -425,16 +423,9 @@ const MSP = {
425423

426424
// Send message if it has data or is a new request
427425
if (data || !isDuplicateRequest) {
428-
// Simple adaptive timeout - decrease on success, increase on timeout
429426
serial.send(bufferOut, (sendInfo) => {
430-
if (sendInfo.bytesSent === bufferOut.byteLength) {
431-
// Success: gradually decrease timeout for faster response
432-
if (this.timeout > this.MIN_TIMEOUT) {
433-
this.timeout = Math.max(this.MIN_TIMEOUT, this.timeout - 5);
434-
}
435-
if (callback_sent) {
436-
callback_sent();
437-
}
427+
if (sendInfo.bytesSent === bufferOut.byteLength && callback_sent) {
428+
callback_sent();
438429
}
439430
});
440431
}
@@ -448,83 +439,43 @@ const MSP = {
448439
}, this.timeout);
449440
},
450441

451-
_getDynamicMaxRetries() {
452-
// Reduce retries when queue is getting full to prevent resource exhaustion
453-
if (this.callbacks.length > 30) {
454-
return 1;
455-
} // Very aggressive when queue is nearly full
456-
if (this.callbacks.length > 20) {
457-
return 2;
458-
} // Moderate reduction
459-
if (this.callbacks.length > 10) {
460-
return 3;
461-
} // Slight reduction
462-
return this.MAX_RETRIES; // Full retries when queue is healthy
463-
},
464-
465442
_handleTimeout(requestObj, bufferOut) {
466-
// Increase timeout on failure for better reliability
467-
this.timeout = Math.min(this.MAX_TIMEOUT, this.timeout + 50);
468-
469443
// Increment retry attempts
470444
requestObj.attempts++;
471445

472-
const dynamicMaxRetries = this._getDynamicMaxRetries();
473-
474446
console.warn(
475-
`MSP: data request timed-out: ${requestObj.code} ID: ${serial.connectionId} ` +
476-
`TAB: ${GUI.active_tab} TIMEOUT: ${this.timeout} ` +
477-
`QUEUE: ${this.callbacks.length}/${this.MAX_QUEUE_SIZE} (${this.callbacks.map((e) => e.code)}) ` +
478-
`ATTEMPTS: ${requestObj.attempts}/${dynamicMaxRetries}`,
447+
`MSP: data request timed-out: ${requestObj.code} ` +
448+
`QUEUE: ${this.callbacks.length}/${this.MAX_QUEUE_SIZE} ` +
449+
`ATTEMPTS: ${requestObj.attempts}/${this.MAX_RETRIES}`,
479450
);
480451

481452
// Check if max retries exceeded OR queue is too large
482-
if (requestObj.attempts >= dynamicMaxRetries || this.callbacks.length > this.MAX_QUEUE_SIZE) {
453+
if (requestObj.attempts >= this.MAX_RETRIES || this.callbacks.length > this.MAX_QUEUE_SIZE) {
483454
const reason =
484-
requestObj.attempts >= dynamicMaxRetries
485-
? `max retries (${dynamicMaxRetries})`
486-
: `queue overflow (${this.callbacks.length}/${this.MAX_QUEUE_SIZE})`;
455+
requestObj.attempts >= this.MAX_RETRIES ? `max retries (${this.MAX_RETRIES})` : `queue overflow`;
487456

488457
console.error(`MSP: Request ${requestObj.code} exceeded ${reason}, giving up`);
489-
490-
// Remove from callbacks to prevent memory leak
491458
this._removeRequestFromCallbacks(requestObj);
492459

493-
// Call error callback if available
494460
if (requestObj.callbackOnError && requestObj.callback) {
495461
requestObj.callback();
496462
}
497-
498-
return; // Stop retrying
463+
return;
499464
}
500465

501466
// Clear the existing timer before retry
502467
clearTimeout(requestObj.timer);
503468

504-
// Reset start time for this retry attempt
505-
requestObj.start = performance.now();
506-
507469
serial.send(bufferOut, (sendInfo) => {
508470
if (sendInfo.bytesSent === bufferOut.byteLength) {
509-
// Successfully sent retry
510-
requestObj.stop = performance.now();
511-
const executionTime = Math.round(requestObj.stop - requestObj.start);
512-
// Reset baseline for next retry
513-
requestObj.start = requestObj.stop;
514-
this.timeout = Math.max(this.MIN_TIMEOUT, Math.min(executionTime, this.MAX_TIMEOUT));
515-
516-
// Re-arm the timeout for retry attempts
517-
this._setupTimeout(requestObj, bufferOut);
471+
// Use exponential backoff for retries: 1ms, 2ms, 4ms, 8ms...
472+
const retryTimeout = Math.min(this.MAX_TIMEOUT, this.timeout * Math.pow(2, requestObj.attempts - 1));
473+
requestObj.timer = setTimeout(() => {
474+
this._handleTimeout(requestObj, bufferOut);
475+
}, retryTimeout);
518476
} else {
519-
// Failed to send retry - remove request and handle error
520-
console.error(
521-
`MSP: Failed to send retry for request ${requestObj.code}: ` +
522-
`sent ${sendInfo.bytesSent}/${bufferOut.byteLength} bytes`,
523-
);
524-
477+
console.error(`MSP: Failed to send retry for request ${requestObj.code}`);
525478
this._removeRequestFromCallbacks(requestObj);
526-
527-
// Call error callback if available
528479
if (requestObj.callbackOnError && requestObj.callback) {
529480
requestObj.callback();
530481
}

0 commit comments

Comments
 (0)