Basic memory profiling setup.
This makes it a bit easier to profile memory usage of certain components and plot them using Gnuplot. In the past I would write one-off scripts for this and throw them away, only to figure out I needed them again later on. Profiling samples are written to profile/samples and can be plotted using corresponding Gnuplot scripts found in profile/plot. The latter requires Gnuplot to be installed.
This commit is contained in:
parent
70fcc8534c
commit
53c45c621b
|
@ -7,3 +7,6 @@ lib/oga/xml/lexer.rb
|
||||||
lib/oga/xml/parser.rb
|
lib/oga/xml/parser.rb
|
||||||
|
|
||||||
benchmark/fixtures/big.xml
|
benchmark/fixtures/big.xml
|
||||||
|
|
||||||
|
profile/samples/*.txt
|
||||||
|
profile/samples/lexer/*.txt
|
||||||
|
|
|
@ -0,0 +1,8 @@
|
||||||
|
require_relative '../profile_helper'
|
||||||
|
|
||||||
|
xml = read_big_xml
|
||||||
|
lexer = Oga::XML::Lexer.new(xml)
|
||||||
|
|
||||||
|
profile_memory('lexer/big_xml')
|
||||||
|
|
||||||
|
lexer.advance { |tok| }
|
|
@ -0,0 +1,20 @@
|
||||||
|
#!/usr/bin/env gnuplot
|
||||||
|
|
||||||
|
set title "Lexing 10MB of XML"
|
||||||
|
|
||||||
|
set xlabel "Sample"
|
||||||
|
set ylabel "Memory (MB)"
|
||||||
|
|
||||||
|
set yrange [0:*]
|
||||||
|
|
||||||
|
set term qt persist
|
||||||
|
set grid
|
||||||
|
|
||||||
|
set style line 1 lc rgb "#0060ad" lt 1 lw 2 pt 7 ps 1
|
||||||
|
|
||||||
|
plot "profile/samples/lexer/big_xml.txt" \
|
||||||
|
using 0:($1 / 1024 ** 2) \
|
||||||
|
with linespoints ls 1 \
|
||||||
|
title "Memory"
|
||||||
|
|
||||||
|
# vim: set ft=gnuplot:
|
|
@ -0,0 +1,41 @@
|
||||||
|
require_relative '../lib/oga'
|
||||||
|
|
||||||
|
##
|
||||||
|
# Returns memory usage in bytes. This relies on the /proc filesystem, it won't
|
||||||
|
# work without it.
|
||||||
|
#
|
||||||
|
# @return [Fixnum]
|
||||||
|
#
|
||||||
|
def memory_usage
|
||||||
|
return File.read('/proc/self/status').match(/VmRSS:\s+(\d+)/)[1].to_i * 1024
|
||||||
|
end
|
||||||
|
|
||||||
|
##
|
||||||
|
# Reads a big XML file and returns it as a String.
|
||||||
|
#
|
||||||
|
# @return [String]
|
||||||
|
#
|
||||||
|
def read_big_xml
|
||||||
|
return File.read(File.expand_path('../../benchmark/fixtures/big.xml', __FILE__))
|
||||||
|
end
|
||||||
|
|
||||||
|
##
|
||||||
|
# Writes memory samples to a file until the thread is killed.
|
||||||
|
#
|
||||||
|
# @param [String] name The name of the samples file.
|
||||||
|
# @param [Fixnum] interval The sample interval. The default is 200 ms.
|
||||||
|
# @return [Thread]
|
||||||
|
#
|
||||||
|
def profile_memory(name, interval = 0.2)
|
||||||
|
return Thread.new do
|
||||||
|
path = File.expand_path("../samples/#{name}.txt", __FILE__)
|
||||||
|
handle = File.open(path, 'w')
|
||||||
|
handle.sync = true
|
||||||
|
|
||||||
|
loop do
|
||||||
|
handle.write("#{memory_usage}\n")
|
||||||
|
|
||||||
|
sleep(interval)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
Loading…
Reference in New Issue