using deque in a few places for efficiency

This commit is contained in:
Eric 2023-01-19 13:29:34 -08:00
parent 154e5f72b9
commit f61539275f
No known key found for this signature in database
GPG Key ID: 89C93F0F8D6D5A98
10 changed files with 1716 additions and 1632 deletions

View File

@ -4008,50 +4008,50 @@
"assets/src/ba_data/python/ba/_generated/__init__.py": "https://files.ballistica.net/cache/ba1/ee/e8/cad05aa531c7faf7ff7b96db7f6e",
"assets/src/ba_data/python/ba/_generated/enums.py": "https://files.ballistica.net/cache/ba1/1c/77/ac670a5118abdf8a7687af0e159b",
"ballisticacore-windows/Generic/BallisticaCore.ico": "https://files.ballistica.net/cache/ba1/89/c0/e32c7d2a35dc9aef57cc73b0911a",
"build/prefab/full/linux_arm64_gui/debug/ballisticacore": "https://files.ballistica.net/cache/ba1/2b/e0/d62298f03362b29b1d7e15319f9f",
"build/prefab/full/linux_arm64_gui/release/ballisticacore": "https://files.ballistica.net/cache/ba1/d0/db/4e877084f27207c687cb965c26f2",
"build/prefab/full/linux_arm64_server/debug/dist/ballisticacore_headless": "https://files.ballistica.net/cache/ba1/3e/e0/8f1b50fbd66f92c52984511f3663",
"build/prefab/full/linux_arm64_server/release/dist/ballisticacore_headless": "https://files.ballistica.net/cache/ba1/e0/18/86760bcace92207da35a3776d9f1",
"build/prefab/full/linux_x86_64_gui/debug/ballisticacore": "https://files.ballistica.net/cache/ba1/d7/62/c324bceefb32847929fc7acf463c",
"build/prefab/full/linux_x86_64_gui/release/ballisticacore": "https://files.ballistica.net/cache/ba1/4f/c0/3c4c12ae0e6c4cae936f70518490",
"build/prefab/full/linux_x86_64_server/debug/dist/ballisticacore_headless": "https://files.ballistica.net/cache/ba1/3e/8a/76fb94e739dc1abd304c7167e21d",
"build/prefab/full/linux_x86_64_server/release/dist/ballisticacore_headless": "https://files.ballistica.net/cache/ba1/f2/53/14f99c17acec8ec729a1e745c79c",
"build/prefab/full/mac_arm64_gui/debug/ballisticacore": "https://files.ballistica.net/cache/ba1/75/6b/4554a4cea11610211f913d223619",
"build/prefab/full/mac_arm64_gui/release/ballisticacore": "https://files.ballistica.net/cache/ba1/07/51/13a07fe150afd562218a8006ce76",
"build/prefab/full/mac_arm64_server/debug/dist/ballisticacore_headless": "https://files.ballistica.net/cache/ba1/52/33/2d9f49b297b8ff594dcc17d0f32f",
"build/prefab/full/mac_arm64_server/release/dist/ballisticacore_headless": "https://files.ballistica.net/cache/ba1/10/00/374c0b00b7dd3d5c21b282d46902",
"build/prefab/full/mac_x86_64_gui/debug/ballisticacore": "https://files.ballistica.net/cache/ba1/26/11/c4d90c60ca4f2cf15151a939124a",
"build/prefab/full/mac_x86_64_gui/release/ballisticacore": "https://files.ballistica.net/cache/ba1/29/64/746de9f0ac84f842222801c362a2",
"build/prefab/full/mac_x86_64_server/debug/dist/ballisticacore_headless": "https://files.ballistica.net/cache/ba1/86/98/43faaadafd9a2d7f268fbb3e9d49",
"build/prefab/full/mac_x86_64_server/release/dist/ballisticacore_headless": "https://files.ballistica.net/cache/ba1/1b/01/d3357b85faef1469067a2eba4ee6",
"build/prefab/full/windows_x86_gui/debug/BallisticaCore.exe": "https://files.ballistica.net/cache/ba1/17/82/7bc7a9b23dece50f91581da61a10",
"build/prefab/full/windows_x86_gui/release/BallisticaCore.exe": "https://files.ballistica.net/cache/ba1/10/33/80e50c50f6e6081ee729018c088d",
"build/prefab/full/windows_x86_server/debug/dist/BallisticaCoreHeadless.exe": "https://files.ballistica.net/cache/ba1/a2/5b/1a508cfac64802bc5359647f593e",
"build/prefab/full/windows_x86_server/release/dist/BallisticaCoreHeadless.exe": "https://files.ballistica.net/cache/ba1/5b/c3/3e2944f02aab59db9d6818a58066",
"build/prefab/lib/linux_arm64_gui/debug/libballisticacore_internal.a": "https://files.ballistica.net/cache/ba1/58/9d/6bfac8dfa89a40303d8ed3fbd979",
"build/prefab/lib/linux_arm64_gui/release/libballisticacore_internal.a": "https://files.ballistica.net/cache/ba1/48/d3/762370803cf51dc78281610925b0",
"build/prefab/lib/linux_arm64_server/debug/libballisticacore_internal.a": "https://files.ballistica.net/cache/ba1/55/1c/4a5e5dcf1060965a6268d75ca85d",
"build/prefab/lib/linux_arm64_server/release/libballisticacore_internal.a": "https://files.ballistica.net/cache/ba1/e2/ff/11cc9bb55cdef26f5c8bfe3e48b5",
"build/prefab/lib/linux_x86_64_gui/debug/libballisticacore_internal.a": "https://files.ballistica.net/cache/ba1/70/a6/9571c5f278487a043230cac2e7b7",
"build/prefab/lib/linux_x86_64_gui/release/libballisticacore_internal.a": "https://files.ballistica.net/cache/ba1/ce/bf/e8d377d882414498c904ef0d7196",
"build/prefab/lib/linux_x86_64_server/debug/libballisticacore_internal.a": "https://files.ballistica.net/cache/ba1/53/0a/cd2800c0f21e0841ecd2e22e24f3",
"build/prefab/lib/linux_x86_64_server/release/libballisticacore_internal.a": "https://files.ballistica.net/cache/ba1/01/bc/dba89ca8070a1b7ecb34352d737d",
"build/prefab/lib/mac_arm64_gui/debug/libballisticacore_internal.a": "https://files.ballistica.net/cache/ba1/34/79/44a55d426a00311c834db41e8246",
"build/prefab/lib/mac_arm64_gui/release/libballisticacore_internal.a": "https://files.ballistica.net/cache/ba1/20/aa/80da4a9785bcf06416b2d8a338e8",
"build/prefab/lib/mac_arm64_server/debug/libballisticacore_internal.a": "https://files.ballistica.net/cache/ba1/f2/03/dbb9b61aa3a5488cba6d8eb628e8",
"build/prefab/lib/mac_arm64_server/release/libballisticacore_internal.a": "https://files.ballistica.net/cache/ba1/60/f4/7e766850a0f24e099a641c1dd369",
"build/prefab/lib/mac_x86_64_gui/debug/libballisticacore_internal.a": "https://files.ballistica.net/cache/ba1/04/34/78bed4b7e83c48e370122c22108e",
"build/prefab/lib/mac_x86_64_gui/release/libballisticacore_internal.a": "https://files.ballistica.net/cache/ba1/1b/79/b617b139fcb528eaa7d56730e4c3",
"build/prefab/lib/mac_x86_64_server/debug/libballisticacore_internal.a": "https://files.ballistica.net/cache/ba1/da/b7/5041c7ea7b951ddfed1cabc599ff",
"build/prefab/lib/mac_x86_64_server/release/libballisticacore_internal.a": "https://files.ballistica.net/cache/ba1/c1/9c/06d199252fb5ce1d21db06488cc9",
"build/prefab/lib/windows/Debug_Win32/BallisticaCoreGenericInternal.lib": "https://files.ballistica.net/cache/ba1/57/e8/5c589728e4f3b0685595dfd9a732",
"build/prefab/lib/windows/Debug_Win32/BallisticaCoreGenericInternal.pdb": "https://files.ballistica.net/cache/ba1/f9/9c/d9132f91b3f02daeb581cdc6144b",
"build/prefab/lib/windows/Debug_Win32/BallisticaCoreHeadlessInternal.lib": "https://files.ballistica.net/cache/ba1/c7/dc/16cbdf63b6fbae771c97070d32b4",
"build/prefab/lib/windows/Debug_Win32/BallisticaCoreHeadlessInternal.pdb": "https://files.ballistica.net/cache/ba1/78/c9/df88a990bb9587d297f7b720e936",
"build/prefab/lib/windows/Release_Win32/BallisticaCoreGenericInternal.lib": "https://files.ballistica.net/cache/ba1/7b/ac/8f61cb2620f6c8646aebb8746392",
"build/prefab/lib/windows/Release_Win32/BallisticaCoreGenericInternal.pdb": "https://files.ballistica.net/cache/ba1/ee/31/7e1f0d67ad3004cc2e4e4cc18570",
"build/prefab/lib/windows/Release_Win32/BallisticaCoreHeadlessInternal.lib": "https://files.ballistica.net/cache/ba1/99/60/92ce6b353fef56eb7040d7bbee54",
"build/prefab/lib/windows/Release_Win32/BallisticaCoreHeadlessInternal.pdb": "https://files.ballistica.net/cache/ba1/af/e5/95ff75798915d83d20fdb453faf1",
"build/prefab/full/linux_arm64_gui/debug/ballisticacore": "https://files.ballistica.net/cache/ba1/82/d3/3715dc8f54d1353bab3493b785bc",
"build/prefab/full/linux_arm64_gui/release/ballisticacore": "https://files.ballistica.net/cache/ba1/21/a3/3d39047fbe2d7168fde9323461a3",
"build/prefab/full/linux_arm64_server/debug/dist/ballisticacore_headless": "https://files.ballistica.net/cache/ba1/fa/ae/0b8e3ea76ead98bcb1f91154adb4",
"build/prefab/full/linux_arm64_server/release/dist/ballisticacore_headless": "https://files.ballistica.net/cache/ba1/9a/de/2d3ea7b4b6b8d96fee70bc6ee51e",
"build/prefab/full/linux_x86_64_gui/debug/ballisticacore": "https://files.ballistica.net/cache/ba1/63/73/49be93777a8e46dd3379897eaee0",
"build/prefab/full/linux_x86_64_gui/release/ballisticacore": "https://files.ballistica.net/cache/ba1/bc/81/80bb7ab35ed92ce9e904874f38b9",
"build/prefab/full/linux_x86_64_server/debug/dist/ballisticacore_headless": "https://files.ballistica.net/cache/ba1/46/1d/18f4916b42ec3af78ca83e132be4",
"build/prefab/full/linux_x86_64_server/release/dist/ballisticacore_headless": "https://files.ballistica.net/cache/ba1/9f/38/5a8b30c0b79cecb834eb5348ff8d",
"build/prefab/full/mac_arm64_gui/debug/ballisticacore": "https://files.ballistica.net/cache/ba1/3e/76/8c1cea0d914d49a64bf721e49070",
"build/prefab/full/mac_arm64_gui/release/ballisticacore": "https://files.ballistica.net/cache/ba1/a4/a3/189278b9cd02c7c4255f96bc5bc2",
"build/prefab/full/mac_arm64_server/debug/dist/ballisticacore_headless": "https://files.ballistica.net/cache/ba1/60/2a/8f637d1dcf6e3b832c4770ed0c16",
"build/prefab/full/mac_arm64_server/release/dist/ballisticacore_headless": "https://files.ballistica.net/cache/ba1/01/28/20484d98b6b88ce8b56e28efcc80",
"build/prefab/full/mac_x86_64_gui/debug/ballisticacore": "https://files.ballistica.net/cache/ba1/50/a2/b54a80f3881e94c7fabeaaec7ad4",
"build/prefab/full/mac_x86_64_gui/release/ballisticacore": "https://files.ballistica.net/cache/ba1/b0/ab/7472dd6f3ae5bb06753f5df250ff",
"build/prefab/full/mac_x86_64_server/debug/dist/ballisticacore_headless": "https://files.ballistica.net/cache/ba1/8c/0a/35c89966441a7dd16f6543d540f3",
"build/prefab/full/mac_x86_64_server/release/dist/ballisticacore_headless": "https://files.ballistica.net/cache/ba1/e5/9c/43a7f214bacd6eab04ec30ebcafd",
"build/prefab/full/windows_x86_gui/debug/BallisticaCore.exe": "https://files.ballistica.net/cache/ba1/71/c7/781eae3a95730651fc8fef6e6346",
"build/prefab/full/windows_x86_gui/release/BallisticaCore.exe": "https://files.ballistica.net/cache/ba1/b2/a9/7bc2e2f656ddb8505f9f380033af",
"build/prefab/full/windows_x86_server/debug/dist/BallisticaCoreHeadless.exe": "https://files.ballistica.net/cache/ba1/c4/7c/6f8e20e6ec4788047a228a5d896f",
"build/prefab/full/windows_x86_server/release/dist/BallisticaCoreHeadless.exe": "https://files.ballistica.net/cache/ba1/3b/2e/48440d1ace2bc05e48eb9f56f63b",
"build/prefab/lib/linux_arm64_gui/debug/libballisticacore_internal.a": "https://files.ballistica.net/cache/ba1/34/66/0a1e0fece6b9ad87ac315a9ba9f3",
"build/prefab/lib/linux_arm64_gui/release/libballisticacore_internal.a": "https://files.ballistica.net/cache/ba1/6d/a4/4a1357b21f0bc128c9b5948061da",
"build/prefab/lib/linux_arm64_server/debug/libballisticacore_internal.a": "https://files.ballistica.net/cache/ba1/c1/23/405f68ec8c229549de5b0dad41eb",
"build/prefab/lib/linux_arm64_server/release/libballisticacore_internal.a": "https://files.ballistica.net/cache/ba1/aa/a5/c088252e71a395765f8bc0cdc028",
"build/prefab/lib/linux_x86_64_gui/debug/libballisticacore_internal.a": "https://files.ballistica.net/cache/ba1/0f/ba/196bbcd459b59e32e93c15a7c128",
"build/prefab/lib/linux_x86_64_gui/release/libballisticacore_internal.a": "https://files.ballistica.net/cache/ba1/39/d2/706b2ca75bae629545cc7eb0a8d5",
"build/prefab/lib/linux_x86_64_server/debug/libballisticacore_internal.a": "https://files.ballistica.net/cache/ba1/89/56/24c6be441e8b120eef698c467ce6",
"build/prefab/lib/linux_x86_64_server/release/libballisticacore_internal.a": "https://files.ballistica.net/cache/ba1/6b/11/b1c5fc90854821d7e63fafd6f664",
"build/prefab/lib/mac_arm64_gui/debug/libballisticacore_internal.a": "https://files.ballistica.net/cache/ba1/3c/a7/308c08a0ebd82d100505666b85d5",
"build/prefab/lib/mac_arm64_gui/release/libballisticacore_internal.a": "https://files.ballistica.net/cache/ba1/2e/83/abff53b7982976aa9c6edb39d22b",
"build/prefab/lib/mac_arm64_server/debug/libballisticacore_internal.a": "https://files.ballistica.net/cache/ba1/01/d2/b005ef960a6c9ba96c3d77fd005f",
"build/prefab/lib/mac_arm64_server/release/libballisticacore_internal.a": "https://files.ballistica.net/cache/ba1/dc/53/af455ca35433fba5018fb0a4ea10",
"build/prefab/lib/mac_x86_64_gui/debug/libballisticacore_internal.a": "https://files.ballistica.net/cache/ba1/e7/91/4c135c16252f54a325ca375a7f79",
"build/prefab/lib/mac_x86_64_gui/release/libballisticacore_internal.a": "https://files.ballistica.net/cache/ba1/65/95/85ac4196233bb9a6fbef9e10f431",
"build/prefab/lib/mac_x86_64_server/debug/libballisticacore_internal.a": "https://files.ballistica.net/cache/ba1/ac/0d/82b7132a360c91e386b070c38fa2",
"build/prefab/lib/mac_x86_64_server/release/libballisticacore_internal.a": "https://files.ballistica.net/cache/ba1/7d/43/7112b8b9467213a48880352a4ba2",
"build/prefab/lib/windows/Debug_Win32/BallisticaCoreGenericInternal.lib": "https://files.ballistica.net/cache/ba1/4c/8a/bfeae3274074681c9fcc50625029",
"build/prefab/lib/windows/Debug_Win32/BallisticaCoreGenericInternal.pdb": "https://files.ballistica.net/cache/ba1/0e/46/75aff046dbc4ac23208ab9b4774e",
"build/prefab/lib/windows/Debug_Win32/BallisticaCoreHeadlessInternal.lib": "https://files.ballistica.net/cache/ba1/81/5d/66dfda3a7d4428b8c7a3ed1ad17f",
"build/prefab/lib/windows/Debug_Win32/BallisticaCoreHeadlessInternal.pdb": "https://files.ballistica.net/cache/ba1/41/79/5be0ca4e66ab63ccfdb4f129ddcb",
"build/prefab/lib/windows/Release_Win32/BallisticaCoreGenericInternal.lib": "https://files.ballistica.net/cache/ba1/f2/0a/e8432743590dd423b723eb3f262f",
"build/prefab/lib/windows/Release_Win32/BallisticaCoreGenericInternal.pdb": "https://files.ballistica.net/cache/ba1/06/13/fc1c3c4b3acb2677a48e28ffae63",
"build/prefab/lib/windows/Release_Win32/BallisticaCoreHeadlessInternal.lib": "https://files.ballistica.net/cache/ba1/58/95/3a1c4831cd80b6516ad95301bb7d",
"build/prefab/lib/windows/Release_Win32/BallisticaCoreHeadlessInternal.pdb": "https://files.ballistica.net/cache/ba1/f3/08/8936bdf7db0abe3c438a1db84445",
"src/ballistica/generated/python_embedded/binding.inc": "https://files.ballistica.net/cache/ba1/23/ce/68396b1b7ec6d2f8425902148140",
"src/ballistica/generated/python_embedded/bootstrap.inc": "https://files.ballistica.net/cache/ba1/2d/4f/f4fe67827f36cd59cd5193333a02",
"src/ballistica/generated/python_embedded/bootstrap_monolithic.inc": "https://files.ballistica.net/cache/ba1/ef/c1/aa5f1aa10af89f5c0b1e616355fd"

