When I run this little main from rfxcom python library :
from asyncio import get_event_loop
from rfxcom.transport import AsyncioTransport
dev_name = '/dev/serial/by-id/usb-RFXCOM_RFXtrx433_A1XZI13O-if00-port0'
loop = get_event_loop()
def handler(packet):
print(packet.data)
try:
rfxcom = AsyncioTransport(dev_name, loop, callback=handler)
loop.run_forever()
finally:
loop.close()
I see that CPU usage is getting very hight (around 100%). I can't understand why : there is very few messages (~ 1 message every 5 seconds) received by the module, and I thought that when epoll_wait was called then the CPU should be idled, waiting for the next event.
I launched the main with python cProfile, and it shows this :
In [4]: s.sort_stats('time', 'module').print_stats(50)
Mon Jul 20 22:20:55 2015 rfxcom_profile.log
263629453 function calls (263628703 primitive calls) in 145.437 seconds
Ordered by: internal time, file name
List reduced from 857 to 50 due to restriction <50>
ncalls tottime percall cumtime percall filename:lineno(function)
13178675 37.280 0.000 141.337 0.000 /usr/local/lib/python3.4/asyncio/base_events.py:1076(_run_once)
13178675 31.114 0.000 53.230 0.000 /usr/local/lib/python3.4/selectors.py:415(select)
13178674 15.115 0.000 32.253 0.000 /usr/local/lib/python3.4/asyncio/selector_events.py:479(_process_events)
13178675 12.582 0.000 12.582 0.000 {method 'poll' of 'select.epoll' objects}
13178699 11.462 0.000 17.138 0.000 /usr/local/lib/python3.4/asyncio/base_events.py:1058(_add_callback)
13178732 6.397 0.000 11.397 0.000 /usr/local/lib/python3.4/asyncio/events.py:118(_run)
26359349 4.872 0.000 4.872 0.000 {built-in method isinstance}
1 4.029 4.029 145.365 145.365 /usr/local/lib/python3.4/asyncio/base_events.py:267(run_forever)
13178669 4.010 0.000 4.913 0.000 /home/bruno/src/DomoPyc/venv/lib/python3.4/site-packages/rfxcom-0.3.0-py3.4.egg/rfxcom/transport/asyncio.py:85(_writer)
So the first three function calls in term of elapsed time are python3.4/asyncio/base_events.py
, python3.4/selectors.py
and python3.4/asyncio/selector_events.py
.
EDIT : the time command on a similar run gives :
time python -m cProfile -o rfxcom_profile.log rfxcom_profile.py
real 2m24.548s
user 2m19.892s
sys 0m4.113s
Can someone explain me why ?
EDIT2: As the the number of fonctions calls is very high, I made a strace of the process and found that there is a loop on epoll_wait with a timeout value of 2ms :
// many lines like this :
epoll_wait(4, {{EPOLLOUT, {u32=7, u64=537553536922157063}}}, 2, -1) = 1
I saw in base_event._run_once that the timeout is calculated, but I can't figure it out. I don't know how to set this timeout higher to lower the CPU.
If someone has a clue...
Thank you for your answers.
select
, which is unsurprising because that's basically sleeping between events. On Unixy systems, the commandtime
can show whether a process is I/O bound or CPU bound. Its output would be helpful in diagnosing this issue. – Somewhat