]> git.ipfire.org Git - thirdparty/Python/cpython.git/commitdiff
bpo-42160: tempfile: Reduce overhead of pid check. (GH-22997)
authorEric W <robo-eric@gmx.de>
Fri, 30 Oct 2020 04:56:28 +0000 (05:56 +0100)
committerGitHub <noreply@github.com>
Fri, 30 Oct 2020 04:56:28 +0000 (13:56 +0900)
The _RandomSequence class in tempfile used to check the current pid every time its rng property was used.
This commit replaces this code with `os.register_at_fork` to reduce the overhead.

Lib/tempfile.py
Lib/test/test_tempfile.py
Misc/NEWS.d/next/Library/2020-10-27-00-42-09.bpo-42160.eiLOCi.rst [new file with mode: 0644]

index 770f72c25295cbe756ef32b618682090e6b09b1b..1bc5c71fd03494477130e33e285a645e9d479e34 100644 (file)
@@ -129,24 +129,22 @@ class _RandomNameSequence:
 
     _RandomNameSequence is an iterator."""
 
-    characters = "abcdefghijklmnopqrstuvwxyz0123456789_"
-
-    @property
-    def rng(self):
-        cur_pid = _os.getpid()
-        if cur_pid != getattr(self, '_rng_pid', None):
-            self._rng = _Random()
-            self._rng_pid = cur_pid
-        return self._rng
+    def __init__(self, characters="abcdefghijklmnopqrstuvwxyz0123456789_", length=8, rng=None):
+        if rng is None:
+            rng = _Random()
+        if hasattr(_os, "fork"):
+            # prevent same state after fork
+            _os.register_at_fork(after_in_child=rng.seed)
+        self.rng = rng
+        self.characters = characters
+        self.length = length
 
     def __iter__(self):
         return self
 
     def __next__(self):
         c = self.characters
-        choose = self.rng.choice
-        letters = [choose(c) for dummy in range(8)]
-        return ''.join(letters)
+        return ''.join(self.rng.choices(c, k=self.length))
 
 def _candidate_tempdir_list():
     """Generate a list of candidate temporary directories which
index 8ace883d74bb24def59421a09671b1444e6b0756..77d710efaf107b9c91163dccd30ea7aebd07a854 100644 (file)
@@ -153,8 +153,8 @@ class TestRandomNameSequence(BaseTestCase):
         self.r = tempfile._RandomNameSequence()
         super().setUp()
 
-    def test_get_six_char_str(self):
-        # _RandomNameSequence returns a six-character string
+    def test_get_eight_char_str(self):
+        # _RandomNameSequence returns a eight-character string
         s = next(self.r)
         self.nameCheck(s, '', '', '')
 
diff --git a/Misc/NEWS.d/next/Library/2020-10-27-00-42-09.bpo-42160.eiLOCi.rst b/Misc/NEWS.d/next/Library/2020-10-27-00-42-09.bpo-42160.eiLOCi.rst
new file mode 100644 (file)
index 0000000..c5f3091
--- /dev/null
@@ -0,0 +1 @@
+Replaced pid check in ``tempfile._RandomNameSequence`` with ``os.register_at_fork`` to reduce overhead.