Optimized worker and manager
This commit is contained in:
parent
d8853bf247
commit
a4bbe0434c
|
@ -78,9 +78,11 @@ class Manager:
|
||||||
elif avoid["type"] == "image":
|
elif avoid["type"] == "image":
|
||||||
with Image.open(avoid["path"]).convert("LA") as im:
|
with Image.open(avoid["path"]).convert("LA") as im:
|
||||||
assert im.width == 1000 and im.height == 1000
|
assert im.width == 1000 and im.height == 1000
|
||||||
|
pixels = im.load()
|
||||||
|
assert pixels is not None
|
||||||
for y in range(im.height):
|
for y in range(im.height):
|
||||||
for x in range(im.width):
|
for x in range(im.width):
|
||||||
_, a = im.getpixel((x, y)) # type: ignore
|
_, a = pixels[(x, y)] # type: ignore
|
||||||
if a > 128:
|
if a > 128:
|
||||||
self.add_avoid_index(x + y * 1000)
|
self.add_avoid_index(x + y * 1000)
|
||||||
else:
|
else:
|
||||||
|
@ -328,9 +330,11 @@ class Manager:
|
||||||
def add_avoid_image(self, im: Image.Image):
|
def add_avoid_image(self, im: Image.Image):
|
||||||
assert im.width == 1000
|
assert im.width == 1000
|
||||||
assert im.height == 1000
|
assert im.height == 1000
|
||||||
|
pixels = im.load()
|
||||||
|
assert pixels is not None
|
||||||
for i in range(1000000):
|
for i in range(1000000):
|
||||||
y, x = divmod(i, 1000)
|
y, x = divmod(i, 1000)
|
||||||
la = im.getpixel((x, y))
|
la = pixels[(x, y)]
|
||||||
assert isinstance(la, (tuple, list)) and len(la) == 2
|
assert isinstance(la, (tuple, list)) and len(la) == 2
|
||||||
if la[1] > 128:
|
if la[1] > 128:
|
||||||
self.add_avoid_index(i)
|
self.add_avoid_index(i)
|
||||||
|
@ -353,9 +357,11 @@ class Manager:
|
||||||
self.shmem.buf[OFFSET_CANVAS + byte] &= 0xFF ^ (0x80 >> bit)
|
self.shmem.buf[OFFSET_CANVAS + byte] &= 0xFF ^ (0x80 >> bit)
|
||||||
|
|
||||||
def put_image(self, ox: int, oy: int, im: Image.Image):
|
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 y in range(im.height):
|
||||||
for x in range(im.width):
|
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]:
|
if la[1]:
|
||||||
self.set_index(x + ox + (y + oy) * 1000, la[0] > 0)
|
self.set_index(x + ox + (y + oy) * 1000, la[0] > 0)
|
||||||
|
|
||||||
|
|
|
@ -74,38 +74,6 @@
|
||||||
"path": "../pictures/hueh.png",
|
"path": "../pictures/hueh.png",
|
||||||
"x": 490,
|
"x": 490,
|
||||||
"y": 810
|
"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
|
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|
|
@ -6,7 +6,7 @@ from typing import NamedTuple, Optional
|
||||||
from aiohttp_socks import ProxyConnector
|
from aiohttp_socks import ProxyConnector
|
||||||
import socketio
|
import socketio
|
||||||
import aiohttp
|
import aiohttp
|
||||||
import signal
|
import time
|
||||||
|
|
||||||
OFFSET_STATE = 0
|
OFFSET_STATE = 0
|
||||||
OFFSET_AVOID = 125000
|
OFFSET_AVOID = 125000
|
||||||
|
@ -26,16 +26,25 @@ class WorkerManager:
|
||||||
self.shmem_name = shmem_name
|
self.shmem_name = shmem_name
|
||||||
self.base = "https://onemillioncheckboxes.com"
|
self.base = "https://onemillioncheckboxes.com"
|
||||||
self.delay = 0.25
|
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):
|
async def queue_manager(self):
|
||||||
while True:
|
|
||||||
index = random.randint(0, 999999)
|
index = random.randint(0, 999999)
|
||||||
state = self.get_state(index)
|
while True:
|
||||||
if (
|
index = (index + 1) % 1000000
|
||||||
not state.avoid
|
byte, bit = divmod(index, 8)
|
||||||
and state.mask
|
mask = 0x80 >> bit
|
||||||
and (state.state != state.canvas)
|
|
||||||
|
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)
|
await self.queue.put(index)
|
||||||
|
|
||||||
|
@ -51,19 +60,23 @@ class WorkerManager:
|
||||||
print("Connected and running")
|
print("Connected and running")
|
||||||
while sio.connected:
|
while sio.connected:
|
||||||
index = await self.queue.get()
|
index = await self.queue.get()
|
||||||
state = self.get_state(index)
|
byte, bit = divmod(index, 8)
|
||||||
if (
|
mask = 0x80 >> bit
|
||||||
not state.avoid
|
|
||||||
and state.mask
|
if self.shmem.buf[OFFSET_AVOID + byte] & mask:
|
||||||
and (state.state != state.canvas)
|
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)
|
byte, bit = divmod(index, 8)
|
||||||
print("toggle", index)
|
self.n_toggles += 1
|
||||||
self.shmem.buf[OFFSET_STATE + byte] ^= 0x80 >> bit
|
self.shmem.buf[OFFSET_STATE + byte] ^= 0x80 >> bit
|
||||||
await sio.emit("toggle_bit", {"index": index})
|
await sio.emit("toggle_bit", {"index": index})
|
||||||
await asyncio.sleep(self.delay)
|
await asyncio.sleep(self.delay)
|
||||||
|
|
||||||
await asyncio.sleep(0.1)
|
|
||||||
print("Writer closed")
|
print("Writer closed")
|
||||||
|
|
||||||
sio.on("connect", writer_itself)
|
sio.on("connect", writer_itself)
|
||||||
|
@ -71,15 +84,18 @@ class WorkerManager:
|
||||||
await sio.connect(self.base.replace("http", "ws"))
|
await sio.connect(self.base.replace("http", "ws"))
|
||||||
await sio.wait()
|
await sio.wait()
|
||||||
|
|
||||||
def get_state(self, index: int) -> PixelState:
|
async def status_display(self):
|
||||||
byte, bit = divmod(index, 8)
|
last_printout = time.time()
|
||||||
mask = 0x80 >> bit
|
while True:
|
||||||
return PixelState(
|
await asyncio.sleep(1)
|
||||||
self.shmem.buf[OFFSET_STATE + byte] & mask != 0,
|
diff = time.time() - last_printout
|
||||||
self.shmem.buf[OFFSET_AVOID + byte] & mask != 0,
|
|
||||||
self.shmem.buf[OFFSET_CANVAS + byte] & mask != 0,
|
print()
|
||||||
self.shmem.buf[OFFSET_MASK + byte] & mask != 0,
|
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):
|
async def __aenter__(self):
|
||||||
self.shmem = SharedMemory(self.shmem_name)
|
self.shmem = SharedMemory(self.shmem_name)
|
||||||
|
@ -92,7 +108,9 @@ class WorkerManager:
|
||||||
async def main():
|
async def main():
|
||||||
async with WorkerManager() as mgr:
|
async with WorkerManager() as mgr:
|
||||||
await asyncio.gather(
|
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)]
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue