pm_sched_mc.py 29 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835
  1. #!/usr/bin/env python3
  2. ''' Reusable functions related to sched mc FVT are put together
  3. '''
  4. import os
  5. import sys
  6. import re
  7. from time import time
  8. __author__ = "Vaidyanathan Srinivasan <svaidy@linux.vnet.ibm.com>"
  9. __author__ = "Poornima Nayak <mpnayak@linux.vnet.ibm.com>"
  10. cpu_map = {}
  11. stats_start = {}
  12. stats_stop = {}
  13. stats_percentage = {}
  14. intr_start = []
  15. intr_stop = []
  16. cpu_count = 0
  17. socket_count = 0
  18. cpu1_max_intr = 0
  19. cpu2_max_intr = 0
  20. intr_stat_timer_0 = []
  21. siblings_list = []
  22. def clear_dmesg():
  23. '''
  24. Clears dmesg
  25. '''
  26. try:
  27. os.system('dmesg -c >/dev/null')
  28. except OSError as e:
  29. print('Clearing dmesg failed', e)
  30. sys.exit(1)
  31. def count_num_cpu():
  32. ''' Returns number of cpu's in system
  33. '''
  34. try:
  35. cpuinfo = open('/proc/cpuinfo', 'r')
  36. global cpu_count
  37. for line in cpuinfo:
  38. if line.startswith('processor'):
  39. cpu_count += 1
  40. cpuinfo.close()
  41. except IOError as e:
  42. print("Could not get cpu count", e)
  43. sys.exit(1)
  44. def count_num_sockets():
  45. ''' Returns number of cpu's in system
  46. '''
  47. socket_list = []
  48. global socket_count
  49. try:
  50. for i in range(0, cpu_count):
  51. phy_pkg_file = '/sys/devices/system/cpu/cpu%s' % i
  52. phy_pkg_file += '/topology/physical_package_id'
  53. socket_id = open(phy_pkg_file).read().rstrip()
  54. if socket_id not in socket_list:
  55. socket_list.append(socket_id)
  56. socket_count = socket_count + 1
  57. except Exception as details:
  58. print("INFO: Failed to get number of sockets in system", details)
  59. sys.exit(1)
  60. def is_multi_socket():
  61. '''Return 1 if the system is multi socket else return 0
  62. '''
  63. try:
  64. if socket_count > 1:
  65. return 1
  66. else:
  67. return 0
  68. except Exception:
  69. print("Failed to check if system is multi socket system")
  70. sys.exit(1)
  71. def is_hyper_threaded():
  72. '''Return 1 if the system is hyper threaded else return 0
  73. '''
  74. try:
  75. file_cpuinfo = open("/proc/cpuinfo", 'r')
  76. for line in file_cpuinfo:
  77. if line.startswith('siblings'):
  78. siblings = line.split(":")
  79. if line.startswith('cpu cores'):
  80. cpu_cores = line.split(":")
  81. break
  82. if int( siblings[1] ) / int( cpu_cores[1] )> 1:
  83. file_cpuinfo.close()
  84. return 1
  85. else:
  86. return 0
  87. except Exception:
  88. print("Failed to check if system is hyper-threaded")
  89. sys.exit(1)
  90. def is_multi_core():
  91. ''' Return true if system has sockets has multiple cores
  92. '''
  93. try:
  94. file_cpuinfo = open("/proc/cpuinfo", 'r')
  95. for line in file_cpuinfo:
  96. if line.startswith('siblings'):
  97. siblings = line.split(":")
  98. if line.startswith('cpu cores'):
  99. cpu_cores = line.split(":")
  100. break
  101. if int( siblings[1] ) == int( cpu_cores[1] ):
  102. if int( cpu_cores[1] ) > 1:
  103. multi_core = 1
  104. else:
  105. multi_core = 0
  106. else:
  107. num_of_cpus = int(siblings[1]) / int(cpu_cores[1])
  108. if num_of_cpus > 1:
  109. multi_core = 1
  110. else:
  111. multi_core = 0
  112. file_cpuinfo.close()
  113. return multi_core
  114. except Exception:
  115. print("Failed to check if system is multi core system")
  116. sys.exit(1)
  117. def get_hyper_thread_count():
  118. ''' Return number of threads in CPU. For eg for x3950 this function
  119. would return 2. In future if 4 threads are supported in CPU, this
  120. routine would return 4
  121. '''
  122. try:
  123. file_cpuinfo = open("/proc/cpuinfo", 'r')
  124. for line in file_cpuinfo:
  125. if line.startswith('siblings'):
  126. siblings = line.split(":")
  127. if line.startswith('cpu cores'):
  128. cpu_cores = line.split(":")
  129. break
  130. return( int( siblings[1] ) / int( cpu_cores[1] ) )
  131. except Exception:
  132. print("Failed to check if system is hyper-threaded")
  133. sys.exit(1)
  134. def map_cpuid_pkgid():
  135. ''' Routine to map physical package id to cpu id
  136. '''
  137. if is_hyper_threaded():
  138. core_info = {}
  139. try:
  140. for i in range(0, cpu_count):
  141. phy_pkg_file = '/sys/devices/system/cpu/cpu%s' % i
  142. phy_pkg_file += '/topology/physical_package_id'
  143. core_file = '/sys/devices/system/cpu/cpu%s' % i
  144. core_file += '/topology/core_id'
  145. core_id = open(core_file).read().rstrip()
  146. cpu_phy_id = open(phy_pkg_file).read().rstrip()
  147. if not cpu_phy_id in list(cpu_map.keys()):
  148. core_info = {}
  149. else:
  150. core_info = cpu_map[cpu_phy_id]
  151. if not core_id in list(core_info.keys()):
  152. core_info[core_id] = [i]
  153. else:
  154. core_info[core_id].append(i)
  155. cpu_map[cpu_phy_id] = core_info
  156. except Exception as details:
  157. print("Package, core & cpu map table creation failed", e)
  158. sys.exit(1)
  159. else:
  160. for i in range(0, cpu_count):
  161. try:
  162. phy_pkg_file = '/sys/devices/system/cpu/cpu%s' %i
  163. phy_pkg_file += '/topology/physical_package_id'
  164. cpu_phy_id = open(phy_pkg_file).read().rstrip()
  165. if not cpu_phy_id in list(cpu_map.keys()):
  166. cpu_map[cpu_phy_id] = [i]
  167. else:
  168. cpu_map[cpu_phy_id].append(i)
  169. except IOError as e:
  170. print("Mapping of CPU to pkg id failed", e)
  171. sys.exit(1)
  172. def generate_sibling_list():
  173. ''' Routine to generate siblings list
  174. '''
  175. try:
  176. for i in range(0, cpu_count):
  177. siblings_file = '/sys/devices/system/cpu/cpu%s' % i
  178. siblings_file += '/topology/thread_siblings_list'
  179. threads_sibs = open(siblings_file).read().rstrip()
  180. thread_ids = threads_sibs.split("-")
  181. if not thread_ids in siblings_list:
  182. siblings_list.append(thread_ids)
  183. except Exception as details:
  184. print("Exception in generate_siblings_list", details)
  185. sys.exit(1)
  186. def get_siblings(cpu_id):
  187. ''' Return siblings of cpu_id
  188. '''
  189. try:
  190. cpus = ""
  191. for i in range(0, len(siblings_list)):
  192. for cpu in siblings_list[i]:
  193. if cpu_id == cpu:
  194. for j in siblings_list[i]:
  195. # Exclude cpu_id in the list of siblings
  196. if j != cpu_id:
  197. cpus += j
  198. return cpus
  199. return cpus
  200. except Exception as details:
  201. print("Exception in get_siblings", details)
  202. sys.exit(1)
  203. def get_proc_data(stats_list):
  204. ''' Read /proc/stat info and store in dictionary
  205. '''
  206. try:
  207. file_procstat = open("/proc/stat", 'r')
  208. for line in file_procstat:
  209. if line.startswith('cpu'):
  210. data = line.split()
  211. stats_list[data[0]] = data
  212. file_procstat.close()
  213. except OSError as e:
  214. print("Could not read statistics", e)
  215. sys.exit(1)
  216. def get_proc_loc_count(loc_stats):
  217. ''' Read /proc/interrupts info and store in list
  218. '''
  219. try:
  220. file_procstat = open("/proc/interrupts", 'r')
  221. for line in file_procstat:
  222. if line.startswith(' LOC:') or line.startswith('LOC:'):
  223. data = line.split()
  224. for i in range(0, cpu_count):
  225. # To skip LOC
  226. loc_stats.append(data[i+1])
  227. file_procstat.close()
  228. return
  229. except Exception as details:
  230. print("Could not read interrupt statistics", details)
  231. sys.exit(1)
  232. def set_sched_mc_power(sched_mc_level):
  233. ''' Routine to set sched_mc_power_savings to required level
  234. '''
  235. try:
  236. os.system('echo %s > \
  237. /sys/devices/system/cpu/sched_mc_power_savings 2>/dev/null'
  238. % sched_mc_level)
  239. get_proc_data(stats_start)
  240. except OSError as e:
  241. print("Could not set sched_mc_power_savings to", sched_mc_level, e)
  242. sys.exit(1)
  243. def set_sched_smt_power(sched_smt_level):
  244. ''' Routine to set sched_smt_power_savings to required level
  245. '''
  246. try:
  247. os.system('echo %s > \
  248. /sys/devices/system/cpu/sched_smt_power_savings 2>/dev/null'
  249. % sched_smt_level)
  250. get_proc_data(stats_start)
  251. except OSError as e:
  252. print("Could not set sched_smt_power_savings to", sched_smt_level, e)
  253. sys.exit(1)
  254. def set_timer_migration_interface(value):
  255. ''' Set value of timer migration interface to a value
  256. passed as argument
  257. '''
  258. try:
  259. os.system('echo %s > \
  260. /proc/sys/kernel/timer_migration 2>/dev/null' % value)
  261. except OSError as e:
  262. print("Could not set timer_migration to ", value, e)
  263. sys.exit(1)
  264. def get_job_count(stress, workload, sched_smt):
  265. ''' Returns number of jobs/threads to be triggered
  266. '''
  267. try:
  268. if stress == "thread":
  269. threads = get_hyper_thread_count()
  270. if stress == "partial":
  271. threads = cpu_count / socket_count
  272. if is_hyper_threaded():
  273. if workload == "ebizzy" and int(sched_smt) ==0:
  274. threads = threads / get_hyper_thread_count()
  275. if workload == "kernbench" and int(sched_smt) < 2:
  276. threads = threads / get_hyper_thread_count()
  277. if stress == "full":
  278. threads = cpu_count
  279. if stress == "single_job":
  280. threads = 1
  281. duration = 180
  282. return threads
  283. except Exception as details:
  284. print("get job count failed ", details)
  285. sys.exit(1)
  286. def trigger_ebizzy (sched_smt, stress, duration, background, pinned):
  287. ''' Triggers ebizzy workload for sched_mc=1
  288. testing
  289. '''
  290. try:
  291. threads = get_job_count(stress, "ebizzy", sched_smt)
  292. workload = "ebizzy"
  293. olddir = os.getcwd()
  294. path = '%s/testcases/bin' % os.environ['LTPROOT']
  295. os.chdir(path)
  296. workload_file = ""
  297. for file_name in os.listdir('.'):
  298. if file_name == workload:
  299. workload_file = file_name
  300. break
  301. if workload_file == "":
  302. print("INFO: ebizzy benchmark not found")
  303. os.chdir(olddir)
  304. sys.exit(1)
  305. get_proc_data(stats_start)
  306. get_proc_loc_count(intr_start)
  307. try:
  308. if background == "yes":
  309. succ = os.system('./ebizzy -t%s -s4096 -S %s >/dev/null &'
  310. % (threads, duration))
  311. else:
  312. if pinned == "yes":
  313. succ = os.system('taskset -c %s ./ebizzy -t%s -s4096 -S %s >/dev/null'
  314. % (cpu_count -1, threads, duration))
  315. else:
  316. succ = os.system('./ebizzy -t%s -s4096 -S %s >/dev/null'
  317. % (threads, duration))
  318. if succ == 0:
  319. print("INFO: ebizzy workload triggerd")
  320. os.chdir(olddir)
  321. #Commented bcoz it doesnt make sense to capture it when workload triggered
  322. #in background
  323. #get_proc_loc_count(intr_stop)
  324. #get_proc_data(stats_stop)
  325. else:
  326. print("INFO: ebizzy workload triggerd failed")
  327. os.chdir(olddir)
  328. sys.exit(1)
  329. except Exception as details:
  330. print("Ebizzy workload trigger failed ", details)
  331. sys.exit(1)
  332. except Exception as details:
  333. print("Ebizzy workload trigger failed ", details)
  334. sys.exit(1)
  335. def trigger_kernbench (sched_smt, stress, background, pinned, perf_test):
  336. ''' Trigger load on system like kernbench.
  337. Copys existing copy of LTP into as LTP2 and then builds it
  338. with make -j
  339. '''
  340. olddir = os.getcwd()
  341. try:
  342. threads = get_job_count(stress, "kernbench", sched_smt)
  343. dst_path = "/root"
  344. workload = "kernbench"
  345. olddir = os.getcwd()
  346. path = '%s/testcases/bin' % os.environ['LTPROOT']
  347. os.chdir(path)
  348. workload_file = ""
  349. for file_name in os.listdir('.'):
  350. if file_name == workload:
  351. workload_file = file_name
  352. break
  353. if workload_file != "":
  354. benchmark_path = path
  355. else:
  356. print("INFO: kernbench benchmark not found")
  357. os.chdir(olddir)
  358. sys.exit(1)
  359. os.chdir(dst_path)
  360. linux_source_dir=""
  361. for file_name in os.listdir('.'):
  362. if file_name.find("linux-2.6") != -1 and os.path.isdir(file_name):
  363. linux_source_dir=file_name
  364. break
  365. if linux_source_dir != "":
  366. os.chdir(linux_source_dir)
  367. else:
  368. print("INFO: Linux kernel source not found in /root. Workload\
  369. Kernbench cannot be executed")
  370. sys.exit(1)
  371. get_proc_data(stats_start)
  372. get_proc_loc_count(intr_start)
  373. if pinned == "yes":
  374. os.system ( 'taskset -c %s %s/kernbench -o %s -M -H -n 1 \
  375. >/dev/null 2>&1 &' % (cpu_count-1, benchmark_path, threads))
  376. # We have to delete import in future
  377. import time
  378. time.sleep(240)
  379. stop_wkld("kernbench")
  380. else:
  381. if background == "yes":
  382. os.system ( '%s/kernbench -o %s -M -H -n 1 >/dev/null 2>&1 &' \
  383. % (benchmark_path, threads))
  384. else:
  385. if perf_test == "yes":
  386. os.system ( '%s/kernbench -o %s -M -H -n 1 >/dev/null 2>&1' \
  387. % (benchmark_path, threads))
  388. else:
  389. os.system ( '%s/kernbench -o %s -M -H -n 1 >/dev/null 2>&1 &' \
  390. % (benchmark_path, threads))
  391. # We have to delete import in future
  392. import time
  393. time.sleep(240)
  394. stop_wkld("kernbench")
  395. print("INFO: Workload kernbench triggerd")
  396. os.chdir(olddir)
  397. except Exception as details:
  398. print("Workload kernbench trigger failed ", details)
  399. sys.exit(1)
  400. def trigger_workld(sched_smt, workload, stress, duration, background, pinned, perf_test):
  401. ''' Triggers workload passed as argument. Number of threads
  402. triggered is based on stress value.
  403. '''
  404. try:
  405. if workload == "ebizzy":
  406. trigger_ebizzy (sched_smt, stress, duration, background, pinned)
  407. if workload == "kernbench":
  408. trigger_kernbench (sched_smt, stress, background, pinned, perf_test)
  409. except Exception as details:
  410. print("INFO: Trigger workload failed", details)
  411. sys.exit(1)
  412. def generate_report():
  413. ''' Generate report of CPU utilization
  414. '''
  415. cpu_labels = ('cpu', 'user', 'nice', 'system', 'idle', 'iowait', 'irq',
  416. 'softirq', 'x', 'y')
  417. if (not os.path.exists('/procstat')):
  418. os.mkdir('/procstat')
  419. get_proc_data(stats_stop)
  420. reportfile = open('/procstat/cpu-utilisation', 'a')
  421. debugfile = open('/procstat/cpu-utilisation.debug', 'a')
  422. for l in stats_stop:
  423. percentage_list = []
  424. total = 0
  425. for i in range(1, len(stats_stop[l])):
  426. stats_stop[l][i] = int(stats_stop[l][i]) - int(stats_start[l][i])
  427. total += stats_stop[l][i]
  428. percentage_list.append(l)
  429. for i in range(1, len(stats_stop[l])):
  430. percentage_list.append(float(stats_stop[l][i])*100/total)
  431. stats_percentage[l] = percentage_list
  432. for i in range(0, len(cpu_labels)):
  433. print(cpu_labels[i], '\t', end=' ', file=debugfile)
  434. print(file=debugfile)
  435. for l in sorted(stats_stop.keys()):
  436. print(l, '\t', end=' ', file=debugfile)
  437. for i in range(1, len(stats_stop[l])):
  438. print(stats_stop[l][i], '\t', end=' ', file=debugfile)
  439. print(file=debugfile)
  440. for i in range(0, len(cpu_labels)):
  441. print(cpu_labels[i], '\t', end=' ', file=reportfile)
  442. print(file=reportfile)
  443. for l in sorted(stats_percentage.keys()):
  444. print(l, '\t', end=' ', file=reportfile)
  445. for i in range(1, len(stats_percentage[l])):
  446. print(" %3.4f" % stats_percentage[l][i], end=' ', file=reportfile)
  447. print(file=reportfile)
  448. #Now get the package ID information
  449. try:
  450. print("cpu_map: ", cpu_map, file=debugfile)
  451. keyvalfile = open('/procstat/keyval', 'a')
  452. print("nr_packages=%d" % len(cpu_map), file=keyvalfile)
  453. print("system-idle=%3.4f" % (stats_percentage['cpu'][4]), file=keyvalfile)
  454. for pkg in sorted(cpu_map.keys()):
  455. if is_hyper_threaded():
  456. for core in sorted(cpu_map[pkg].keys()):
  457. total_idle = 0
  458. total = 0
  459. for cpu in cpu_map[pkg][core]:
  460. total_idle += stats_stop["cpu%d" % cpu][4]
  461. for i in range(1, len(stats_stop["cpu%d" % cpu])):
  462. total += stats_stop["cpu%d" % cpu][i]
  463. else:
  464. total_idle = 0
  465. total = 0
  466. for cpu in cpu_map[pkg]:
  467. total_idle += stats_stop["cpu%d" % cpu][4]
  468. for i in range(1, len(stats_stop["cpu%d" % cpu])):
  469. total += stats_stop["cpu%d" % cpu][i]
  470. print("Package: ", pkg, "Idle %3.4f%%" \
  471. % (float(total_idle)*100/total), file=reportfile)
  472. print("package-%s=%3.4f" % \
  473. (pkg, (float(total_idle)*100/total)), file=keyvalfile)
  474. except Exception as details:
  475. print("Generating utilization report failed: ", details)
  476. sys.exit(1)
  477. #Add record delimiter '\n' before closing these files
  478. print(file=debugfile)
  479. debugfile.close()
  480. print(file=reportfile)
  481. reportfile.close()
  482. print(file=keyvalfile)
  483. keyvalfile.close()
  484. def generate_loc_intr_report():
  485. ''' Generate interrupt report of CPU's
  486. '''
  487. try:
  488. if (not os.path.exists('/procstat')):
  489. os.mkdir('/procstat')
  490. get_proc_loc_count(intr_stop)
  491. reportfile = open('/procstat/cpu-loc_interrupts', 'a')
  492. print("==============================================", file=reportfile)
  493. print(" Local timer interrupt stats ", file=reportfile)
  494. print("==============================================", file=reportfile)
  495. for i in range(0, cpu_count):
  496. intr_stop[i] = int(intr_stop[i]) - int(intr_start[i])
  497. print("CPU%s: %s" %(i, intr_stop[i]), file=reportfile)
  498. print(file=reportfile)
  499. reportfile.close()
  500. except Exception as details:
  501. print("Generating interrupt report failed: ", details)
  502. sys.exit(1)
  503. def record_loc_intr_count():
  504. ''' Record Interrupt statistics when timer_migration
  505. was disabled
  506. '''
  507. try:
  508. global intr_start, intr_stop
  509. for i in range(0, cpu_count):
  510. intr_stat_timer_0.append(intr_stop[i])
  511. intr_start = []
  512. intr_stop = []
  513. except Exception as details:
  514. print("INFO: Record interrupt statistics when timer_migration=0",details)
  515. def expand_range(range_val):
  516. '''
  517. Expand the range of value into actual numbers
  518. '''
  519. ids_list = list()
  520. try:
  521. sep_comma = range_val.split(",")
  522. for i in range(0, len(sep_comma)):
  523. hyphen_values = sep_comma[i].split("-")
  524. if len(hyphen_values) == 1:
  525. ids_list.append(int(hyphen_values[0]))
  526. else:
  527. for j in range(int(hyphen_values[0]), int(hyphen_values[1])+1):
  528. ids_list.append(j)
  529. return(ids_list)
  530. except Exception as details:
  531. print("INFO: expand_pkg_grps failed ", details)
  532. def is_quad_core():
  533. '''
  534. Read /proc/cpuinfo and check if system is Quad core
  535. '''
  536. try:
  537. cpuinfo = open('/proc/cpuinfo', 'r')
  538. for line in cpuinfo:
  539. if line.startswith('cpu cores'):
  540. cores = line.split("cpu cores")
  541. num_cores = cores[1].split(":")
  542. cpuinfo.close()
  543. if int(num_cores[1]) == 4:
  544. return(1)
  545. else:
  546. return(0)
  547. except IOError as e:
  548. print("Failed to get cpu core information", e)
  549. sys.exit(1)
  550. def validate_cpugrp_map(cpu_group, sched_mc_level, sched_smt_level):
  551. '''
  552. Verify if cpugrp belong to same package
  553. '''
  554. modi_cpu_grp = cpu_group[:]
  555. try:
  556. if is_hyper_threaded():
  557. for pkg in sorted(cpu_map.keys()):
  558. # if CPU utilized is across package this condition will be true
  559. if len(modi_cpu_grp) != len(cpu_group):
  560. break
  561. for core in sorted(cpu_map[pkg].keys()):
  562. core_cpus = cpu_map[pkg][core]
  563. if core_cpus == modi_cpu_grp:
  564. return 0
  565. else:
  566. #if CPUs used across the cores
  567. for i in range(0, len(core_cpus)):
  568. if core_cpus[i] in modi_cpu_grp:
  569. modi_cpu_grp.remove(core_cpus[i])
  570. if len(modi_cpu_grp) == 0:
  571. return 0
  572. #This code has to be deleted
  573. #else:
  574. # If sched_smt == 0 then its oky if threads run
  575. # in different cores of same package
  576. #if sched_smt_level > 0 :
  577. #return 1
  578. else:
  579. for pkg in sorted(cpu_map.keys()):
  580. pkg_cpus = cpu_map[pkg]
  581. if len(cpu_group) == len(pkg_cpus):
  582. if pkg_cpus == cpu_group:
  583. return(0)
  584. else:
  585. if int(cpus_utilized[0]) in cpu_map[pkg] or int(cpus_utilized[1]) in cpu_map[pkg]:
  586. return(0)
  587. return(1)
  588. except Exception as details:
  589. print("Exception in validate_cpugrp_map: ", details)
  590. sys.exit(1)
  591. def verify_sched_domain_dmesg(sched_mc_level, sched_smt_level):
  592. '''
  593. Read sched domain information from dmesg.
  594. '''
  595. cpu_group = list()
  596. try:
  597. dmesg_info = os.popen('dmesg').read()
  598. if dmesg_info != "":
  599. lines = dmesg_info.split('\n')
  600. for i in range(0, len(lines)):
  601. if lines[i].endswith('CPU'):
  602. groups = lines[i+1].split("groups:")
  603. group_info = groups[1]
  604. if group_info.find("(") != -1:
  605. openindex=group_info.index("(")
  606. closeindex=group_info.index(")")
  607. group_info=group_info.replace\
  608. (group_info[openindex:closeindex+1],"")
  609. subgroup = group_info.split(",")
  610. for j in range(0, len(subgroup)):
  611. cpu_group = expand_range(subgroup[j])
  612. status = validate_cpugrp_map(cpu_group, sched_mc_level,\
  613. sched_smt_level)
  614. if status == 1:
  615. if is_quad_core() == 1:
  616. if int(sched_mc_level) == 0:
  617. return(0)
  618. else:
  619. return(1)
  620. else:
  621. return(1)
  622. return(0)
  623. else:
  624. return(1)
  625. except Exception as details:
  626. print("Reading dmesg failed", details)
  627. sys.exit(1)
  628. def get_cpu_utilization(cpu):
  629. ''' Return cpu utilization of cpu_id
  630. '''
  631. try:
  632. for l in sorted(stats_percentage.keys()):
  633. if cpu == stats_percentage[l][0]:
  634. return stats_percentage[l][1]
  635. return -1
  636. except Exception as details:
  637. print("Exception in get_cpu_utilization", details)
  638. sys.exit(1)
  639. def validate_cpu_consolidation(stress, work_ld, sched_mc_level, sched_smt_level):
  640. ''' Verify if cpu's on which threads executed belong to same
  641. package
  642. '''
  643. cpus_utilized = list()
  644. threads = get_job_count(stress, work_ld, sched_smt_level)
  645. try:
  646. for l in sorted(stats_percentage.keys()):
  647. #modify threshold
  648. cpu_id = stats_percentage[l][0].split("cpu")
  649. if cpu_id[1] == '':
  650. continue
  651. if int(cpu_id[1]) in cpus_utilized:
  652. continue
  653. if is_hyper_threaded():
  654. if work_ld == "kernbench" and sched_smt_level < sched_mc_level:
  655. siblings = get_siblings(cpu_id[1])
  656. if siblings != "":
  657. sib_list = siblings.split()
  658. utilization = int(stats_percentage[l][1])
  659. for i in range(0, len(sib_list)):
  660. utilization += int(get_cpu_utilization("cpu%s" %sib_list[i]))
  661. else:
  662. utilization = stats_percentage[l][1]
  663. if utilization > 40:
  664. cpus_utilized.append(int(cpu_id[1]))
  665. if siblings != "":
  666. for i in range(0, len(sib_list)):
  667. cpus_utilized.append(int(sib_list[i]))
  668. else:
  669. # This threshold wuld be modified based on results
  670. if stats_percentage[l][1] > 40:
  671. cpus_utilized.append(int(cpu_id[1]))
  672. else:
  673. if work_ld == "kernbench" :
  674. if stats_percentage[l][1] > 50:
  675. cpus_utilized.append(int(cpu_id[1]))
  676. else:
  677. if stats_percentage[l][1] > 70:
  678. cpus_utilized.append(int(cpu_id[1]))
  679. cpus_utilized.sort()
  680. print("INFO: CPU's utilized ", cpus_utilized)
  681. # If length of CPU's utilized is not = number of jobs exit with 1
  682. if len(cpus_utilized) < threads:
  683. return 1
  684. status = validate_cpugrp_map(cpus_utilized, sched_mc_level, \
  685. sched_smt_level)
  686. if status == 1:
  687. print("INFO: CPUs utilized is not in same package or core")
  688. return(status)
  689. except Exception as details:
  690. print("Exception in validate_cpu_consolidation: ", details)
  691. sys.exit(1)
  692. def get_cpuid_max_intr_count():
  693. '''Return the cpu id's of two cpu's with highest number of intr'''
  694. try:
  695. highest = 0
  696. second_highest = 0
  697. cpus_utilized = []
  698. #Skipping CPU0 as it is generally high
  699. for i in range(1, cpu_count):
  700. if int(intr_stop[i]) > int(highest):
  701. if highest != 0:
  702. second_highest = highest
  703. cpu2_max_intr = cpu1_max_intr
  704. highest = int(intr_stop[i])
  705. cpu1_max_intr = i
  706. else:
  707. if int(intr_stop[i]) > int(second_highest):
  708. second_highest = int(intr_stop[i])
  709. cpu2_max_intr = i
  710. cpus_utilized.append(cpu1_max_intr)
  711. cpus_utilized.append(cpu2_max_intr)
  712. for i in range(1, cpu_count):
  713. if i != cpu1_max_intr and i != cpu2_max_intr:
  714. diff = second_highest - intr_stop[i]
  715. ''' Threshold of difference has to be manipulated '''
  716. if diff < 10000:
  717. print("INFO: Diff in interrupt count is below threshold")
  718. cpus_utilized = []
  719. return cpus_utilized
  720. print("INFO: Interrupt count in other CPU's low as expected")
  721. return cpus_utilized
  722. except Exception as details:
  723. print("Exception in get_cpuid_max_intr_count: ", details)
  724. sys.exit(1)
  725. def validate_ilb (sched_mc_level, sched_smt_level):
  726. ''' Validate if ilb is running in same package where work load is running
  727. '''
  728. try:
  729. cpus_utilized = get_cpuid_max_intr_count()
  730. if not cpus_utilized:
  731. return 1
  732. status = validate_cpugrp_map(cpus_utilized, sched_mc_level, sched_smt_level)
  733. return status
  734. except Exception as details:
  735. print("Exception in validate_ilb: ", details)
  736. sys.exit(1)
  737. def reset_schedmc():
  738. ''' Routine to reset sched_mc_power_savings to Zero level
  739. '''
  740. try:
  741. os.system('echo 0 > \
  742. /sys/devices/system/cpu/sched_mc_power_savings 2>/dev/null')
  743. except OSError as e:
  744. print("Could not set sched_mc_power_savings to 0", e)
  745. sys.exit(1)
  746. def reset_schedsmt():
  747. ''' Routine to reset sched_smt_power_savings to Zero level
  748. '''
  749. try:
  750. os.system('echo 0 > \
  751. /sys/devices/system/cpu/sched_smt_power_savings 2>/dev/null')
  752. except OSError as e:
  753. print("Could not set sched_smt_power_savings to 0", e)
  754. sys.exit(1)
  755. def stop_wkld(work_ld):
  756. ''' Kill workload triggered in background
  757. '''
  758. try:
  759. os.system('pkill %s 2>/dev/null' %work_ld)
  760. if work_ld == "kernbench":
  761. os.system('pkill make 2>/dev/null')
  762. except OSError as e:
  763. print("Exception in stop_wkld", e)
  764. sys.exit(1)