-
Notifications
You must be signed in to change notification settings - Fork 7
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Refactor flushevents #163
Refactor flushevents #163
Changes from 6 commits
79898c6
8900dbd
a7da48c
1aceb9d
036293e
78c4137
6efb5c2
56fd81c
f1281b7
b61d070
d9d0366
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -58,7 +58,7 @@ | |
|
||
|
||
const ioGame: Server | undefined = initializeGameClient(options) | ||
const interpreter = game ? getGameInterpreter(environment, ioGame!) : interpret(environment, { ...natives }) | ||
const interpreter = game ? getGameInterpreter(environment) : interpret(environment, { ...natives }) | ||
const programPackage = environment.getNodeByFQN<Package>(programFQN).parent as Package | ||
const dynamicDiagramClient = await initializeDynamicDiagram(programPackage, options, interpreter) | ||
|
||
|
@@ -81,43 +81,9 @@ | |
} | ||
} | ||
|
||
export const getGameInterpreter = (environment: Environment, io: Server): Interpreter => { | ||
mind-ar marked this conversation as resolved.
Show resolved
Hide resolved
|
||
const nativesAndDraw = { | ||
...natives, | ||
draw: { | ||
drawer: { | ||
*apply() { | ||
try { | ||
const game = interpreter?.object('wollok.game.game') | ||
const visuals = getVisuals(game, interpreter) | ||
io.emit('visuals', visuals) | ||
|
||
const gameSounds = game.get('sounds')?.innerCollection ?? [] | ||
const mappedSounds = gameSounds.map(sound => | ||
[ | ||
sound.id, | ||
sound.get('file')!.innerString!, | ||
sound.get('status')!.innerString!, | ||
sound.get('volume')!.innerNumber!, | ||
sound.get('loop')!.innerBoolean!, | ||
]) | ||
io.emit('updateSound', { soundInstances: mappedSounds }) | ||
} catch (error: any) { | ||
logger.error(failureDescription(error instanceof WollokException ? error.message : 'Exception while executing the program')) | ||
const debug = logger.getLevel() <= logger.levels.DEBUG | ||
if (debug) logger.error(error) | ||
interpreter.send('stop', gameSingleton) | ||
} | ||
}, | ||
}, | ||
}, | ||
} | ||
|
||
const interpreter = interpret(environment, nativesAndDraw) | ||
|
||
const gameSingleton = interpreter?.object(GAME_MODULE) | ||
const drawer = interpreter.object('draw.drawer') | ||
interpreter.send('onTick', gameSingleton, interpreter.reify(17), interpreter.reify('renderizar'), drawer) | ||
// TODO: ver si se elimina este método | ||
export const getGameInterpreter = (environment: Environment): Interpreter => { | ||
mind-ar marked this conversation as resolved.
Show resolved
Hide resolved
|
||
const interpreter = interpret(environment, natives) | ||
|
||
return interpreter | ||
} | ||
|
@@ -197,7 +163,7 @@ | |
queueEvent(interpreter, buildKeyPressEvent(interpreter, wKeyCode(key.key, key.keyCode)), buildKeyPressEvent(interpreter, 'ANY')) | ||
}) | ||
|
||
const gameSingleton = interpreter?.object('wollok.game.game') | ||
const gameSingleton = interpreter?.object(GAME_MODULE) | ||
const background = gameSingleton.get('boardGround') ? gameSingleton.get('boardGround')?.innerString : 'default' | ||
|
||
const baseFolder = join(project, assets) | ||
|
@@ -213,11 +179,33 @@ | |
socket.emit('background', background) | ||
}) | ||
|
||
const flushInterval = 100 | ||
const flushInterval = 17 | ||
let muestras = 0 | ||
let tEvents = 0 | ||
|
||
const id = setInterval(() => { | ||
try { | ||
const tsStart = performance.now() | ||
interpreter.send('flushEvents', gameSingleton, interpreter.reify(timer)) | ||
timer += flushInterval | ||
|
||
draw(interpreter, io) | ||
const elapsed = performance.now() - tsStart | ||
tEvents += elapsed | ||
|
||
// Si flushEvents demoró más del tiempo flushInterval | ||
// incrementamos el timer tomando el mayor de los tiempos | ||
timer += elapsed > flushInterval ? elapsed : flushInterval | ||
mind-ar marked this conversation as resolved.
Show resolved
Hide resolved
|
||
muestras += 1 | ||
|
||
|
||
// cada 30 muestras se imprime por consola el tiempo promedio | ||
// que tardó en procesar todos los eventos | ||
if(muestras >= 30) { | ||
logger.debug(`flushEvents: ${(tEvents / muestras).toFixed(2)} ms`) | ||
muestras = 0 | ||
tEvents = 0 | ||
} | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Esto se podría mover a una función aparte, y dejar la llamada comentada acá. Cosa de descomentar esa línea y ya tener info en algún lado. Después podemos iterar la técnica. Ojo que el linter marca que hay espacios raros. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
si, pero si lo muevo tengo que hacer There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Lo que yo diría es de tener una función para profilear otra función. Y las variables que mencionás podrían estar "globales" en ese otro módulo. // profile.ts
let n = 0
let totalTime = 0
const hitCount = 30
export const profile = (f: () => any) => {
const start = performance.now()
f()
const end = performance.now()
totalTime += end - start
n++
if(n >= hitCount) {
logger.debug(`flushEvents: ${(tEvents / muestras).toFixed(2)} ms`)
n = 0
totalTime = 0
}
} Y así se podría usar por ejemplo: profile( () =>
interpreter.send('flushEvents', gameSingleton, interpreter.reify(timer))
) Que no es tan invasivo. Después podemos ver si se puede mover a una annotation y controlarla globalmente para "prender y apagar" todos los profiles de una. Pero paso a paso. Algo que también podría recibir la función es una etiqueta para tener contexto de lo que se está profilieando... ahora esa función tiene hardcodeado el Sé que también hay otras funciones para loggear esto, podés ver por ejemplo el script cuando TS buildea el WRE: https://github.com/uqbar-project/wollok-ts/blob/master/scripts/buildWRE.ts |
||
|
||
// We could pass the interpreter but a program does not change it | ||
dynamicDiagramClient.onReload() | ||
if (!gameSingleton.get('running')?.innerBoolean) { | ||
|
@@ -291,4 +279,29 @@ | |
|
||
export const dynamicDiagramPort = (port: string): string => `${+gamePort(port) + 1}` | ||
|
||
const drawDefinition = () => parse.File('draw.wlk').tryParse('object drawer{ method apply() native }') | ||
const drawDefinition = () => parse.File('draw.wlk').tryParse('object drawer{ method apply() native }') | ||
mind-ar marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
||
|
||
const draw = (interpreter: Interpreter, io: Server) => { | ||
const game = interpreter?.object(GAME_MODULE) | ||
try { | ||
const visuals = getVisuals(game, interpreter) | ||
io.emit('visuals', visuals) | ||
|
||
const gameSounds = game.get('sounds')?.innerCollection ?? [] | ||
const mappedSounds = gameSounds.map(sound => | ||
[ | ||
sound.id, | ||
sound.get('file')!.innerString!, | ||
sound.get('status')!.innerString!, | ||
sound.get('volume')!.innerNumber!, | ||
sound.get('loop')!.innerBoolean!, | ||
]) | ||
io.emit('updateSound', { soundInstances: mappedSounds }) | ||
} catch (error: any) { | ||
logger.error(failureDescription(error instanceof WollokException ? error.message : 'Exception while executing the program')) | ||
const debug = logger.getLevel() <= logger.levels.DEBUG | ||
if (debug) logger.error(error) | ||
interpreter.send('stop', game) | ||
PalumboN marked this conversation as resolved.
Show resolved
Hide resolved
|
||
} | ||
} | ||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Esto para qué es? 😅
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
la librería que utilizamos para dibujar, ejecuta un ciclo continuo llamando a la función
draw()
, redibujando todo aunque no hayan nuevos datos que dibujar (no se recibió ninguna actualización del backend). Habría que probarlo en otro entorno, pero en mi PC ocasionaba bastante uso de CPU.Con este cambio lo que hice fue que la llamada a
draw()
sea manual, sólo cuando recibimos un evento. la contra de esto es que cuando exista un nuevo mensaje aún no implementado, hay que acordarse de llamar a draw() si queremos que se actualice el juego