Optimized worker and manager

This commit is contained in:
Casey 2024-07-09 17:09:12 +03:00
parent d8853bf247
commit a4bbe0434c
Signed by: hkc
GPG Key ID: F0F6CFE11CDB0960
3 changed files with 53 additions and 61 deletions

View File

@ -78,9 +78,11 @@ class Manager:
elif avoid["type"] == "image":
with Image.open(avoid["path"]).convert("LA") as im:
assert im.width == 1000 and im.height == 1000
pixels = im.load()
assert pixels is not None
for y in range(im.height):
for x in range(im.width):
_, a = im.getpixel((x, y)) # type: ignore
_, a = pixels[(x, y)] # type: ignore
if a > 128:
self.add_avoid_index(x + y * 1000)
else:
@ -328,9 +330,11 @@ class Manager:
def add_avoid_image(self, im: Image.Image):
assert im.width == 1000
assert im.height == 1000
pixels = im.load()
assert pixels is not None
for i in range(1000000):
y, x = divmod(i, 1000)
la = im.getpixel((x, y))
la = pixels[(x, y)]
assert isinstance(la, (tuple, list)) and len(la) == 2
if la[1] > 128:
self.add_avoid_index(i)
@ -353,9 +357,11 @@ class Manager:
self.shmem.buf[OFFSET_CANVAS + byte] &= 0xFF ^ (0x80 >> bit)
def put_image(self, ox: int, oy: int, im: Image.Image):
pixels = im.load()
assert pixels is not None
for y in range(im.height):
for x in range(im.width):
la: tuple[int, int] = im.getpixel((x, y)) # type: ignore
la: tuple[int, int] = pixels[(x, y)] # type: ignore
if la[1]:
self.set_index(x + ox + (y + oy) * 1000, la[0] > 0)

View File

@ -74,38 +74,6 @@
"path": "../pictures/hueh.png",
"x": 490,
"y": 810
},
{
"type": "text_anim",
"font": "/usr/share/fonts/TTF/TerminusTTF.ttf",
"size": 18,
"lines": [
рипер2004",
"Крипер2004",
"КРипер2004",
"КРИпер2004",
"КРИПер2004",
"КРИПЕр2004",
"КРИПЕР2004",
РИПЕР2004",
рИПЕР2004",
риПЕР2004",
рипЕР2004",
рипеР2004",
рипер2004"
],
"spf": 30,
"x": 3,
"y": 872
},
{
"type": "shrek",
"font": "../creep2.ttf",
"size": 11,
"path": "../funnies/shrek.txt",
"x": 490,
"y": 700,
"spf": 120
}
]
}

View File

@ -6,7 +6,7 @@ from typing import NamedTuple, Optional
from aiohttp_socks import ProxyConnector
import socketio
import aiohttp
import signal
import time
OFFSET_STATE = 0
OFFSET_AVOID = 125000
@ -26,16 +26,25 @@ class WorkerManager:
self.shmem_name = shmem_name
self.base = "https://onemillioncheckboxes.com"
self.delay = 0.25
self.queue: asyncio.Queue[int] = asyncio.Queue(128)
self.queue: asyncio.Queue[int] = asyncio.Queue(64)
self.n_toggles = 0
async def queue_manager(self):
while True:
index = random.randint(0, 999999)
state = self.get_state(index)
if (
not state.avoid
and state.mask
and (state.state != state.canvas)
while True:
index = (index + 1) % 1000000
byte, bit = divmod(index, 8)
mask = 0x80 >> bit
if self.shmem.buf[OFFSET_AVOID + byte] & mask:
continue
if (self.shmem.buf[OFFSET_MASK + byte] & mask) == 0:
continue
if (self.shmem.buf[OFFSET_CANVAS + byte] & mask) != (
self.shmem.buf[OFFSET_STATE + byte] & mask
):
await self.queue.put(index)
@ -51,19 +60,23 @@ class WorkerManager:
print("Connected and running")
while sio.connected:
index = await self.queue.get()
state = self.get_state(index)
if (
not state.avoid
and state.mask
and (state.state != state.canvas)
byte, bit = divmod(index, 8)
mask = 0x80 >> bit
if self.shmem.buf[OFFSET_AVOID + byte] & mask:
continue
if (self.shmem.buf[OFFSET_MASK + byte] & mask) == 0:
continue
if (self.shmem.buf[OFFSET_CANVAS + byte] & mask) != (
self.shmem.buf[OFFSET_STATE + byte] & mask
):
byte, bit = divmod(index, 8)
print("toggle", index)
self.n_toggles += 1
self.shmem.buf[OFFSET_STATE + byte] ^= 0x80 >> bit
await sio.emit("toggle_bit", {"index": index})
await asyncio.sleep(self.delay)
await asyncio.sleep(0.1)
print("Writer closed")
sio.on("connect", writer_itself)
@ -71,15 +84,18 @@ class WorkerManager:
await sio.connect(self.base.replace("http", "ws"))
await sio.wait()
def get_state(self, index: int) -> PixelState:
byte, bit = divmod(index, 8)
mask = 0x80 >> bit
return PixelState(
self.shmem.buf[OFFSET_STATE + byte] & mask != 0,
self.shmem.buf[OFFSET_AVOID + byte] & mask != 0,
self.shmem.buf[OFFSET_CANVAS + byte] & mask != 0,
self.shmem.buf[OFFSET_MASK + byte] & mask != 0,
)
async def status_display(self):
last_printout = time.time()
while True:
await asyncio.sleep(1)
diff = time.time() - last_printout
print()
print(f"Queue size: {self.queue.qsize()}/{self.queue.maxsize}")
print(f"Toggles: {self.n_toggles / diff:.2f}/s")
self.n_toggles = 0
last_printout = time.time()
async def __aenter__(self):
self.shmem = SharedMemory(self.shmem_name)
@ -92,7 +108,9 @@ class WorkerManager:
async def main():
async with WorkerManager() as mgr:
await asyncio.gather(
mgr.queue_manager(), *[mgr.writer(i) for i in range(4)]
mgr.queue_manager(),
mgr.status_display(),
*[mgr.writer(i) for i in range(4)]
)