epoll - asyncio python with serial device takes 100% CPU -


when run little main rfxcom python library :

from asyncio import get_event_loop 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 cpu usage getting hight (around 100%). can't understand why : there few messages (~ 1 message every 5 seconds) received module, , thought when epoll_wait called cpu should idled, waiting next event.

i launched main python cprofile, , shows :

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 857 50 due 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 first 3 function calls in term of elapsed time python3.4/asyncio/base_events.py, python3.4/selectors.py , python3.4/asyncio/selector_events.py.

edit : time command on similar run gives :

time python -m cprofile -o rfxcom_profile.log rfxcom_profile.py real    2m24.548s user    2m19.892s sys     0m4.113s 

can explain me why ?

edit2: the number of fonctions calls high, made strace of process , found there loop on epoll_wait timeout value of 2ms :

// many lines : epoll_wait(4, {{epollout, {u32=7, u64=537553536922157063}}}, 2, -1) = 1     

i saw in base_event._run_once timeout calculated, can't figure out. don't know how set timeout higher lower cpu.

if has clue...

thank answers.

i answer question may usefull others.

after having set environment variable pythonasynciodebug 1, there lines , lines :

 debug:asyncio:poll took 0.006 ms: 1 events 

in rfxcom library there writer mechanism queue push data serial device. intention think "asyncio, tell me when can write, , i'll flush write queue". there line :

self.loop.call_soon(self.loop.add_writer, self.dev.fd, self._writer) 

self.dev serial class instance , self.dev.fd serial file descriptor.

as the doc says "add_writer(fd, callback, *args) : start watching file descriptor write availability".

i thought serial device available writing made little script:

logger = logging.getlogger() logger.setlevel(logging.debug)  loop = get_event_loop()  def writer_cb():     logger.info("writer cb called")  s = serial('/dev/serial/by-id/usb-rfxcom_rfxtrx433_a1xzi13o-if00-port0', 38400, timeout=1)  loop.add_writer(s.fd, writer_cb) loop.run_forever() 

and saw lines looping endlessly, bringing cpu 100%:

debug:asyncio:poll took 0.006 ms: 1 events info:root:writer cb called 

so think there no need put writer callback, call write on serial device.


Comments