View File

@ -1,3 +1,5 @@
### 1.7.20 (build 20999, api 7, 2023-01-19)
### 1.7.19 (build 20997, api 7, 2023-01-19)
- Fixes an issue where repeated curses could use incorrect countdown times (Thanks EraOSBeta!).
- Last manual party connect port is now saved. Previously, it always assumed the port to be 43210 (Thanks ritiek!).

View File

@ -47,7 +47,7 @@ def bootstrap() -> None:
# Give a soft warning if we're being used with a different binary
# version than we expect.
expected_build = 20997
expected_build = 20999
running_build: int = env['build_number']
if running_build != expected_build:
print(

View File

@ -4,6 +4,7 @@
from __future__ import annotations
import threading
from collections import deque
from typing import TYPE_CHECKING
import _ba
@ -68,7 +69,7 @@ class _MacMusicAppThread(threading.Thread):
def __init__(self) -> None:
super().__init__()
self._commands_available = threading.Event()
self._commands: list[list] = []
self._commands = deque[list]()
self._volume = 1.0
self._current_playlist: str | None = None
self._orig_volume: int | None = None
@ -109,7 +110,7 @@ class _MacMusicAppThread(threading.Thread):
# We're not protecting this list with a mutex but we're
# just using it as a simple queue so it should be fine.
while self._commands:
cmd = self._commands.pop(0)
cmd = self._commands.popleft()
if cmd[0] == 'DIE':
self._handle_die_command()
done = True

File diff suppressed because it is too large Load Diff

View File

@ -211,9 +211,8 @@ class PartyWindow(ba.Window):
flatness=1.0,
)
self._chat_texts.append(txt)
if len(self._chat_texts) > 40:
first = self._chat_texts.pop(0)
first.delete()
while len(self._chat_texts) > 40:
self._chat_texts.pop(0).delete()
ba.containerwidget(edit=self._columnwidget, visible_child=txt)
def _on_menu_button_press(self) -> None:

