ShopperCove
Menu
All writingBlogTopicsCategoriesAboutRSS
Blog
Categories
Observability & SRE62All categories
Topics
sre111localhost lab102performance70python58javascript47bundle size36benchmarking35node.js35web development21typescript19benchmark16content creation15All topics
About
Loading article…

ShopperCove

Hands-on notes on developer tools, written after the tool has actually been run.

All writingBlogCategoriesTopicsAboutPrivacyRSS

© 2026 ShopperCove

On this page

  1. Intro — what this post promises
  2. Arms
  3. Lab topology
  4. Lead table (p50 msgs/s)
  5. Sample output
  6. Why keep Formatter anyway
  7. Reading it for SRE work
  8. asctime is the silent tax
  9. Pitfalls
  10. Reproduce
  11. Limits
  12. Takeaway
  1. Blog

logging.Formatter vs f-string: Localhost Lab

1 October 2026·4 min read

Summary
On this page
  1. Intro — what this post promises
  2. Arms
  3. Lab topology
  4. Lead table (p50 msgs/s)
  5. Sample output
  6. Why keep Formatter anyway
  7. Reading it for SRE work
  8. asctime is the silent tax
  9. Pitfalls
  10. Reproduce
  11. Limits
  12. Takeaway

Intro — what this post promises

Format log lines with logging.Formatter vs f-string / %-format assembly — format-only, no handler I/O. This lab reports msgs/s on Linux localhost.

Related links:

  • 01shoppercove.comxml etree vs json localhost lab
  • 02shoppercove.commath fsum vs sum localhost lab
  • 03shoppercove.comfractions vs float localhost lab
  • 04shoppercove.comchainmap vs dict merge localhost lab
  • 05shoppercove.comipaddress vs string prefix localhost lab
  • 06shoppercove.comstatistics quantiles vs manual localhost lab
  • 07shoppercove.comrandom choices vs sample localhost lab
  • 08shoppercove.comitertools batched vs chunk localhost lab

Lab honesty (1 Oct 2026 IST): Python 3.13.5. Affiliates: 0. Differentiates from logging-vs-print (lab 51) — that post compared I/O; this one isolates Formatter.format vs manual string build on prebuilt LogRecords.

Verdict up front (n=50000): Formatter+asctime ~403971 msgs/s; f-string+strftime ~823931; Formatter plain ~1149467; f-string no asctime ~1599896.


Arms

ArmPattern
Formatter with asctimefull style line
Formatter plainlevel/name/message
f-string + strftimemanual peer with clock
%-format + strftimeclassic manual peer
f-string no asctimeskip clock
getMessage() onlybaseline message merge

Seven rounds, p50. Records carry extra host / lat attributes like structured logging extras.


Lab topology

n=50000 LogRecords · 7 rounds · p50
metric: msgs/s = n / p50_s
no StreamHandler / no disk write

Script: lab-evidence/125-logging-formatter-vs-fstring/results/run_lab.py.


Lead table (p50 msgs/s)

Armmsgs/s
Formatter + asctime403971
Formatter plain1149467
f-string + strftime823931
%-format + strftime814939
f-string no asctime1599896
getMessage only3529817

With a clock in the line, manual f-string (~823931) beat full Formatter (~403971). Drop asctime and f-string climbs further (~1599896).


Sample output

Formatter prefix (truncated): '2026-10-01 01:01:09,073 INFO [svc.api] request done id=0 host=n0 lat=0.000'. Manual peer without clock: 'INFO [svc.api] request done id=0 host=n0 lat=0.000'.


Why keep Formatter anyway

Handlers, filters, LogRecord factories, and library code expect Formatter. Hot paths that already hold fields can assemble an f-string for a metrics side channel — but do not fork two divergent layouts without a fixture. Lab 51 still owns the “print vs logging I/O” question.


Reading it for SRE work

  • Standard app logging → Formatter (consistency > peak msgs/s).
  • Ultra-hot debug string you control → f-string; measure with your fields.
  • asctime dominates cost — omit it or use a cheaper clock policy if volume hurts.
  • Never compare Formatter+handler I/O to bare f-string and call it a Formatter tax.

Keep one canonical layout in production so log shippers and alerts stay aligned.



asctime is the silent tax

The plain Formatter (no clock) reached ~1149467 msgs/s, while the asctime variant dropped to ~403971. Manual f-string without a stamp hit ~1599896. If your shipper already stamps at ingest, dropping %(asctime)s from the process Formatter is often the cheapest win — measure before and after on the same box.

This lab intentionally skips handler I/O so the Formatter vs f-string comparison is not drowned by write(2). Pair with lab 51 when you need print-vs-logging throughput under a real StreamHandler.


Pitfalls

  • Benchmarking logger.info(...) (includes level checks + handlers) as if it were Formatter.format.
  • Forgetting getMessage() lazy % args when comparing to f-strings that already interpolated.
  • Divergent layouts between Formatter and manual strings breaking log parsers.
  • Assuming %-format and f-string stay equal after adding timezone-aware stamps.

Reproduce

python3 lab-evidence/125-logging-formatter-vs-fstring/results/run_lab.py

Evidence: summary.json, summary.txt.


Limits

One Linux box. Format-only; no QueueHandler, no JSON formatter libs.


Takeaway

Format-only at 50000 msgs: full Formatter+asctime ~403971 msgs/s vs f-string+strftime ~823931. Prefer Formatter for real logging pipelines; use f-string when you deliberately own a hot, I/O-free format path.

logging.formatterf-stringlogrecordpython logginglocalhost labsremsgs/s

Lab evidence

What I found running this

Lab 1 Oct 2026 IST. Python 3.13.5. n=50000: Formatter+asctime 403971 msgs/s; fstring+strftime 823931; fstring no asctime 1599896. Format-only (not lab 51 I/O). Affiliates: 0. Evidence: lab-evidence/125-logging-formatter-vs-fstring/.

Notes when a lab post goes up

Occasional email for new hands-on reviews. No sequence and no sponsors.

Keep reading

  • logging vs print: Throughput Lab

    Hands-on logging vs print throughput lab: real lines/s for StreamHandler, StringIO, and a disabled logger, measured on Linux localhost only (eng lab).

    Summary1 Oct 20264 min read

  • platform vs os.uname Inventory: Localhost Lab

    Hands-on platform.platform vs os.uname host inventory lab: real ops/s plus cache notes, measured on Linux localhost today in this hands-on lab for SREs.

    Summary1 Oct 20264 min read

  • uuid.uuid4 vs uuid.uuid1: Localhost Lab

    Hands-on uuid.uuid4 vs uuid.uuid1 ID generation lab: real ops/s plus version/node checks, measured on Linux localhost today in this hands-on lab for SREs.

    Summary1 Oct 20263 min read