For node.appendChild you have the whole virtual DOM thing leveraged by modern JS frameworks. If you hit issues try using any framework that boasts having a virtual DOM.
The same strategy could be done for the console to some extent.
The built-in console object is over-writable so you can add a layer that would batch console calls (if you do many in a short time). Note that this will break the call address you have on the right-hand side. Also IE11 does strange things with the console object depending if devtools are open or not.
The solution above is doable but it's a hack. If you really have to call console a lot of times in a short time adding a custom log method would be better.
globalThis.__debugLog = [];
globalThis.__printLog = () => globalThis.__debugLog.forEach(i => console.log(i));
const log = (...args) => globalThis.__debugLog.push(args);
// then in code:
log(whatever);
// and once you want to check it, call printLog in the console
__printLog();
Again with this solution you don't know where the call happens but it's a starting point. I recently started using the pattern above to debug performance and memoization issues I had in heavily used code. The console wasn't readable anymore without it. Console.table is helpful for printing out bigger sets of debug data btw.For canvas setTimeout on requestAnimationFrame seems to do the trick https://stackoverflow.com/questions/19516307/limiting-framer... I don't to much with canvas besides using it indirectly with libraries.