View File

@ -32,8 +32,8 @@
namespace ballistica {
// These are set automatically via script; don't modify them here.
const int kAppBuildNumber = 20997;
const char* kAppVersion = "1.7.19";
const int kAppBuildNumber = 20999;
const char* kAppVersion = "1.7.20";
// Our standalone globals.
// These are separated out for easy access.

View File

@ -8,7 +8,9 @@ import time
import asyncio
import logging
import datetime
import itertools
from enum import Enum
from collections import deque
from dataclasses import dataclass
from typing import TYPE_CHECKING, Annotated
from threading import Thread, current_thread, Lock
@ -143,7 +145,7 @@ class LogHandler(logging.Handler):
assert cache_size_limit >= 0
self._cache_size_limit = cache_size_limit
self._cache_time_limit = cache_time_limit
self._cache: list[tuple[int, LogEntry]] = []
self._cache = deque[tuple[int, LogEntry]]()
self._cache_index_offset = 0
self._cache_lock = Lock()
self._printed_callback_error = False
@ -200,7 +202,7 @@ class LogHandler(logging.Handler):
self._cache
and (now - self._cache[0][1].time) >= self._cache_time_limit
):
popped = self._cache.pop(0)
popped = self._cache.popleft()
self._cache_size -= popped[0]
self._cache_index_offset += 1
@ -236,22 +238,40 @@ class LogHandler(logging.Handler):
return LogArchive(
log_size=self._cache_index_offset + len(self._cache),
start_index=start_index + self._cache_index_offset,
entries=[e[1] for e in self._cache[start_index:end_index]],
entries=self._cache_slice(start_index, end_index),
)
def _cache_slice(
self, start: int, end: int, step: int = 1
) -> list[LogEntry]:
# Deque doesn't natively support slicing but we can do it manually.
# It sounds like rotating the deque and pulling from the beginning
# is the most efficient way to do this. The downside is the deque
# gets temporarily modified in the process so we need to make sure
# we're holding the lock.
assert self._cache_lock.locked()
cache = self._cache
cache.rotate(-start)
slc = [e[1] for e in itertools.islice(cache, 0, end - start, step)]
cache.rotate(start)
return slc
@classmethod
def _is_immutable_log_data(cls, data: Any) -> bool:
if isinstance(data, (str, bool, int, float, bytes)):
return True
if isinstance(data, tuple):
return all(cls._is_immutable_log_data(x) for x in data)
return False
def emit(self, record: logging.LogRecord) -> None:
if __debug__:
starttime = time.monotonic()
# Called by logging to send us records.
# We simply package them up and ship them to our thread.
# UPDATE: turns out we CAN get log messages from this thread
# (the C++ layer can spit out some performance metrics when
# calls take too long/etc.)
# assert current_thread() is not self._thread
# Special case - filter out this common extra-chatty category.
# TODO - should use a standard logging.Filter for this.
# Special case: filter out this common extra-chatty category.
# TODO - perhaps should use a standard logging.Filter for this.
if (
self._suppress_non_root_debug
and record.name != 'root'
@ -259,40 +279,60 @@ class LogHandler(logging.Handler):
):
return
# We want to forward as much as we can along without processing it
# (better to do so in a bg thread).
# However its probably best to flatten the message string here since
# it could cause problems stringifying things in threads where they
# didn't expect to be stringified.
msg = self.format(record)
if __debug__:
formattime = time.monotonic()
# Also immediately print pretty colored output to our echo file
# (generally stderr). We do this part here instead of in our bg
# thread because the delay can throw off command line prompts or
# make tight debugging harder.
if self._echofile is not None:
ends = LEVELNO_COLOR_CODES.get(record.levelno)
if ends is not None:
self._echofile.write(f'{ends[0]}{msg}{ends[1]}\n')
else:
self._echofile.write(f'{msg}\n')
if __debug__:
echotime = time.monotonic()
self._event_loop.call_soon_threadsafe(
tpartial(
self._emit_in_thread,
record.name,
record.levelno,
record.created,
msg,
)
# Optimization: if our log args are all simple immutable values,
# we can just kick the whole thing over to our background thread to
# be formatted there at our leisure. If anything is mutable and
# thus could possibly change between now and then or if we want
# to do immediate file echoing then we need to bite the bullet
# and do that stuff here at the call site.
fast_path = self._echofile is None and self._is_immutable_log_data(
record.args
)
if fast_path:
if __debug__:
formattime = echotime = time.monotonic()
self._event_loop.call_soon_threadsafe(
tpartial(
self._emit_in_thread,
record.name,
record.levelno,
record.created,
record,
)
)
else:
# Slow case; do formatting and echoing here at the log call
# site.
msg = self.format(record)
if __debug__:
formattime = time.monotonic()
# Also immediately print pretty colored output to our echo file
# (generally stderr). We do this part here instead of in our bg
# thread because the delay can throw off command line prompts or
# make tight debugging harder.
if self._echofile is not None:
ends = LEVELNO_COLOR_CODES.get(record.levelno)
if ends is not None:
self._echofile.write(f'{ends[0]}{msg}{ends[1]}\n')
else:
self._echofile.write(f'{msg}\n')
if __debug__:
echotime = time.monotonic()
self._event_loop.call_soon_threadsafe(
tpartial(
self._emit_in_thread,
record.name,
record.levelno,
record.created,
msg,
)
)
if __debug__:
# Make noise if we're taking a significant amount of time here.
# Limit the noise to once every so often though; otherwise we
@ -317,17 +357,28 @@ class LogHandler(logging.Handler):
tpartial(
logging.warning,
'efro.log.LogHandler emit took too long'
' (%.2fs total; %.2fs format, %.2fs echo).',
' (%.2fs total; %.2fs format, %.2fs echo,'
' fast_path=%s).',
duration,
format_duration,
echo_duration,
fast_path,
)
)
def _emit_in_thread(
self, name: str, levelno: int, created: float, message: str
self,
name: str,
levelno: int,
created: float,
message: str | logging.LogRecord,
) -> None:
try:
# If they passed a raw record here, bake it down to a string.
if isinstance(message, logging.LogRecord):
message = self.format(message)
self._emit_entry(
LogEntry(
name=name,
@ -446,7 +497,7 @@ class LogHandler(logging.Handler):
# Prune old until we are back at or under our limit.
while self._cache_size > self._cache_size_limit:
popped = self._cache.pop(0)
popped = self._cache.popleft()
self._cache_size -= popped[0]
self._cache_index_offset += 1
@ -506,6 +557,7 @@ def setup_logging(
level: LogLevel,
suppress_non_root_debug: bool = False,
log_stdout_stderr: bool = False,
echo_to_stderr: bool = True,
cache_size_limit: int = 0,
cache_time_limit: datetime.timedelta | None = None,
) -> LogHandler:
@ -536,8 +588,7 @@ def setup_logging(
# which would create an infinite loop.
loghandler = LogHandler(
log_path,
# echofile=sys.stderr if sys.stderr.isatty() else None,
echofile=sys.stderr,
echofile=sys.stderr if echo_to_stderr else None,
suppress_non_root_debug=suppress_non_root_debug,
cache_size_limit=cache_size_limit,
cache_time_limit=cache_time_limit,

View File

@ -9,6 +9,7 @@ import asyncio
import logging
import weakref
from enum import Enum
from collections import deque
from dataclasses import dataclass
from threading import current_thread
from typing import TYPE_CHECKING, Annotated
@ -201,7 +202,7 @@ class RPCEndpoint:
self._closing = False
self._did_wait_closed = False
self._event_loop = asyncio.get_running_loop()
self._out_packets: list[bytes] = []
self._out_packets = deque[bytes]()
self._have_out_packets = asyncio.Event()
self._run_called = False
self._peer_info: _PeerInfo | None = None
@ -758,7 +759,7 @@ class RPCEndpoint:
await self._have_out_packets.wait()
assert self._out_packets
data = self._out_packets.pop(0)
data = self._out_packets.popleft()
# Important: only clear this once all packets are sent.
if not self._out_packets:

View File

@ -5,6 +5,7 @@
from __future__ import annotations
import logging
from collections import deque
from typing import TYPE_CHECKING
from threading import Condition, Thread
import os
@ -23,7 +24,7 @@ class _FileBatchesRun:
) -> None:
self.condition = Condition()
self.paths = paths
self.batches: list[list[str]] = []
self.batches = deque[list[str]]()
self.batch_size = batch_size
self.done = False
self.errored = False
@ -141,7 +142,7 @@ def file_batches(
if run.errored:
raise RuntimeError('BG batch run errored.')
while run.batches:
yield run.batches.pop(0)
yield run.batches.popleft()
if run.done:
break
except GeneratorExit: