shows high-CPU C code hogging the GIL
if you remove the with nogil
decorator in loop.pyx this behaves Badly
#!/usr/bin/env python | |
import threading, asyncio, time, multiprocessing | |
import loop | |
def threadmain(count: int = 100, kind: str = 'thread'): | |
for i in range(count): | |
time.sleep(0.01) | |
if i % 10 == 0: | |
print(kind, i) | |
def cpu_sleep(): | |
print('starting cpu_sleep') | |
t0 = time.time() | |
print('iters', loop.cpu_sleep(2000)) | |
print('cpu_sleep', time.time() - t0) | |
async def asyncmain(count: int = 100): | |
# await asyncio.create_task(cpu_sleep()) | |
for i in range(count): | |
await asyncio.sleep(0.01) | |
if i % 10 == 0: | |
print('async', i) | |
def main(): | |
tasks = [ | |
threading.Thread(target=threadmain), | |
multiprocessing.Process(target=threadmain, kwargs={'kind': 'proc'}), | |
threading.Thread(target=cpu_sleep), | |
threading.Thread(target=cpu_sleep), | |
] | |
for t in tasks: t.start() | |
asyncio.run(asyncmain()) | |
for t in tasks: t.join() | |
print('ok joins') | |
if __name__ == '__main__': | |
main() |
import cython | |
from posix.time cimport timespec, clock_gettime, CLOCK_REALTIME, time_t | |
cdef int to_millis(timespec* t) nogil: | |
return (t.tv_sec * 1000) + (t.tv_nsec // 1000000) | |
cdef int diff(timespec* a, timespec* b) nogil: | |
"return diff in milliseconds" | |
return to_millis(b) - to_millis(a) | |
cdef int _cpu_sleep(int milliseconds) nogil: | |
cdef timespec base, latest; | |
clock_gettime(CLOCK_REALTIME, &base) | |
clock_gettime(CLOCK_REALTIME, &latest) | |
cdef unsigned int iter = 0 | |
cdef int elapsed = diff(&base, &latest) | |
cdef int ratchet = 0 | |
while elapsed < milliseconds: | |
iter += 1 | |
clock_gettime(CLOCK_REALTIME, &latest) | |
elapsed = diff(&base, &latest) | |
if elapsed > ratchet + 100: | |
ratchet += 100 | |
# print('elapsed', ratchet) | |
return iter | |
def cpu_sleep(int milliseconds): | |
cdef int ret | |
# without nogil, this blocks python | |
with nogil: | |
ret = _cpu_sleep(milliseconds) | |
return ret |
loop.cpython-310-x86_64-linux-gnu.so: loop.pyx | |
cythonize -i $^ |