-
Notifications
You must be signed in to change notification settings - Fork 797
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
Why do we always need to judge the log level before printing the log in business logic? #2264
Comments
For me personally, it is to avoid that someone in the future will do heavy things just for the log before passing in the log parameter, but forget to add an additional guard statement, a common use case, to record structed json log log.Debugf("%s", toJson(request)) At this time, the guard statement in the log method is invalid |
Thanks for your reply. @jizhuozhi
However, I think that in most scenarios we don't need this judgment, which can make the code cleaner and more functional. |
Another use is to prevent args from mem escaping.
|
Good point, your case is actually similar to the first one @jizhuozhi provided, which is essentially to avoid allocate resources in non-debug level, which makes sense, but here are something can be discussed:
➜ mosn git:(master) ✗ cat tmp.go
package main
import (
"mosn.io/mosn/pkg/protocol/xprotocol/bolt"
"mosn.io/pkg/log"
)
var condition = false
func main() {
var cmd interface{}
cmd = &bolt.Request{}
if condition {
_, isReq := cmd.(*bolt.Request)
_, isResp := cmd.(*bolt.Response)
if cmd != nil {
log.DefaultLogger.Debugf("decode command, req(%v)|resp(%v)|hb(%v)\n", func() { toJson() }, isResp)
}
}
}
➜ mosn git:(master) ✗ go build -gcflags=-m tmp.go
# command-line-arguments
./tmp.go:12:8: &bolt.Request{} does not escape
./tmp.go:17:28: ... argument escapes to heap
./tmp.go:17:29: isReq escapes to heap
./tmp.go:17:29: isResp escapes to heap |
Oh, you're right. Thanks for correct~ @LENSHOOD |
I found in this case that the escape analysis may be inaccurate.
I found a issue. golang/go#17725 |
I'm also in favor of deleting this judgment at the moment. |
Hello, @diannaowa , @taoyuanyuan and @LENSHOOD . Unfortunately, our previous inferences and reality may be somewhat different. I'm currently working on a latency-based load balancer (#2252), and then doing related benchmarks and performance optimizations (since it's on the hotspot path). There is some logic of DEBUG level logs in my load balancer. In the flame graph, I found a convT64 function. However, there is no escape using pointers in my code, so the only possibility is that it is caused by logger. When I print the call stack, I find that it is true. In fact, because the log accepts parameters are Debugf(format string, args ...interface{}) so for the primitive type we pass in, even if we don't use the log, the conversion will still happen, which is really a big deal The overhead, so I think this change needs to be cautious, and I will continue to add judgment conditions here to avoid this situation from happening |
This is somewhat different from Java. In Java, due to the existence of method inlining, under the action of the JIT compiler, the judgment can be promoted to the caller stack, thereby avoiding the automatic boxing problem caused by passing values. But this is not possible without PGO optimization in Go, so we are better off writing guard statements |
Thank you for your kind reminder! To avoid dangling pointers, memory allocation requires that heap pointers must not point to the stack. Therefore, when the passed parameter is Using generics MAY solve this problem (although I have not tested whether functions with varargs types will still be monomorphized based on GCShape). Another way is to force the type to be determined at compile-time, similar to the approach used in Uber Zap: logger.Info("failed to fetch URL",
// Structured context as strongly typed Field values.
zap.String("url", url),
zap.Int("attempt", 3),
zap.Duration("backoff", time.Second),
) In short, any modification approach, whether using generics or the Uber Zap, may involve changes to hundreds of lines of code in MOSN. The evaluation of the actual performance impact may be considerable. Therefore, I also believe that simply removing the guard statements is too hasty. I agree with you to keep these guard statements and hope this issue can be resolved in the end. |
Your question
Like the following code in business logic:
But the loglevel has been judged in the log lib, Like the following code:
Is there some logic I'm missing?
Environment
Logs
The text was updated successfully, but these errors were encountered: