I'm writing small tool, which must execute jmap -heap
, write output to log, then takes some data from log and calculate used memory.
I added some debug
to it.
# JVM with jmap statistic
def java_heap_save(log):
subprocess.call('jmap -heap %s > %s' % (java_pid, log), shell=True, stdout=devnull, stderr=devnull)
with open(log, 'r') as logread:
data = logread.readlines()
# this is just to display 'what will parsing'
print(data)
# here is two list, first - index of item in data, second - for message on terminal
nums = [40, 35, 30, 25, 20]
messages = ['PS Perm Generation', 'PS Old Generation', 'Yong To Space', 'Yong From Space', 'Yong Eden Space']
# I don't found how to create dynamic variable names, so use dictionary
count_names = {}
count_numbers = 1
for num, mess in zip(nums, messages):
# print(mess + ' used '+ str((int(data[num].split(' ')[-2]) / 1024)) + ' KB;')
# from log we got data in bytes, convert here to megabatyes
res = (int(data[num].split(' ')[-2]) / 1024)
print('%s used %s KB;' % (mess, res))
# save value
count_names[count_numbers] = int(res)
count_numbers += 1
print('\nJVM Heap memory stats:\n')
mem_total = (int(data[7].split(' ')[-2]) / 1024 / 1024)
print('MemTotal = %s MB;' % mem_total)
# next few lines - my first attempt, then was rewrited to loop above
# ps_perm_gen = (int(data[40].split(' ')[-2]) / 1024)
# print('PS Perm Generation used = %s KB;' % ps_perm_gen)
# ps_old_gen = (int(data[35].split(' ')[-2]) / 1024)
# print('PS Old Generation used = %s KB;' % ps_old_gen)
# young_to_space = (int(data[30].split(' ')[-2]) / 1024)
# print('Yong To Space used = %s KB;' % young_to_space)
# young_from_space = (int(data[25].split(' ')[-2]) / 1024)
# print('Yong From Space used = %s KB;' % young_from_space)
# young_eden_space = (int(data[20].split(' ')[-2]) / 1024)
# print('Yong Eden Space used = %s KB;' % young_eden_space)
# heap_total_used = ((ps_perm_gen + ps_old_gen + young_to_space + young_eden_space) / 1024)
# count total used memory
heap_total_used = ((count_names[1] + count_names[2] + count_names[3] + count_names[4] + count_names[5]) / 1024)
print('\nTotal heap used: %s MB;' % heap_total_used)
# count % from total avail memory
heap_percentage_used = heap_total_used * 100 / mem_total
print('Heap percentage used: %s%%' % heap_percentage_used)
Then it is called like:
java_heap_save(jmap_log)
Output:
$ ./monitor.py ... JUST FOR DEBUG ['\n', 'using thread-local object allocation.\n', 'Parallel GC with 2 thread(s)\n', '\n', 'Heap Configuration:\n', ' MinHeapFreeRatio = 40\n', ' MaxHeapFreeRatio = 70\n', ' MaxHeapSize = 1073741824 (1024.0MB)\n', ' NewSize = 1310720 (1.25MB)\n', ' MaxNewSize = 17592186044415 MB\n', ' OldSize = 5439488 (5.1875MB)\n', ' NewRatio = 2\n', ' SurvivorRatio = 8\n', ' PermSize = 21757952 (20.75MB)\n', ' MaxPermSize = 1073741824 (1024.0MB)\n', '\n', 'Heap Usage:\n', 'PS Young Generation\n', 'Eden Space:\n', ' capacity = 334626816 (319.125MB)\n', ' used = 164795568 (157.1613006591797MB)\n', ' free = 169831248 (161.9636993408203MB)\n', ' 49.247567774126026% used\n', 'From Space:\n', ' capacity = 11927552 (11.375MB)\n', ' used = 2293760 (2.1875MB)\n', ' free = 9633792 (9.1875MB)\n', ' 19.23076923076923% used\n', 'To Space:\n', ' capacity = 11337728 (10.8125MB)\n', ' used = 0 (0.0MB)\n', ' free = 11337728 (10.8125MB)\n', ' 0.0% used\n', 'PS Old Generation\n', ' capacity = 715849728 (682.6875MB)\n', ' used = 249838952 (238.2649917602539MB)\n', ' free = 466010776 (444.4225082397461MB)\n', ' 34.90103330737034% used\n', 'PS Perm Generation\n', ' capacity = 104005632 (99.1875MB)\n', ' used = 95693760 (91.26068115234375MB)\n', ' free = 8311872 (7.92681884765625MB)\n', ' 92.00824816871456% used\n'] PS Perm Generation used 93450 KB; PS Old Generation used 243983 KB; Yong To Space used 0 KB; Yong From Space used 2240 KB; Yong Eden Space used 160933 KB; JVM Heap memory stats: MemTotal = 1024 MB; Total heap used: 488 MB; Heap percentage used: 47%
What I can improve here?
In fact - I don't like how I realized 'log read' code, I mean this:
int(data[SOME_NUMBER_HERE_ENTERED_MANUALLY].split(' ')[-2]) / 1024)
CentOS 6,5, Python 2.6