From a4bbe0434c50b653dc6e1da309927a178c2696a9 Mon Sep 17 00:00:00 2001 From: hkc Date: Tue, 9 Jul 2024 17:09:12 +0300 Subject: [PATCH] Optimized worker and manager --- swarm/manager.py | 12 ++++++-- swarm/settings.json | 32 --------------------- swarm/worker.py | 70 ++++++++++++++++++++++++++++----------------- 3 files changed, 53 insertions(+), 61 deletions(-) diff --git a/swarm/manager.py b/swarm/manager.py index 6a89410..fd3adad 100644 --- a/swarm/manager.py +++ b/swarm/manager.py @@ -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) diff --git a/swarm/settings.json b/swarm/settings.json index 82aae10..4ed26a1 100644 --- a/swarm/settings.json +++ b/swarm/settings.json @@ -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 } ] } diff --git a/swarm/worker.py b/swarm/worker.py index 4791d0a..eab958f 100644 --- a/swarm/worker.py +++ b/swarm/worker.py @@ -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): + index = random.randint(0, 999999) while True: - index = random.randint(0, 999999) - state = self.get_state(index) - if ( - not state.avoid - and state.mask - and (state.state != state.canvas) + 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)] )