Speed up IF reads with chunked I/O and short idle timeout
This commit is contained in:
parent
43fce6a4ed
commit
e8f16ca18a
1 changed files with 25 additions and 21 deletions
|
|
@ -170,34 +170,38 @@ class IFSession:
|
|||
if not self.process or not self.process.stdout:
|
||||
return ""
|
||||
|
||||
output = []
|
||||
buf = b""
|
||||
idle_timeout = 0.1 # return quickly once data stops flowing
|
||||
overall_deadline = asyncio.get_event_loop().time() + 5.0
|
||||
|
||||
try:
|
||||
# Read byte by byte until we see "\n>"
|
||||
while True:
|
||||
byte = await asyncio.wait_for(self.process.stdout.read(1), timeout=5.0)
|
||||
if not byte:
|
||||
remaining = overall_deadline - asyncio.get_event_loop().time()
|
||||
if remaining <= 0:
|
||||
break
|
||||
|
||||
char = byte.decode("latin-1")
|
||||
output.append(char)
|
||||
|
||||
# Check if we've hit the prompt
|
||||
# Prompt is "\n>" or just ">" at start
|
||||
if len(output) >= 2:
|
||||
if output[-2] == "\n" and output[-1] == ">":
|
||||
# Strip the trailing "\n>"
|
||||
output = output[:-2]
|
||||
break
|
||||
elif len(output) == 1 and output[0] == ">":
|
||||
# Prompt at very start
|
||||
output = []
|
||||
timeout = min(idle_timeout, remaining)
|
||||
try:
|
||||
chunk = await asyncio.wait_for(
|
||||
self.process.stdout.read(1024), timeout=timeout
|
||||
)
|
||||
except TimeoutError:
|
||||
# No data for idle_timeout - dfrotz is done talking
|
||||
break
|
||||
if not chunk:
|
||||
break
|
||||
buf += chunk
|
||||
|
||||
# Check for prompt at end of buffer
|
||||
text = buf.decode("latin-1")
|
||||
if text.endswith("\n>"):
|
||||
text = text[:-2]
|
||||
return text.rstrip()
|
||||
if text == ">":
|
||||
return ""
|
||||
except TimeoutError:
|
||||
# If we timeout, return what we got
|
||||
pass
|
||||
|
||||
result = "".join(output)
|
||||
return result.rstrip()
|
||||
return buf.decode("latin-1").rstrip()
|
||||
|
||||
|
||||
async def broadcast_to_spectators(player: "Player", message: str) -> None:
|
||||
|
|
|
|||
Loading…
Reference in a new issue