chore: drop three scratch files a verification agent left behind
`_c131_cpu.py`, `_c131_micro.py` and `_c131_probe.py` were throwaway probes
written by a subagent while checking a README claim, and a7c8a7a swept them
in with `git add -A`. They are not part of the project and nothing imports
them.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 5
parent
a7c8a7a0b8
commit
776fe5bcf1
@@ -1,94 +0,0 @@
|
|||||||
"""CPU-time attribution for C131 (wall clock on this box is too noisy).
|
|
||||||
|
|
||||||
process_time() counts CPU across every thread of the process, so scheduler
|
|
||||||
jitter and the thread-pool handoff latency drop out and what is left is the
|
|
||||||
actual work each _async shape performs.
|
|
||||||
"""
|
|
||||||
from __future__ import annotations
|
|
||||||
|
|
||||||
import asyncio
|
|
||||||
import os
|
|
||||||
import statistics
|
|
||||||
import time
|
|
||||||
|
|
||||||
os.environ.setdefault("AUTOCAD_MCP_BACKEND", "ezdxf")
|
|
||||||
|
|
||||||
import config # noqa: E402
|
|
||||||
from backends.ezdxf_backend import EzdxfBackend # noqa: E402
|
|
||||||
|
|
||||||
CALLS = 4000
|
|
||||||
REPS = 9
|
|
||||||
SHIPPED = EzdxfBackend._async
|
|
||||||
|
|
||||||
|
|
||||||
def noop():
|
|
||||||
return None
|
|
||||||
|
|
||||||
|
|
||||||
async def task_no_waitfor(self, func, *a, **k):
|
|
||||||
timeout = config.settings.ezdxf_call_timeout
|
|
||||||
loop = asyncio.get_running_loop()
|
|
||||||
deadline = loop.time() + timeout
|
|
||||||
_ = max(deadline - loop.time(), 0.0)
|
|
||||||
lock = self._lock
|
|
||||||
await lock.acquire()
|
|
||||||
call = asyncio.ensure_future(asyncio.to_thread(func, *a, **k))
|
|
||||||
try:
|
|
||||||
result = await call
|
|
||||||
except BaseException:
|
|
||||||
lock.release()
|
|
||||||
raise
|
|
||||||
lock.release()
|
|
||||||
return result
|
|
||||||
|
|
||||||
|
|
||||||
async def naive_waitfor(self, func, *a, **k):
|
|
||||||
timeout = config.settings.ezdxf_call_timeout
|
|
||||||
async with self._lock:
|
|
||||||
return await asyncio.wait_for(asyncio.to_thread(func, *a, **k), timeout)
|
|
||||||
|
|
||||||
|
|
||||||
VARIANTS = [
|
|
||||||
("A shipped timeout path (2x wait_for + ensure_future)", SHIPPED, 120.0),
|
|
||||||
("B shipped no-timeout path (lock + to_thread) ", SHIPPED, 0.0),
|
|
||||||
("C timeout path, both wait_for removed ", task_no_waitfor, 120.0),
|
|
||||||
("D naive single wait_for on the coroutine ", naive_waitfor, 120.0),
|
|
||||||
]
|
|
||||||
|
|
||||||
|
|
||||||
async def run(impl, timeout, backend):
|
|
||||||
EzdxfBackend._async = impl
|
|
||||||
config.settings.ezdxf_call_timeout = timeout
|
|
||||||
try:
|
|
||||||
started = time.process_time()
|
|
||||||
for _ in range(CALLS):
|
|
||||||
await backend._async(noop)
|
|
||||||
return (time.process_time() - started) * 1e6 / CALLS
|
|
||||||
finally:
|
|
||||||
EzdxfBackend._async = SHIPPED
|
|
||||||
|
|
||||||
|
|
||||||
async def main():
|
|
||||||
backend = EzdxfBackend()
|
|
||||||
await backend.connect()
|
|
||||||
await run(SHIPPED, 120.0, backend)
|
|
||||||
samples = {label: [] for label, _, _ in VARIANTS}
|
|
||||||
for _ in range(REPS):
|
|
||||||
for label, impl, timeout in VARIANTS:
|
|
||||||
samples[label].append(await run(impl, timeout, backend))
|
|
||||||
med = {}
|
|
||||||
for label, _, _ in VARIANTS:
|
|
||||||
vals = sorted(samples[label])
|
|
||||||
med[label] = statistics.median(vals)
|
|
||||||
print(f"{label} {med[label]:7.1f} us cpu/call min {vals[0]:.0f} max {vals[-1]:.0f}")
|
|
||||||
a, b, c, d = (med[label] for label, _, _ in VARIANTS)
|
|
||||||
print()
|
|
||||||
print(f"timeout path overhead A-B : {a - b:6.1f} us cpu/call")
|
|
||||||
print(f"survives removing wait_for C-B : {c - b:6.1f} us cpu/call "
|
|
||||||
f"({(c - b) / (a - b) * 100:.0f}% of A-B)")
|
|
||||||
print(f"attributable to wait_for A-C : {a - c:6.1f} us cpu/call "
|
|
||||||
f"({(a - c) / (a - b) * 100:.0f}% of A-B)")
|
|
||||||
print(f"naive single wait_for D-B : {d - b:6.1f} us cpu/call")
|
|
||||||
|
|
||||||
|
|
||||||
asyncio.run(main())
|
|
||||||
@@ -1,98 +0,0 @@
|
|||||||
"""Micro-attribution for README claim C131: what does the timeout path cost?
|
|
||||||
|
|
||||||
Same four `_async` shapes, but the payload is a no-op so the delta is pure
|
|
||||||
async machinery. Interleaved, median of many reps.
|
|
||||||
"""
|
|
||||||
from __future__ import annotations
|
|
||||||
|
|
||||||
import asyncio
|
|
||||||
import os
|
|
||||||
import statistics
|
|
||||||
import time
|
|
||||||
|
|
||||||
os.environ.setdefault("AUTOCAD_MCP_BACKEND", "ezdxf")
|
|
||||||
|
|
||||||
import config # noqa: E402
|
|
||||||
from backends.ezdxf_backend import EzdxfBackend # noqa: E402
|
|
||||||
|
|
||||||
CALLS = 3000
|
|
||||||
REPS = 7
|
|
||||||
SHIPPED = EzdxfBackend._async
|
|
||||||
|
|
||||||
|
|
||||||
def noop():
|
|
||||||
return None
|
|
||||||
|
|
||||||
|
|
||||||
async def shipped_off(self, func, *a, **k):
|
|
||||||
async with self._lock:
|
|
||||||
return await asyncio.to_thread(func, *a, **k)
|
|
||||||
|
|
||||||
|
|
||||||
async def task_no_waitfor(self, func, *a, **k):
|
|
||||||
timeout = config.settings.ezdxf_call_timeout
|
|
||||||
loop = asyncio.get_running_loop()
|
|
||||||
deadline = loop.time() + timeout
|
|
||||||
_ = max(deadline - loop.time(), 0.0)
|
|
||||||
lock = self._lock
|
|
||||||
await lock.acquire()
|
|
||||||
call = asyncio.ensure_future(asyncio.to_thread(func, *a, **k))
|
|
||||||
try:
|
|
||||||
result = await call
|
|
||||||
except BaseException:
|
|
||||||
lock.release()
|
|
||||||
raise
|
|
||||||
lock.release()
|
|
||||||
return result
|
|
||||||
|
|
||||||
|
|
||||||
async def naive_waitfor(self, func, *a, **k):
|
|
||||||
timeout = config.settings.ezdxf_call_timeout
|
|
||||||
async with self._lock:
|
|
||||||
return await asyncio.wait_for(asyncio.to_thread(func, *a, **k), timeout)
|
|
||||||
|
|
||||||
|
|
||||||
VARIANTS = [
|
|
||||||
("A shipped timeout path (2x wait_for + ensure_future)", SHIPPED, 120.0),
|
|
||||||
("B shipped no-timeout path (lock + to_thread) ", SHIPPED, 0.0),
|
|
||||||
("C timeout path with both wait_for removed ", task_no_waitfor, 120.0),
|
|
||||||
("D naive single wait_for on the coroutine ", naive_waitfor, 120.0),
|
|
||||||
]
|
|
||||||
|
|
||||||
|
|
||||||
async def run(impl, timeout, backend):
|
|
||||||
EzdxfBackend._async = impl
|
|
||||||
config.settings.ezdxf_call_timeout = timeout
|
|
||||||
try:
|
|
||||||
started = time.perf_counter()
|
|
||||||
for _ in range(CALLS):
|
|
||||||
await backend._async(noop)
|
|
||||||
return (time.perf_counter() - started) * 1e6 / CALLS # us per call
|
|
||||||
finally:
|
|
||||||
EzdxfBackend._async = SHIPPED
|
|
||||||
|
|
||||||
|
|
||||||
async def main():
|
|
||||||
backend = EzdxfBackend()
|
|
||||||
await backend.connect()
|
|
||||||
await run(SHIPPED, 120.0, backend) # warm-up
|
|
||||||
samples = {label: [] for label, _, _ in VARIANTS}
|
|
||||||
for _ in range(REPS):
|
|
||||||
for label, impl, timeout in VARIANTS:
|
|
||||||
samples[label].append(await run(impl, timeout, backend))
|
|
||||||
med = {}
|
|
||||||
for label, _, _ in VARIANTS:
|
|
||||||
med[label] = statistics.median(samples[label])
|
|
||||||
print(f"{label} {med[label]:7.1f} us/call runs "
|
|
||||||
+ " ".join(f"{v:.0f}" for v in samples[label]))
|
|
||||||
a, b, c, d = (med[label] for label, _, _ in VARIANTS)
|
|
||||||
print()
|
|
||||||
print(f"timeout path total overhead A-B : {a - b:6.1f} us/call")
|
|
||||||
print(f"overhead with wait_for gone C-B : {c - b:6.1f} us/call "
|
|
||||||
f"({(c - b) / (a - b) * 100:.0f}% of it)")
|
|
||||||
print(f"cost of the wait_for wrappers A-C: {a - c:6.1f} us/call "
|
|
||||||
f"({(a - c) / (a - b) * 100:.0f}% of it)")
|
|
||||||
print(f"naive one-wait_for overhead D-B : {d - b:6.1f} us/call")
|
|
||||||
|
|
||||||
|
|
||||||
asyncio.run(main())
|
|
||||||
-120
@@ -1,120 +0,0 @@
|
|||||||
"""Read-only probe for README claim C131 (asyncio.wait_for attribution).
|
|
||||||
|
|
||||||
Interleaved A/B/C/D so warm-up and machine drift hit every variant equally.
|
|
||||||
"""
|
|
||||||
from __future__ import annotations
|
|
||||||
|
|
||||||
import asyncio
|
|
||||||
import os
|
|
||||||
import statistics
|
|
||||||
import time
|
|
||||||
|
|
||||||
os.environ.setdefault("AUTOCAD_MCP_BACKEND", "ezdxf")
|
|
||||||
|
|
||||||
import config # noqa: E402
|
|
||||||
from backends.ezdxf_backend import EzdxfBackend # noqa: E402
|
|
||||||
|
|
||||||
N = 2000
|
|
||||||
REPS = 5
|
|
||||||
|
|
||||||
SHIPPED = EzdxfBackend._async
|
|
||||||
|
|
||||||
|
|
||||||
async def build(backend: EzdxfBackend) -> float:
|
|
||||||
await backend.drawing_new()
|
|
||||||
started = time.perf_counter()
|
|
||||||
for index in range(N):
|
|
||||||
y = float(index % 100)
|
|
||||||
await backend.entity_create_line(0.0, y, 100.0, y + 1.0)
|
|
||||||
return (time.perf_counter() - started) * 1000.0
|
|
||||||
|
|
||||||
|
|
||||||
async def async_no_timeout(self, func, *args, **kwargs):
|
|
||||||
"""The shipped timeout<=0 branch: plain lock + to_thread, no wait_for."""
|
|
||||||
async with self._lock:
|
|
||||||
return await asyncio.to_thread(func, *args, **kwargs)
|
|
||||||
|
|
||||||
|
|
||||||
async def async_task_no_waitfor(self, func, *args, **kwargs):
|
|
||||||
"""Shipped timeout branch MINUS both wait_for wrappers.
|
|
||||||
|
|
||||||
Same lock acquire, same loop.time() bookkeeping, same ensure_future Task
|
|
||||||
around to_thread, same try/except/release -- only the two asyncio.wait_for
|
|
||||||
wrappers removed.
|
|
||||||
"""
|
|
||||||
timeout = config.settings.ezdxf_call_timeout
|
|
||||||
loop = asyncio.get_running_loop()
|
|
||||||
deadline = loop.time() + timeout
|
|
||||||
_ = max(deadline - loop.time(), 0.0)
|
|
||||||
lock = self._lock
|
|
||||||
await lock.acquire()
|
|
||||||
call = asyncio.ensure_future(asyncio.to_thread(func, *args, **kwargs))
|
|
||||||
try:
|
|
||||||
result = await call
|
|
||||||
except BaseException:
|
|
||||||
lock.release()
|
|
||||||
raise
|
|
||||||
lock.release()
|
|
||||||
return result
|
|
||||||
|
|
||||||
|
|
||||||
async def async_waitfor_only(self, func, *args, **kwargs):
|
|
||||||
"""Naive shape: plain `async with lock` + a single wait_for on the coroutine.
|
|
||||||
|
|
||||||
This is what "wrap every call in asyncio.wait_for" would look like if you
|
|
||||||
wrote it the obvious way -- wait_for does its own ensure_future internally.
|
|
||||||
"""
|
|
||||||
timeout = config.settings.ezdxf_call_timeout
|
|
||||||
async with self._lock:
|
|
||||||
return await asyncio.wait_for(asyncio.to_thread(func, *args, **kwargs), timeout)
|
|
||||||
|
|
||||||
|
|
||||||
VARIANTS = [
|
|
||||||
("A shipped, EZDXF_CALL_TIMEOUT=120", SHIPPED, 120.0),
|
|
||||||
("B shipped, EZDXF_CALL_TIMEOUT=0 ", SHIPPED, 0.0),
|
|
||||||
("C timeout branch minus wait_for ", async_task_no_waitfor, 120.0),
|
|
||||||
("D plain lock + to_thread ", async_no_timeout, 120.0),
|
|
||||||
("E naive single wait_for ", async_waitfor_only, 120.0),
|
|
||||||
]
|
|
||||||
|
|
||||||
|
|
||||||
async def one(impl, timeout):
|
|
||||||
EzdxfBackend._async = impl
|
|
||||||
config.settings.ezdxf_call_timeout = timeout
|
|
||||||
backend = EzdxfBackend()
|
|
||||||
await backend.connect()
|
|
||||||
try:
|
|
||||||
return await build(backend)
|
|
||||||
finally:
|
|
||||||
EzdxfBackend._async = SHIPPED
|
|
||||||
|
|
||||||
|
|
||||||
async def main():
|
|
||||||
print("python", os.sys.version.split()[0])
|
|
||||||
print("default EZDXF_CALL_TIMEOUT =", config.settings.ezdxf_call_timeout)
|
|
||||||
await one(SHIPPED, 120.0) # warm-up, discarded
|
|
||||||
samples = {label: [] for label, _, _ in VARIANTS}
|
|
||||||
for _ in range(REPS):
|
|
||||||
for label, impl, timeout in VARIANTS:
|
|
||||||
samples[label].append(await one(impl, timeout))
|
|
||||||
meds = {}
|
|
||||||
for label, _, _ in VARIANTS:
|
|
||||||
vals = samples[label]
|
|
||||||
meds[label] = statistics.median(vals)
|
|
||||||
print(f"{label} median {meds[label]:8.1f} ms runs "
|
|
||||||
+ " ".join(f"{v:.0f}" for v in vals))
|
|
||||||
a = meds["A shipped, EZDXF_CALL_TIMEOUT=120"]
|
|
||||||
b = meds["B shipped, EZDXF_CALL_TIMEOUT=0 "]
|
|
||||||
c = meds["C timeout branch minus wait_for "]
|
|
||||||
d = meds["D plain lock + to_thread "]
|
|
||||||
e = meds["E naive single wait_for "]
|
|
||||||
print()
|
|
||||||
print(f"naive wait_for over baseline (E-D) : {e - d:7.1f} ms ({(e/d-1)*100:5.1f}%)")
|
|
||||||
print(f"total timeout-branch overhead (A-B) : {a - b:7.1f} ms ({(a/b-1)*100:5.1f}%)")
|
|
||||||
print(f"overhead with wait_for removed (C-D): {c - d:7.1f} ms")
|
|
||||||
print(f"overhead attributable to wait_for : {a - c:7.1f} ms")
|
|
||||||
if a - b > 0:
|
|
||||||
print(f"wait_for share of the A-B delta : {(a - c)/(a - b)*100:5.0f}%")
|
|
||||||
|
|
||||||
|
|
||||||
asyncio.run(main())
|
|
||||||
Reference in New Issue
Block a user