Skip to content
This repository was archived by the owner on Oct 1, 2024. It is now read-only.

Commit 5ec3e8f

Browse files
Merge pull request #1412 from microsoft/gcampbell/AddingBuffering
Added buffering to prevent heavy logging issues
2 parents 1baf85f + feb8a39 commit 5ec3e8f

File tree

3 files changed

+69
-9
lines changed

3 files changed

+69
-9
lines changed

src/serialmonitor/outputBuffer.ts

+44
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
// Copyright (c) Microsoft Corporation. All rights reserved.
2+
// Licensed under the MIT license.
3+
4+
import { performance } from "perf_hooks";
5+
import * as vscode from "vscode";
6+
7+
export class BufferedOutputChannel implements vscode.Disposable {
8+
private _buffer: string[];
9+
private _timer: NodeJS.Timer;
10+
private _lastFlushTime: number;
11+
12+
public constructor(private readonly outputCallback: (value: string) => void, private readonly flushIntervalMs: number) {
13+
this._buffer = [];
14+
this._timer = setInterval(() => this.tryFlush(), this.flushIntervalMs);
15+
this._lastFlushTime = Number.NEGATIVE_INFINITY;
16+
}
17+
18+
public append(value: string) {
19+
this.add(value);
20+
}
21+
22+
public appendLine(value: string) {
23+
this.add(value + "\n");
24+
}
25+
26+
public dispose() {
27+
this.tryFlush();
28+
clearInterval(this._timer);
29+
}
30+
31+
private add(value: string) {
32+
this._buffer.push(value);
33+
this.tryFlush();
34+
}
35+
36+
private tryFlush() {
37+
const currentTime = performance.now();
38+
if (this._buffer.length > 0 && currentTime - this._lastFlushTime > this.flushIntervalMs) {
39+
this.outputCallback(this._buffer.join(""));
40+
this._lastFlushTime = currentTime;
41+
this._buffer = [];
42+
}
43+
}
44+
}

src/serialmonitor/serialMonitor.ts

+11-1
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ import ArduinoContext from "../arduinoContext";
66
import * as constants from "../common/constants";
77
import { DeviceContext } from "../deviceContext";
88
import * as Logger from "../logger/logger";
9+
import { BufferedOutputChannel } from "./outputBuffer";
910
import { SerialPortCtrl } from "./serialportctrl";
1011

1112
export interface ISerialPortDetail {
@@ -49,6 +50,8 @@ export class SerialMonitor implements vscode.Disposable {
4950

5051
private _outputChannel: vscode.OutputChannel;
5152

53+
private _bufferedOutputChannel: BufferedOutputChannel;
54+
5255
public initialize() {
5356
let defaultBaudRate;
5457
if (ArduinoContext.arduinoApp && ArduinoContext.arduinoApp.settings && ArduinoContext.arduinoApp.settings.defaultBaudRate) {
@@ -57,6 +60,7 @@ export class SerialMonitor implements vscode.Disposable {
5760
defaultBaudRate = SerialMonitor.DEFAULT_BAUD_RATE;
5861
}
5962
this._outputChannel = vscode.window.createOutputChannel(SerialMonitor.SERIAL_MONITOR);
63+
this._bufferedOutputChannel = new BufferedOutputChannel(this._outputChannel.append, 300);
6064
this._currentBaudRate = defaultBaudRate;
6165
this._portsStatusBar = vscode.window.createStatusBarItem(vscode.StatusBarAlignment.Right, constants.statusBarPriority.PORT);
6266
this._portsStatusBar.command = "arduino.selectSerialPort";
@@ -88,6 +92,8 @@ export class SerialMonitor implements vscode.Disposable {
8892
if (this._serialPortCtrl && this._serialPortCtrl.isActive) {
8993
return this._serialPortCtrl.stop();
9094
}
95+
this._outputChannel.dispose();
96+
this._bufferedOutputChannel.dispose();
9197
}
9298

9399
public async selectSerialPort(vid: string, pid: string) {
@@ -145,7 +151,11 @@ export class SerialMonitor implements vscode.Disposable {
145151
return;
146152
}
147153
} else {
148-
this._serialPortCtrl = new SerialPortCtrl(this._currentPort, this._currentBaudRate, this._outputChannel);
154+
this._serialPortCtrl = new SerialPortCtrl(
155+
this._currentPort,
156+
this._currentBaudRate,
157+
this._bufferedOutputChannel,
158+
this._outputChannel.show);
149159
}
150160

151161
if (!this._serialPortCtrl.currentPort) {

src/serialmonitor/serialportctrl.ts

+14-8
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,8 @@
44
import { ChildProcess, execFileSync, spawn } from "child_process";
55
import * as os from "os";
66
import * as path from "path";
7-
import { OutputChannel } from "vscode";
87
import { DeviceContext } from "../deviceContext";
8+
import { BufferedOutputChannel } from "./outputBuffer";
99

1010
interface ISerialPortDetail {
1111
port: string;
@@ -63,7 +63,11 @@ export class SerialPortCtrl {
6363
private _currentBaudRate: number;
6464
private _currentSerialPort = null;
6565

66-
public constructor(port: string, baudRate: number, private _outputChannel: OutputChannel) {
66+
public constructor(
67+
port: string,
68+
baudRate: number,
69+
private _bufferedOutputChannel: BufferedOutputChannel,
70+
private showOutputChannel: (preserveFocus?: boolean) => void) {
6771
this._currentBaudRate = baudRate;
6872
this._currentPort = port;
6973
}
@@ -80,8 +84,8 @@ export class SerialPortCtrl {
8084
}
8185

8286
public open(): Promise<void> {
83-
this._outputChannel.appendLine(`[Starting] Opening the serial port - ${this._currentPort}`);
84-
this._outputChannel.show();
87+
this._bufferedOutputChannel.appendLine(`[Starting] Opening the serial port - ${this._currentPort}`);
88+
this.showOutputChannel();
8589

8690
if (this._child) {
8791
this.stop();
@@ -96,8 +100,10 @@ export class SerialPortCtrl {
96100
});
97101

98102
this._child.stdout.on("data", (data) => {
99-
const jsonObj = JSON.parse(data.toString())
100-
this._outputChannel.append(jsonObj["payload"] + "\n");
103+
if (this.isActive) {
104+
const jsonObj = JSON.parse(data.toString())
105+
this._bufferedOutputChannel.append(jsonObj["payload"] + "\n");
106+
}
101107
});
102108
// TODO: add message check to ensure _child spawned without errors
103109
resolve();
@@ -155,8 +161,8 @@ export class SerialPortCtrl {
155161
}
156162
try {
157163
this._child.stdin.write('{"cmd": "close"}\n');
158-
if (this._outputChannel) {
159-
this._outputChannel.appendLine(`[Done] Closed the serial port ${os.EOL}`);
164+
if (this._bufferedOutputChannel) {
165+
this._bufferedOutputChannel.appendLine(`[Done] Closed the serial port ${os.EOL}`);
160166
}
161167
this._child = null;
162168
resolve(true);

0 commit comments

Comments
 (0)