-
Notifications
You must be signed in to change notification settings - Fork 274
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
perf: do not compute log message until required #5410
Conversation
…eeded The idea is that sometimes we do heavy operations for silly logs, but we then discard just the log output. Instead, we can pass a callback and if the log is never needed for display, it won't actually call the heavy operations.
There might be multiple loggers resolving the message eventually. Wrap it in `memoize` so that it only gets resolved once.
19c17ed
to
2e3473c
Compare
@@ -318,38 +340,38 @@ export abstract class Log<C extends BaseContext = LogContext> implements LogConf | |||
/** | |||
* Render a log entry at the silly level. This is the highest verbosity. | |||
*/ | |||
silly(params: string | LogParams) { | |||
silly(params: Msg | LogParams) { |
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.
I think we might want to enforce using the closure instead of a string for silly
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.
I love this! It really is a very simple change for a 20% performance improvement
@@ -406,28 +406,28 @@ export class GraphSolver extends TypedEventEmitter<SolverEvents> { | |||
|
|||
if (status?.aborted || status?.error) { | |||
// Status is either aborted or failed | |||
this.log.silly(`Request ${request.getKey()} status: ${resultToString(status)}`) | |||
this.log.silly(() => `Request ${request.getKey()} status: ${resultToString(status)}`) |
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.
For for the record, these resultToString
calls were the main culprits of the time spent in logging by using CircularJSON.stringify
.
What this PR does / why we need it:
Before letting go of the whole performance epic, I did one last round of CPU profiling and noticed that for large projects we spend a large amount of time calling functions that are only used in higher log levels, which aren't actually really set most of the time. The problem is that we do the heavy processing for the log entries, but then we eventually discard them.
Thus I changed the logger so it can accept a callback, and if nothing logs it, the callback never gets called.
I don't want to spend large amounts of time on this anymore, and this was just a quick search and replace thing, so if it works let's consider merging it, if not, we can still keep this around as inspiration.
For now this was only applied to the
silly
log level since that's where the most expensive log lines were coming from.This improves performance of
garden validate
on a project with 500 modules from ~32 to ~25 seconds.So this change gives an about 20% time saving for very large projects, which is pretty nice for such a simple change.
Which issue(s) this PR fixes:
Fixes #
Special notes for your reviewer: