comparison mercurial/worker.py @ 49233:520722523955

worker: implement _blockingreader.readinto() (issue6444) The core logic for readinto() was already implemented in read(), so this is mostly extracting that code into its own method. Another fix for issue6444 was committed to the stable branch: 2fe4efaa59af. That is a minimal fix that implements readinto() only on Python versions that require readinto() (3.8.0 and 3.8.1), which is the right approach for the stable branch. However, I think that this changeset has its value. It improves performance in cases when pickle can use readinto(), it reduces code duplication compared to the other patch, and by defining readinto() on all Python versions, it makes behavior more consistent across all Python versions. This changesets reverts the other change.
author Manuel Jacob <me@manueljacob.de>
date Sun, 22 May 2022 00:10:58 +0200
parents 4c57ce494a4e
children 395f28064826
comparison
equal deleted inserted replaced
49232:4c57ce494a4e 49233:520722523955
77 """ 77 """
78 78
79 def __init__(self, wrapped): 79 def __init__(self, wrapped):
80 self._wrapped = wrapped 80 self._wrapped = wrapped
81 81
82 # Do NOT implement readinto() by making it delegate to
83 # _wrapped.readinto(), since that is unbuffered. The unpickler is fine
84 # with just read() and readline(), so we don't need to implement it.
85
86 if (3, 8, 0) <= sys.version_info[:3] < (3, 8, 2):
87
88 # This is required for python 3.8, prior to 3.8.2. See issue6444.
89 def readinto(self, b):
90 pos = 0
91 size = len(b)
92
93 while pos < size:
94 ret = self._wrapped.readinto(b[pos:])
95 if not ret:
96 break
97 pos += ret
98
99 return pos
100
101 def readline(self): 82 def readline(self):
102 return self._wrapped.readline() 83 return self._wrapped.readline()
103 84
104 # issue multiple reads until size is fulfilled (or EOF is encountered) 85 def readinto(self, buf):
105 def read(self, size=-1):
106 if size < 0:
107 return self._wrapped.readall()
108
109 buf = bytearray(size)
110 pos = 0 86 pos = 0
87 size = len(buf)
111 88
112 with memoryview(buf) as view: 89 with memoryview(buf) as view:
113 while pos < size: 90 while pos < size:
114 with view[pos:] as subview: 91 with view[pos:] as subview:
115 ret = self._wrapped.readinto(subview) 92 ret = self._wrapped.readinto(subview)
116 if not ret: 93 if not ret:
117 break 94 break
118 pos += ret 95 pos += ret
119 96
120 del buf[pos:] 97 return pos
98
99 # issue multiple reads until size is fulfilled (or EOF is encountered)
100 def read(self, size=-1):
101 if size < 0:
102 return self._wrapped.readall()
103
104 buf = bytearray(size)
105 n_read = self.readinto(buf)
106 del buf[n_read:]
121 return bytes(buf) 107 return bytes(buf)
122 108
123 109
124 if pycompat.isposix or pycompat.iswindows: 110 if pycompat.isposix or pycompat.iswindows:
125 _STARTUP_COST = 0.01 111 _STARTUP_COST = 0.01