Python Logging Benchmark

If you have a heavy logging application, you might want to take into consideration to use the %-format strings for logging.
The Python logging module recommends to use the %-format.
But I guess most of the developers will prefer the f-string format, which came with the Python 3.6 release, because it simply easier to read.

My question was: Which impact does it have on performance? In case, we use logging with string concatenation.

So, I wrote a short script to “benchmark” it (and yes, I know it is not a proper benchmark).

Compared was: logging and concatenation with ‘+’ vs formatting with % vs f-strings, over multiple runs in a different order of the benchmark functions. So that, we can at least exclude the cold start issue.

Benchmark Diagram

If we take an average of all measuring points and compare them with each other, we would come to the result:

formatting with %concatenation with +f-strings
7.087545455 sec7.588454545 sec7.707727273 sec
100%107.06%108.75%

That means that, formatting with % is 8.75% faster than with f-string or 7.06% faster than with concatenation. At least in the combination with “deactivated” logging.

The reason for that is probably, because the string will be concatenated anyway, even if we don’t log anything. But in case of formatting with %, the string will be not concatenated.

Benchmark Script

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
import logging
import timeit

logger = logging.getLogger(__name__)
logger.setLevel(logging.ERROR)

def concatenate():
"""Function to benchmark with concatenation (+)"""

message = "Yeah!"
logger.warning("Message we would like to benchmark " + message)

def formatting():
"""Function to benchmark with formatting %s"""

message = "Yeah!"
logger.warning("Message we would like to benchmark %s", message)

def fstring():
"""Function to benchmark with f-string"""

message = "Yeah!"
logger.warning(f"Message we would like to benchmark {message}")

if __name__ == "__main__":
print("concatenate: ", timeit.timeit("concatenate()", setup="from __main__ import concatenate", number=10000000))
print("formatting: ", timeit.timeit("formatting()", setup="from __main__ import formatting", number=10000000))
print("fstring: ", timeit.timeit("fstring()", setup="from __main__ import fstring", number=10000000))