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:
|
if not self.process or not self.process.stdout:
|
||||||
return ""
|
return ""
|
||||||
|
|
||||||
output = []
|
buf = b""
|
||||||
|
idle_timeout = 0.1 # return quickly once data stops flowing
|
||||||
|
overall_deadline = asyncio.get_event_loop().time() + 5.0
|
||||||
|
|
||||||
try:
|
try:
|
||||||
# Read byte by byte until we see "\n>"
|
|
||||||
while True:
|
while True:
|
||||||
byte = await asyncio.wait_for(self.process.stdout.read(1), timeout=5.0)
|
remaining = overall_deadline - asyncio.get_event_loop().time()
|
||||||
if not byte:
|
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 = []
|
|
||||||
break
|
break
|
||||||
|
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:
|
except TimeoutError:
|
||||||
# If we timeout, return what we got
|
|
||||||
pass
|
pass
|
||||||
|
|
||||||
result = "".join(output)
|
return buf.decode("latin-1").rstrip()
|
||||||
return result.rstrip()
|
|
||||||
|
|
||||||
|
|
||||||
async def broadcast_to_spectators(player: "Player", message: str) -> None:
|
async def broadcast_to_spectators(player: "Player", message: str) -> None:
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue