zturner added a comment.

In https://reviews.llvm.org/D27459#614670, @clayborg wrote:

> Part of the reason I like the current "if (log) log->Printf()" is that it 
> doesn't cost you much if logging isn't enabled. So if you have a log line 
> like:
>
>   if (log)
>     log->Printf("%s %s %s", myStringRef1.str().c_str(), 
> myStringRef2.str().c_str(), myStringRef3.str().c_str());
>
>
> And switch over to using:
>
>   LLDB_LOG() << myStringRef1 << " " << myStringRef2 << " " << myStringRef2;
>   
>
> You end up doing some work with all of the types regardless of wether the 
> logging is enabled. We tend to do pretty heavy logging in places and I really 
> don't want performance impacted (the expression parser emits a full novel 
> worth of information when logging is enabled), nor would I want people to log 
> less because they are worried about affecting performance.
>
> So any solution should have very minimal cost if logging isn't enabled. We 
> also do log channels, so any design will need to include the ability to log 
> to a channel, any channel, or only if all channels are enabled.
>
> The other thing I don't like about streams is they are harder to read over a 
> printf style log string. I wrote all of dwarfdump and used the full power off 
> C++ streams and I regret doing this as all of the code is really hard to 
> read. I also didn't like the fact that streams maintain state and can affect 
> things down the line. If we adopt LLVM style streams I believe they don't 
> suffer from the C++ streams having state issue. But with C++ you can do this:


Take a look at `llvm::formatv`.  I wrote this in LLVM specifically to be the 
best of both worlds.  You get all the flexibility and conciseness of printf 
with all the type safety of streams.  Example:

  // Printf style
  log->Printf("%d %s %z", 12, "test", (size_t)7);
  
  // Stream style
  *log << 12 << "test" << (size_t)7;
  
  // formatv style
  *log << llvm::formatv("{0} {1} {2}", 12, "test", (size_t)7);
  
  // alternative formatv sytle
  log->Formatv("{0} {1} {2}", 12, "test", (size_t)7);

As you can see, you don't have to specify the type.  All the ugliness about 
`PRIx64`, compiler inconsistencies, platform-dependent sizes, etc all disappear 
because it deduces the type.  And it's even better than this, because you can 
write custom formatters for your own types.  For examples, LLDB has a class 
called `AddressRange`.  With printf you would have to write this 
`log->Printf("%llu - %llu", range.first(), range.second())', but with `formatv` 
you can write this: `log->Formatv("{0}", range);` as long as it can find a 
formatter somewhere.  And formatters can define arbitrary style options too, so 
you could write something like `log->Formatv("{0:abc}", range);` and this 
string "abc" would get passed to the formatter's format function.  This is 
useful when a type is often formatted different ways (precision, optional 
fields, etc).

I strongly recommend moving to this for all printf style formatting moving 
forward.


https://reviews.llvm.org/D27459



_______________________________________________
lldb-commits mailing list
lldb-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits

Reply via email to