Bug #72002 mysqlfailover consumes excessive CPU
Submitted: 11 Mar 2014 4:17 Modified: 10 Jun 2014 0:38
Reporter: Sadao Hiratsuka Email Updates:
Status: Closed Impact on me:
None 
Category:MySQL Utilities Severity:S3 (Non-critical)
Version:1.3.6 OS:Any
Assigned to: CPU Architecture:Any
Tags: mysqlfailover

[11 Mar 2014 4:17] Sadao Hiratsuka
Description:
mysqlfailover consumes excessive CPU.

top - 11:29:35 up 32 days, 13 min,  2 users,  load average: 0.58, 0.20, 0.07
Tasks: 143 total,   2 running, 141 sleeping,   0 stopped,   0 zombie
Cpu(s):  0.2%us,  0.2%sy,  0.0%ni, 99.5%id,  0.0%wa,  0.0%hi,  0.0%si,  0.1%st
Mem:   3922728k total,  3772080k used,   150648k free,   375424k buffers
Swap:  2097144k total,     7388k used,  2089756k free,  2201300k cached

  PID USER      PR  NI  VIRT  RES  SHR S %CPU %MEM    TIME+  COMMAND                                                             
15306 taira     20   0  201m  11m 3444 R 99.4  0.3   0:24.60 mysqlfailover
    1 root      20   0 19356 1256 1036 S  0.0  0.0   0:08.37 init
    2 root      20   0     0    0    0 S  0.0  0.0   0:00.01 kthreadd
    3 root      RT   0     0    0    0 S  0.0  0.0   0:01.38 migration/0
    4 root      20   0     0    0    0 S  0.0  0.0   0:35.58 ksoftirqd/0

How to repeat:
$ python -m cProfile /usr/bin/mysqlfailover --master=util:xxxx@xxx.xxx.xxx.xxx --discover-slaves-login=util:xxxx

         31610206 function calls (31608036 primitive calls) in 42.623 CPU seconds

   Ordered by: internal time

   ncalls  tottime  percall  cumtime  percall filename:lineno(function)
 10475537   11.991    0.000   11.991    0.000 {select.select}
 10475537   10.794    0.000   22.785    0.000 failover_console.py:88(kbhit)
        3    9.005    3.002    9.005    3.002 {posix.waitpid}
        3    7.772    2.591   33.121   11.040 failover_console.py:423(_wait_for_interval)
 10475542    2.564    0.000    2.564    0.000 {time.time}
    18150    0.158    0.000    0.158    0.000 {method 'recv' of '_socket.socket' objects}
     3630    0.041    0.000    0.208    0.000 network.py:185(recv_plain)
        2    0.034    0.017    0.034    0.017 {built-in method search}
    14544    0.020    0.000    0.023    0.000 utils.py:138(read_lc_string)
     2424    0.014    0.000    0.039    0.000 protocol.py:170(parse_column)
   332/42    0.011    0.000    0.031    0.001 sre_parse.py:385(_parse)
        3    0.010    0.003    0.010    0.003 {posix.system}
41578/41188    0.010    0.000    0.010    0.000 {len}
      517    0.009    0.000    0.009    0.000 {method 'sendall' of '_socket.socket' objects}
      253    0.008    0.000    0.097    0.000 connection.py:530(_handle_result)
     6302    0.007    0.000    0.009    0.000 sre_parse.py:188(__next)
        2    0.006    0.003    0.006    0.003 {method 'read' of 'file' objects}
   698/40    0.006    0.000    0.019    0.000 sre_compile.py:38(_compile)
    22849    0.005    0.000    0.005    0.000 {ord}
      245    0.005    0.000    0.008    0.000 sre_compile.py:213(_optimize_charset)
      301    0.005    0.000    0.007    0.000 utils.py:190(read_lc_string_list)
        4    0.005    0.001    0.005    0.001 {posix.read}
        1    0.004    0.004    0.090    0.090 rpl_admin.py:21(<module>)
      506    0.004    0.000    0.171    0.000 connection.py:398(_send_cmd)
     7071    0.004    0.000    0.004    0.000 {_struct.unpack}
        1    0.004    0.004    0.004    0.004 socket.py:44(<module>)
        8    0.004    0.000    0.004    0.000 {method 'connect' of '_socket.socket' objects}
  977/349    0.003    0.000    0.004    0.000 sre_parse.py:146(getwidth)
     5616    0.003    0.000    0.011    0.000 sre_parse.py:207(get)
    12667    0.003    0.000    0.003    0.000 {method 'append' of 'list' objects}
 

Suggested fix:
--- failover_console.py_org	2014-03-11 11:46:41.253000220 +0900
+++ failover_console.py	2014-03-11 13:16:11.127000221 +0900
@@ -88,7 +88,7 @@
     def kbhit():
         """Make a keyboard hit method for Posix machines.
         """
-        return select([sys.stdin], [], [], 0) == ([sys.stdin], [], [])
+        return select([sys.stdin], [], [], 1) == ([sys.stdin], [], [])
 
 
 def get_terminal_size():
[11 Mar 2014 7:53] MySQL Verification Team
Hello Sadao,

Thank you for the bug report.
Verified as described.

Thanks,
Umesh
[10 Jun 2014 0:38] Philip Olson
Fixed as of the upcoming MySQL Utilities 1.4.4 release, and here's the changelog entry:

The "mysqlfailover" utility caused excessive CPU usage when executed in the
console without passing in "--daemon". This high CPU usage was due to the
process waiting for user input.

Thank you for the bug report.