performance improv for flowing output

This commit is contained in:
Eugene Pankov
2018-03-29 00:25:57 +02:00
parent 049f08b8f9
commit 663da34e6d
6 changed files with 68 additions and 8 deletions

46
app/bufferizedPTY.js Normal file
View File

@@ -0,0 +1,46 @@
module.exports = function patchPTYModule (path) {
const mod = require(path)
const oldSpawn = mod.spawn
mod.spawn = (file, args, opt) => {
let terminal = oldSpawn(file, args, opt)
let timeout = null
let buffer = ''
let lastFlush = 0
let nextTimeout = 0
const maxWindow = 250
const minWindow = 50
function flush () {
if (buffer) {
terminal.emit('data-buffered', buffer)
}
lastFlush = Date.now()
buffer = ''
}
function reschedule () {
if (timeout) {
clearTimeout(timeout)
}
nextTimeout = Date.now() + minWindow
timeout = setTimeout(() => {
timeout = null
flush()
}, minWindow)
}
terminal.on('data', data => {
buffer += data
if (Date.now() - lastFlush > maxWindow) {
flush()
} else {
if (Date.now() > nextTimeout - (minWindow / 10)) {
reschedule()
}
}
})
return terminal
}
return mod
}

View File

@@ -1,11 +1,9 @@
if (process.platform == 'win32' && require('electron-squirrel-startup')) process.exit(0) if (process.platform == 'win32' && require('electron-squirrel-startup')) process.exit(0)
const electron = require('electron') const electron = require('electron')
if (process.argv.indexOf('--debug') !== -1) { if (process.argv.indexOf('--debug') !== -1) {
require('electron-debug')({enabled: true, showDevTools: 'undocked'}) require('electron-debug')({enabled: true, showDevTools: 'undocked'})
} }
let app = electron.app let app = electron.app
let secondInstance = app.makeSingleInstance((argv, cwd) => { let secondInstance = app.makeSingleInstance((argv, cwd) => {
@@ -44,6 +42,9 @@ setupWindowManagement = () => {
} }
}) })
app.window.on('enter-full-screen', () => app.window.webContents.send('host:window-enter-full-screen'))
app.window.on('leave-full-screen', () => app.window.webContents.send('host:window-leave-full-screen'))
app.window.on('close', (e) => { app.window.on('close', (e) => {
windowConfig.set('windowBoundaries', app.window.getBounds()) windowConfig.set('windowBoundaries', app.window.getBounds())
}) })

View File

@@ -1,5 +1,5 @@
title-bar( title-bar(
*ngIf='!hostApp.getWindow().isFullScreen() && config.store.appearance.frame == "full" && config.store.appearance.dock == "off"', *ngIf='!hostApp.isFullScreen && config.store.appearance.frame == "full" && config.store.appearance.dock == "off"',
[class.inset]='hostApp.platform == Platform.macOS' [class.inset]='hostApp.platform == Platform.macOS'
) )
@@ -7,7 +7,7 @@ title-bar(
[class.tabs-on-top]='config.store.appearance.tabsLocation == "top"' [class.tabs-on-top]='config.store.appearance.tabsLocation == "top"'
) )
.tab-bar( .tab-bar(
*ngIf='!hostApp.getWindow().isFullScreen()', *ngIf='!hostApp.isFullScreen',
[class.inset]='hostApp.platform == Platform.macOS && config.store.appearance.frame == "thin" && config.store.appearance.tabsLocation == "top"' [class.inset]='hostApp.platform == Platform.macOS && config.store.appearance.frame == "thin" && config.store.appearance.tabsLocation == "top"'
) )
.tabs .tabs

View File

@@ -32,7 +32,11 @@ export class ElectronService {
} }
remoteRequirePluginModule (plugin: string, module: string, globals: any): any { remoteRequirePluginModule (plugin: string, module: string, globals: any): any {
return this.remoteRequire(globals.require.resolve(`${plugin}/node_modules/${module}`)) return this.remoteRequire(this.remoteResolvePluginModule(plugin, module, globals))
}
remoteResolvePluginModule (plugin: string, module: string, globals: any): any {
return globals.require.resolve(`${plugin}/node_modules/${module}`)
} }
loseFocus () { loseFocus () {

View File

@@ -22,7 +22,7 @@ export class HostAppService {
ready = new EventEmitter<any>() ready = new EventEmitter<any>()
shown = new EventEmitter<any>() shown = new EventEmitter<any>()
secondInstance$ = new Subject<{ argv: string[], cwd: string }>() secondInstance$ = new Subject<{ argv: string[], cwd: string }>()
isFullScreen = false
private logger: Logger private logger: Logger
constructor ( constructor (
@@ -44,6 +44,14 @@ export class HostAppService {
this.logger.error('Unhandled exception:', err) this.logger.error('Unhandled exception:', err)
}) })
electron.ipcRenderer.on('host:window-enter-full-screen', () => this.zone.run(() => {
this.isFullScreen = true
}))
electron.ipcRenderer.on('host:window-leave-full-screen', () => this.zone.run(() => {
this.isFullScreen = false
}))
electron.ipcRenderer.on('host:window-shown', () => { electron.ipcRenderer.on('host:window-shown', () => {
this.zone.run(() => this.shown.emit()) this.zone.run(() => this.shown.emit())
}) })

View File

@@ -100,7 +100,7 @@ export class Session extends BaseSession {
this.open = true this.open = true
this.pty.on('data', data => { this.pty.on('data-buffered', data => {
this.emitOutput(data) this.emitOutput(data)
}) })
@@ -200,7 +200,8 @@ export class SessionsService {
electron: ElectronService, electron: ElectronService,
log: LogService, log: LogService,
) { ) {
nodePTY = electron.remoteRequirePluginModule('terminus-terminal', 'node-pty-tmp', global as any) const nodePTYPath = electron.remoteResolvePluginModule('terminus-terminal', 'node-pty-tmp', global as any)
nodePTY = electron.remoteRequire('./bufferizedPTY')(nodePTYPath)
this.logger = log.create('sessions') this.logger = log.create('sessions')
this.persistenceProviders = this.config.enabledServices(this.persistenceProviders).filter(x => x.isAvailable()) this.persistenceProviders = this.config.enabledServices(this.persistenceProviders).filter(x => x.isAvailable())
} }