diff --git a/arduino-ide-extension/src/node/core-service-impl.ts b/arduino-ide-extension/src/node/core-service-impl.ts index 6d55b307b..c1919d6db 100644 --- a/arduino-ide-extension/src/node/core-service-impl.ts +++ b/arduino-ide-extension/src/node/core-service-impl.ts @@ -28,7 +28,7 @@ import { ArduinoCoreServiceClient } from './cli-protocol/cc/arduino/cli/commands import { Port as GrpcPort } from './cli-protocol/cc/arduino/cli/commands/v1/port_pb'; import { ApplicationError, Disposable, nls } from '@theia/core'; import { MonitorManager } from './monitor-manager'; -import { SimpleBuffer } from './utils/simple-buffer'; +import { AutoFlushingBuffer } from './utils/buffers'; import { tryParseError } from './cli-error-parser'; import { Instance } from './cli-protocol/cc/arduino/cli/commands/v1/common_pb'; import { firstToUpperCase, notEmpty } from '../common/utils'; @@ -290,7 +290,7 @@ export class CoreServiceImpl extends CoreClientAware implements CoreService { onData: (response: R) => void; } { const stderr: Buffer[] = []; - const buffer = new SimpleBuffer((chunks) => { + const buffer = new AutoFlushingBuffer((chunks) => { Array.from(chunks.entries()).forEach(([severity, chunk]) => { if (chunk) { this.sendResponse(chunk, severity); diff --git a/arduino-ide-extension/src/node/utils/simple-buffer.ts b/arduino-ide-extension/src/node/utils/buffers.ts similarity index 59% rename from arduino-ide-extension/src/node/utils/simple-buffer.ts rename to arduino-ide-extension/src/node/utils/buffers.ts index 1e3a8293d..e703e1bce 100644 --- a/arduino-ide-extension/src/node/utils/simple-buffer.ts +++ b/arduino-ide-extension/src/node/utils/buffers.ts @@ -1,25 +1,33 @@ +import { DisposableCollection } from '@theia/core'; import { Disposable } from '@theia/core/shared/vscode-languageserver-protocol'; import { OutputMessage } from '../../common/protocol'; -const DEFAULT_FLUS_TIMEOUT_MS = 32; - -export class SimpleBuffer implements Disposable { +export class AutoFlushingBuffer implements Disposable { private readonly chunks = Chunks.create(); - private readonly flush: () => void; - private flushInterval?: NodeJS.Timeout; + private readonly toDispose; + private timer?: NodeJS.Timeout; + private disposed = false; constructor( onFlush: (chunks: Map) => void, - flushTimeout: number = DEFAULT_FLUS_TIMEOUT_MS + taskTimeout: number = AutoFlushingBuffer.DEFAULT_FLUSH_TIMEOUT_MS ) { - this.flush = () => { + const task = () => { if (!Chunks.isEmpty(this.chunks)) { const chunks = Chunks.toString(this.chunks); - this.clearChunks(); + Chunks.clear(this.chunks); onFlush(chunks); } + if (!this.disposed) { + this.timer = setTimeout(task, taskTimeout); + } }; - this.flushInterval = setInterval(this.flush, flushTimeout); + this.timer = setTimeout(task, taskTimeout); + this.toDispose = new DisposableCollection( + Disposable.create(() => (this.disposed = true)), + Disposable.create(() => clearTimeout(this.timer)), + Disposable.create(() => task()) + ); } addChunk( @@ -29,17 +37,17 @@ export class SimpleBuffer implements Disposable { this.chunks.get(severity)?.push(chunk); } - private clearChunks(): void { - Chunks.clear(this.chunks); - } - dispose(): void { - this.flush(); - clearInterval(this.flushInterval); - this.clearChunks(); - this.flushInterval = undefined; + this.toDispose.dispose(); } } +export namespace AutoFlushingBuffer { + /** + * _"chunking and sending every 16ms (60hz) is the best for small amount of data + * To be able to crunch more data without the cpu going to high, I opted for a 30fps refresh rate, hence the 32msec"_ + */ + export const DEFAULT_FLUSH_TIMEOUT_MS = 32; +} type Chunks = Map; namespace Chunks {