200 lines
5.2 KiB
Lua
200 lines
5.2 KiB
Lua
local Timeseries = require 'Timeseries'
|
|
local Table = require 'Table'
|
|
local Util = require 'Util'
|
|
local Common = require 'Common'
|
|
local Geometry = require 'Geometry'
|
|
local func = require 'func'
|
|
|
|
return function(update_freq)
|
|
local MODULE_Y = 712
|
|
local DIAL_THICKNESS = 8
|
|
local DIAL_RADIUS = 32
|
|
local DIAL_SPACING = 40
|
|
local CACHE_Y_OFFSET = 7
|
|
local CACHE_X_OFFSET = 50
|
|
local TEXT_SPACING = 20
|
|
local PLOT_SECTION_BREAK = 22
|
|
local PLOT_HEIGHT = 56
|
|
local TABLE_SECTION_BREAK = 20
|
|
local TABLE_HEIGHT = 114
|
|
|
|
local MEMINFO_REGEX = '\nMemFree:%s+(%d+).+'..
|
|
'\nBuffers:%s+(%d+).+'..
|
|
'\nCached:%s+(%d+).+'..
|
|
'\nSwapFree:%s+(%d+).+'..
|
|
'\nShmem:%s+(%d+).+'..
|
|
'\nSReclaimable:%s+(%d+)'
|
|
|
|
local __string_match = string.match
|
|
|
|
-----------------------------------------------------------------------------
|
|
-- header
|
|
|
|
local header = Common.Header(
|
|
Geometry.RIGHT_X,
|
|
MODULE_Y,
|
|
Geometry.SECTION_WIDTH,
|
|
'MEMORY'
|
|
)
|
|
|
|
-----------------------------------------------------------------------------
|
|
-- mem consumption dial
|
|
|
|
local get_meminfo_field = function(field)
|
|
return tonumber(Util.read_file('/proc/meminfo', field..':%s+(%d+)'))
|
|
end
|
|
|
|
local memtotal = get_meminfo_field('MemTotal')
|
|
local swaptotal = get_meminfo_field('SwapTotal')
|
|
|
|
local FORMAT_PERCENT = function(x)
|
|
return string.format('%.0f%%', x * 100)
|
|
end
|
|
|
|
local MEM_X = Geometry.RIGHT_X + DIAL_RADIUS + DIAL_THICKNESS / 2
|
|
local MEM_Y = header.bottom_y + DIAL_RADIUS + DIAL_THICKNESS / 2
|
|
local DIAL_DIAMETER = DIAL_RADIUS * 2 + DIAL_THICKNESS
|
|
|
|
local mem = Common.dial(
|
|
MEM_X,
|
|
MEM_Y,
|
|
DIAL_RADIUS,
|
|
DIAL_THICKNESS,
|
|
0.8,
|
|
FORMAT_PERCENT
|
|
)
|
|
|
|
-----------------------------------------------------------------------------
|
|
-- swap consumption dial
|
|
|
|
local SWAP_X = MEM_X + DIAL_DIAMETER + DIAL_SPACING
|
|
|
|
local swap = Common.dial(
|
|
SWAP_X,
|
|
MEM_Y,
|
|
DIAL_RADIUS,
|
|
DIAL_THICKNESS,
|
|
0.8,
|
|
FORMAT_PERCENT
|
|
)
|
|
|
|
-----------------------------------------------------------------------------
|
|
-- swap/buffers stats
|
|
|
|
local CACHE_Y = header.bottom_y + CACHE_Y_OFFSET
|
|
local CACHE_X = SWAP_X + CACHE_X_OFFSET + DIAL_DIAMETER / 2
|
|
local CACHE_WIDTH = Geometry.RIGHT_X + Geometry.SECTION_WIDTH - CACHE_X
|
|
|
|
local cache = Common.initTextRows_formatted(
|
|
CACHE_X,
|
|
CACHE_Y,
|
|
CACHE_WIDTH,
|
|
TEXT_SPACING,
|
|
{'Page Cache', 'Buffers', 'Shared', 'Kernel Slab'},
|
|
'%.1f%%'
|
|
)
|
|
|
|
-----------------------------------------------------------------------------
|
|
-- memory consumption plot
|
|
|
|
local PLOT_Y = header.bottom_y + PLOT_SECTION_BREAK + DIAL_DIAMETER
|
|
|
|
local plot = Common.initThemedLabelPlot(
|
|
Geometry.RIGHT_X,
|
|
PLOT_Y,
|
|
Geometry.SECTION_WIDTH,
|
|
PLOT_HEIGHT,
|
|
Common.percent_label_config,
|
|
update_freq
|
|
)
|
|
|
|
-----------------------------------------------------------------------------
|
|
-- memory top table
|
|
|
|
local NUM_ROWS = 5
|
|
local TABLE_CONKY = func.map(
|
|
function(i)
|
|
return {
|
|
comm = '${top_mem name '..i..'}',
|
|
pid = '${top_mem pid '..i..'}',
|
|
mem = '${top_mem mem '..i..'}',
|
|
}
|
|
end,
|
|
func.seq(NUM_ROWS))
|
|
|
|
local tbl = Common.initTable(
|
|
Geometry.RIGHT_X,
|
|
PLOT_Y + PLOT_HEIGHT + TABLE_SECTION_BREAK,
|
|
Geometry.SECTION_WIDTH,
|
|
TABLE_HEIGHT,
|
|
NUM_ROWS,
|
|
{'Name', 'PID', 'Mem (%)'}
|
|
)
|
|
|
|
-----------------------------------------------------------------------------
|
|
-- main functions
|
|
|
|
local update = function(cr)
|
|
local conky = Util.conky
|
|
-- see manpage for free command for formulas
|
|
|
|
local memfree,
|
|
buffers,
|
|
cached,
|
|
swapfree,
|
|
shmem,
|
|
sreclaimable
|
|
= __string_match(Util.read_file('/proc/meminfo'), MEMINFO_REGEX)
|
|
|
|
local used_percent =
|
|
(memtotal -
|
|
memfree -
|
|
cached -
|
|
buffers -
|
|
sreclaimable) / memtotal
|
|
|
|
Common.dial_set(mem, cr, used_percent)
|
|
Common.dial_set(swap, cr, (swaptotal - swapfree) / swaptotal)
|
|
|
|
Common.text_rows_set(cache, cr, 1, cached / memtotal * 100)
|
|
Common.text_rows_set(cache, cr, 2, buffers / memtotal * 100)
|
|
Common.text_rows_set(cache, cr, 3, shmem / memtotal * 100)
|
|
Common.text_rows_set(cache, cr, 4, sreclaimable / memtotal * 100)
|
|
|
|
Timeseries.update(plot, used_percent)
|
|
|
|
for r = 1, NUM_ROWS do
|
|
Table.set(tbl, 1, r, conky(TABLE_CONKY[r].comm, '(%S+)'))
|
|
Table.set(tbl, 2, r, conky(TABLE_CONKY[r].pid))
|
|
Table.set(tbl, 3, r, conky(TABLE_CONKY[r].mem))
|
|
end
|
|
end
|
|
|
|
local draw_static = function(cr)
|
|
Common.drawHeader(cr, header)
|
|
|
|
Common.dial_draw_static(mem, cr)
|
|
Common.dial_draw_static(swap, cr)
|
|
|
|
Common.text_rows_draw_static(cache, cr)
|
|
Timeseries.draw_static(plot, cr)
|
|
|
|
Table.draw_static(tbl, cr)
|
|
end
|
|
|
|
local draw_dynamic = function(cr)
|
|
update(cr)
|
|
|
|
Common.dial_draw_dynamic(mem, cr)
|
|
Common.dial_draw_dynamic(swap, cr)
|
|
|
|
Common.text_rows_draw_dynamic(cache, cr)
|
|
|
|
Timeseries.draw_dynamic(plot, cr)
|
|
|
|
Table.draw_dynamic(tbl, cr)
|
|
end
|
|
|
|
return {dynamic = draw_dynamic, static = draw_static}
|
|
end
|