3 ms·
> There also isn't generally a huge amount of pressure for these kinds of optimizations, given typical Python use cases. People who need performance are often a
by sgarland 2y ago
> There also isn't generally a huge amount of pressure for these kinds of optimizations, given typical Python use cases. People who need performance are often already using a Python binding to code written in another language anyway.
You’re of course not wrong, it’s just disappointing to see regressions. A side project I have started as pure Python and has gradually shifted to Python calling various C functions via ctypes. Before anyone jumps in with “why not numpy” etc., I wanted to see how fast I could make Python using only the stdlib. Calling C code is only kind of cheating, IMO.
That aside, there do remain some surprising ways to gain performance in Python that aren’t usually looked at. For example, its string mini-format language (you know, before f-strings, and before .format()) is significantly faster than either alternative. Not surprising, since it’s essentially just printf. This doesn’t matter at all unless it’s in a hot loop, but most of my usage is, so I’ve spent an extremely long time in cProfile, perf, and memray doing optimizations.
- zahlman 2y ago"mini-format language" in the documentation generally refers to the common system of type-specifying letters, width/precision specifiers, etc. Anyway, f-strings can be faster since they're "pre-compiled", especially for simple cases: $ python -m timeit --setup 'foo="bar"' -- 'f"Is the {foo}tender here?"' 5000000 loops, best of 5: 61.1 nsec per loop $ python -m timeit '"Is the %(foo)stender here?" % {"foo":"bar"}' 1000000 loops, best of 5: 246 nsec per loop $ python -m timeit '"Is the {foo}tender here?".format(foo="bar")' 1000000 loops, best of 5: 345 nsec per loop Similarly with positional rather than named substitutions: $ python -m timeit 'f"""Is the {"bar"}tender here?"""' 5000000 loops, best of 5: 60.4 nsec per loop $ python -m timeit '"Is the %stender here?" % "bar"' 2000000 loops, best of 5: 124 nsec per loop $ python -m timeit '"Is the {}tender here?".format("bar")' 2000000 loops, best of 5: 181 nsec per loop
- sgarland 2y agoI get ~20% faster times with the first style than with f-strings for this specific use, which is when I discovered it. def test_with_cstr(epoch: float) -> str: return "%04d-%02d-%02d %02d:%02d:%02d" % (time.gmtime(epoch)[:6]) def test_with_fstr(dt: datetime) -> str: return f"{dt.year:04d}-{dt.month:02d}-{dt.day:02d} {dt.hour:02d}:{dt.minute:02d}:{dt.second:02d}" EDIT: bad example, there’s other function overhead here as well.