This program only runs during installation if the "debug" command line option
is provided. It writes out a /tmp/memory.dat file which can be copied off the
system and processed with the provided gnuplot script to display a graph.
---
anaconda.spec.in | 1 +
data/systemd/Makefile.am | 2 +-
data/systemd/instperf.service | 8 +++++
data/systemd/loader.service | 4 +-
scripts/Makefile.am | 5 +++-
scripts/instperf | 58 +++++++++++++++++++++++++++++++++++++++++
scripts/instperf.p | 15 ++++++++++
7 files changed, 89 insertions(+), 4 deletions(-)
create mode 100644 data/systemd/instperf.service
create mode 100755 scripts/instperf
create mode 100644 scripts/instperf.p
diff --git a/anaconda.spec.in b/anaconda.spec.in
index e655c42..707366f 100644
--- a/anaconda.spec.in
+++ b/anaconda.spec.in
@@ -209,6 +209,7 @@ update-desktop-database &> /dev/null || :
%doc docs/anaconda-release-notes.txt
/lib/systemd/system/*
/lib/udev/rules.d/70-anaconda.rules
+%{_bindir}/instperf
%{_sbindir}/anaconda
%{_sbindir}/logpicker
%ifarch i386 i486 i586 i686 x86_64
diff --git a/data/systemd/Makefile.am b/data/systemd/Makefile.am
index cebbd2c..4654695 100644
--- a/data/systemd/Makefile.am
+++ b/data/systemd/Makefile.am
@@ -18,7 +18,7 @@
# Author: Chris Lumens <clumens(a)redhat.com>
systemddir = /lib/systemd/system
-dist_systemd_DATA = anaconda-shell.service anaconda.target loader.service tmp.mount
+dist_systemd_DATA = anaconda-shell.service anaconda.target loader.service instperf.service tmp.mount
MAINTAINERCLEANFILES = Makefile.in
diff --git a/data/systemd/instperf.service b/data/systemd/instperf.service
new file mode 100644
index 0000000..b843872
--- /dev/null
+++ b/data/systemd/instperf.service
@@ -0,0 +1,8 @@
+[Unit]
+Description=anaconda performance monitor
+Before=loader.service
+
+[Service]
+WorkingDirectory=/
+ExecStart=/usr/bin/instperf
+ConditionKernelCommandLine=debug
diff --git a/data/systemd/loader.service b/data/systemd/loader.service
index d808067..5d2b0ac 100644
--- a/data/systemd/loader.service
+++ b/data/systemd/loader.service
@@ -1,7 +1,7 @@
[Unit]
Description=The anaconda loader
-Requires=dbus.service udev.service rsyslog.service tmp.mount
-After=dbus.service udev.service rsyslog.service tmp.mount
+Requires=dbus.service udev.service rsyslog.service tmp.mount instperf.service
+After=dbus.service udev.service rsyslog.service tmp.mount instperf.service
[Service]
Environment=HOME=/root MALLOC_CHECK_=2 MALLOC_PERTURB_=204 PATH=/usr/bin:/bin:/sbin:/usr/sbin:/mnt/sysimage/bin:/mnt/sysimage/usr/bin:/mnt/sysimage/usr/sbin:/mnt/sysimage/sbin PYTHONPATH=/tmp/updates TERM=linux
diff --git a/scripts/Makefile.am b/scripts/Makefile.am
index 329a2fc..7b843a0 100644
--- a/scripts/Makefile.am
+++ b/scripts/Makefile.am
@@ -25,9 +25,12 @@ dist_scripts_DATA = mk-images.* pyrc.py
dist_noinst_SCRIPTS = getlangnames.py upd-bootimage upd-initrd upd-kernel \
makeupdates
-dist_bin_SCRIPTS = analog anaconda-cleanup
+dist_bin_SCRIPTS = analog anaconda-cleanup instperf
stage2scriptsdir = $(datadir)/$(PACKAGE_NAME)
dist_stage2scripts_SCRIPTS = restart-anaconda
+miscdir = $(datadir)/$(PACKAGE_NAME)
+dist_misc_DATA = instperf.p
+
MAINTAINERCLEANFILES = Makefile.in
diff --git a/scripts/instperf b/scripts/instperf
new file mode 100755
index 0000000..3999834
--- /dev/null
+++ b/scripts/instperf
@@ -0,0 +1,58 @@
+#!/usr/bin/python
+
+import logging
+from string import split
+from subprocess import Popen, PIPE
+import time
+
+# grab the top five memory consuming processes, returning them in a string of
+# of the format:
+#
+# name1:kB1,name2:kB2,...,name5:kB5
+def topProcesses():
+ output = Popen(["ps", "-eo", "comm,rss", "--sort", "-rss", "--no-headers"], stdout=PIPE).communicate()[0]
+ top5 = output.split("\n")[:5]
+ return ",".join(map(lambda (a,b): a+":"+b, map(split, top5)))
+
+def logit():
+ buffers = 0
+ cached = 0
+ memTotal = 0
+ memFree = 0
+ swapTotal = 0
+ swapFree = 0
+
+ global mem_logger
+
+ with open("/proc/meminfo") as f:
+ for line in f.readlines():
+ if line.startswith("Buffers:"):
+ buffers = line.split()[1]
+ elif line.startswith("Cached:"):
+ cached = line.split()[1]
+ elif line.startswith("MemTotal:"):
+ memTotal = line.split()[1]
+ elif line.startswith("MemFree:"):
+ memFree = line.split()[1]
+ elif line.startswith("SwapTotal:"):
+ swapTotal = line.split()[1]
+ elif line.startswith("SwapFree:"):
+ swapFree = line.split()[1]
+
+ d = {"memUsed": int(memTotal)-int(memFree)-int(cached)-int(buffers),
+ "swapUsed": int(swapTotal)-int(swapFree),
+ "procs": topProcesses()}
+
+ mem_logger.debug("%(memUsed)d %(swapUsed)d %(procs)s" % d)
+
+mem_logger = logging.getLogger("memLog")
+mem_logger.setLevel(logging.DEBUG)
+
+handler = logging.FileHandler("/tmp/memory.dat")
+handler.setLevel(logging.DEBUG)
+handler.setFormatter(logging.Formatter("%(asctime)s %(message)s", "%H:%M:%S"))
+mem_logger.addHandler(handler)
+
+while True:
+ logit()
+ time.sleep(10)
diff --git a/scripts/instperf.p b/scripts/instperf.p
new file mode 100644
index 0000000..078a5a1
--- /dev/null
+++ b/scripts/instperf.p
@@ -0,0 +1,15 @@
+# This script processes a memory.dat file as generated by instperf during
+# installation and writes out a graph to memusage.png.
+set terminal png size 1024,768
+set output "memusage.png"
+set title "anaconda Memory Usage"
+set xlabel "Time"
+set xtics rotate
+set xdata time
+set timefmt "%H:%M:%S"
+set ylabel "Memory Used (in KB)\n(Total-Free-Buffers-Cached)"
+set format y "%.0f"
+set grid
+
+plot "memory.dat" using 1:2 title "Memory" with lines, \
+ "memory.dat" using 1:3 title "Swap" with lines
--
1.7.4.1