]> git.ipfire.org Git - thirdparty/Python/cpython.git/commitdiff
bpo-38045: Improve the performance of _decompose() in enum.py (GH-16483)
authorHongWeipeng <961365124@qq.com>
Tue, 26 Nov 2019 22:36:02 +0000 (06:36 +0800)
committerEthan Furman <ethan@stoneleaf.us>
Tue, 26 Nov 2019 22:36:02 +0000 (14:36 -0800)
* Improve the performance of _decompose() in enum.py

Co-Authored-By: Brandt Bucher <brandtbucher@gmail.com>
Lib/enum.py
Misc/NEWS.d/next/Library/2019-09-30-12-09-41.bpo-38045.VDRtd3.rst [new file with mode: 0644]

index 06f42a978035be408448e0e85234c088eb5dc7d2..0be1b60cd6d8aaa7aaebea10bab619d6bb908209 100644 (file)
@@ -861,28 +861,20 @@ def _decompose(flag, value):
     # _decompose is only called if the value is not named
     not_covered = value
     negative = value < 0
-    # issue29167: wrap accesses to _value2member_map_ in a list to avoid race
-    #             conditions between iterating over it and having more pseudo-
-    #             members added to it
-    if negative:
-        # only check for named flags
-        flags_to_check = [
-                (m, v)
-                for v, m in list(flag._value2member_map_.items())
-                if m.name is not None
-                ]
-    else:
-        # check for named flags and powers-of-two flags
-        flags_to_check = [
-                (m, v)
-                for v, m in list(flag._value2member_map_.items())
-                if m.name is not None or _power_of_two(v)
-                ]
     members = []
-    for member, member_value in flags_to_check:
+    for member in flag:
+        member_value = member.value
         if member_value and member_value & value == member_value:
             members.append(member)
             not_covered &= ~member_value
+    if not negative:
+        tmp = not_covered
+        while tmp:
+            flag_value = 2 ** _high_bit(tmp)
+            if flag_value in flag._value2member_map_:
+                members.append(flag._value2member_map_[flag_value])
+                not_covered &= ~flag_value
+            tmp &= ~flag_value
     if not members and value in flag._value2member_map_:
         members.append(flag._value2member_map_[value])
     members.sort(key=lambda m: m._value_, reverse=True)
@@ -890,8 +882,3 @@ def _decompose(flag, value):
         # we have the breakdown, don't need the value member itself
         members.pop(0)
     return members, not_covered
-
-def _power_of_two(value):
-    if value < 1:
-        return False
-    return value == 2 ** _high_bit(value)
diff --git a/Misc/NEWS.d/next/Library/2019-09-30-12-09-41.bpo-38045.VDRtd3.rst b/Misc/NEWS.d/next/Library/2019-09-30-12-09-41.bpo-38045.VDRtd3.rst
new file mode 100644 (file)
index 0000000..e7e515f
--- /dev/null
@@ -0,0 +1 @@
+Improve the performance of :func:`enum._decompose` in :mod:`enum`. Patch by hongweipeng.