This issue tracker has been migrated to GitHub, and is currently read-only.
For more information, see the GitHub FAQs in the Python's Developer Guide.

classification
Title: logging.getLevelName microoptimization
Type: performance Stage: resolved
Components: Library (Lib) Versions: Python 3.5
process
Status: closed Resolution: fixed
Dependencies: Superseder:
Assigned To: Nosy List: Ondřej Medek, python-dev, r.david.murray, vinay.sajip, xiang.zhang
Priority: normal Keywords:

Created on 2016-09-02 08:33 by Ondřej Medek, last changed 2022-04-11 14:58 by admin. This issue is now closed.

Messages (7)
msg274210 - (view) Author: Ondřej Medek (Ondřej Medek) Date: 2016-09-02 08:33
The logging.getLevelName contains code:

return _levelToName.get(level, _nameToLevel.get(level, ("Level %s" % level)))

I am still a Python beginner, but I think the most of the times the _nameToLevel.get is called unnecessarily. IMHO the code should be

return _levelToName.get(level, (_nameToLevel.get(level, ("Level %s" % level))))

or maybe better a classic if then style:
result = _levelToName.get(level)
if result is None:
   result = _nameToLevel.get(level, ("Level %s" % level))
return result

Since this function is called every time the LogRecord is created, I think it should be microoptimized.
msg274211 - (view) Author: Xiang Zhang (xiang.zhang) * (Python committer) Date: 2016-09-02 08:46
What's the meaning of the first method?
msg274215 - (view) Author: Ondřej Medek (Ondřej Medek) Date: 2016-09-02 09:03
Which 'first' method do you mean?

logging.getLevelName() converts level (int) to level name (str). But due to the backward compatibility is also converts level name (str) to level (int).
msg274216 - (view) Author: Xiang Zhang (xiang.zhang) * (Python committer) Date: 2016-09-02 09:06
No, I mean this method you propose:

return _levelToName.get(level, (_nameToLevel.get(level, ("Level %s" % level))))

I cannot see any difference with the original code, except parentheses.
msg274218 - (view) Author: Ondřej Medek (Ondřej Medek) Date: 2016-09-02 09:11
That's probably my lack of Python knowledge. I have though that parentheses in ("Level %s" % level) cause lazy evaluation. If not, then this code has to be optimized by if-then, too.
msg274247 - (view) Author: R. David Murray (r.david.murray) * (Python committer) Date: 2016-09-02 15:03
Parens do not cause lazy evaluation unless what is parenthesized is a generator comprehension.  An expanded if solution is the correct one.  

If Vinay prefers a one liner, I think you could also write:

   _levelToName.get(level) or _nameToLevel.get(level) or ("Level %s" % level)

Because we know we get back either a True string or None, I don't think there's any ambiguity there.
msg274302 - (view) Author: Roundup Robot (python-dev) (Python triager) Date: 2016-09-03 15:55
New changeset 0986401d0733 by Vinay Sajip in branch 'default':
Fixes #27937: optimise code used in all logging calls.
https://hg.python.org/cpython/rev/0986401d0733

New changeset e4b6faf22e8d by Vinay Sajip in branch '3.5':
Fixes #27937: optimise code used in all logging calls.
https://hg.python.org/cpython/rev/e4b6faf22e8d

New changeset 773c9401735f by Vinay Sajip in branch 'default':
Closes #27937: Merge fix from 3.5.
https://hg.python.org/cpython/rev/773c9401735f
History
Date User Action Args
2022-04-11 14:58:35adminsetgithub: 72124
2016-09-03 15:55:45python-devsetstatus: open -> closed

nosy: + python-dev
messages: + msg274302

resolution: fixed
stage: resolved
2016-09-02 15:03:02r.david.murraysetnosy: + r.david.murray, vinay.sajip
messages: + msg274247
2016-09-02 09:11:53Ondřej Medeksetmessages: + msg274218
2016-09-02 09:06:22xiang.zhangsetmessages: + msg274216
2016-09-02 09:03:28Ondřej Medeksetmessages: + msg274215
2016-09-02 08:46:38xiang.zhangsetnosy: + xiang.zhang
messages: + msg274211
2016-09-02 08:33:08Ondřej Medekcreate