Revamped the profiling setup.

This removes the need for dozens of standalone gnuplot scripts, adds extra
profiling data and makes the actual profiling easier.
This commit is contained in:
Yorick Peterse 2014-05-01 20:54:25 +02:00
parent e54d77fc2f
commit 1c35317165
9 changed files with 94 additions and 82 deletions

View File

@ -0,0 +1,21 @@
# The `sample_file` variable should contain the path to the variable to plot.
set title sample_file
set xlabel "Time"
set ylabel "Memory (MB)"
set xdata time
set timefmt "%Y-%m-%dT%H:%M:%S"
set yrange [0:*]
set term qt persist size 900,600
set grid
set style line 1 lc rgb "#0060ad" lt 1 lw 2 pt 7 ps 1
plot sample_file \
using 1:($2 / 1024 ** 2) \
with linespoints ls 1 \
title "Memory"

View File

@ -1,8 +1,7 @@
require_relative '../profile_helper'
xml = read_big_xml
lexer = Oga::XML::Lexer.new(xml)
profile_memory('lexer/big_xml')
lexer.advance { |tok| }
profile_memory('lexer/big_xml') do
Oga::XML::Lexer.new(xml).advance { }
end

View File

@ -1,8 +1,7 @@
require_relative '../profile_helper'
xml = read_big_xml
parser = Oga::XML::Parser.new(xml)
profile_memory('parser/big_xml')
parser.parse
profile_memory('parser/big_xml') do
Oga::XML::Parser.new(xml).parse
end

18
profile/plot.sh Executable file
View File

@ -0,0 +1,18 @@
#!/usr/bin/env bash
sample_file="$1"
plot_script="$2"
if [[ ! -f "$sample_file" ]]
then
echo "The sample file ${sample_file} does not exist"
exit 1
fi
if [[ ! -f "$plot_script" ]]
then
echo "The gnuplot script ${plot_script} does not exist"
exit 1
fi
gnuplot -e "sample_file='${sample_file}'" "${plot_script}"

View File

@ -1,20 +0,0 @@
#!/usr/bin/env gnuplot
set title "Lexing 10MB of XML"
set xlabel "Sample"
set ylabel "Memory (MB)"
set yrange [0:*]
set term qt persist size 900,600
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:

View File

@ -1,20 +0,0 @@
#!/usr/bin/env gnuplot
set title "DOM parsing 10MB of XML"
set xlabel "Sample"
set ylabel "Memory (MB)"
set yrange [0:*]
set term qt persist size 900,600
set grid
set style line 1 lc rgb "#0060ad" lt 1 lw 2 pt 7 ps 1
plot "profile/samples/parser/big_xml.txt" \
using 0:($1 / 1024 ** 2) \
with linespoints ls 1 \
title "Memory"
# vim: set ft=gnuplot:

View File

@ -1,20 +0,0 @@
#!/usr/bin/env gnuplot
set title "Pull parsing 10MB of XML"
set xlabel "Sample"
set ylabel "Memory (MB)"
set yrange [0:*]
set term qt persist size 900,600
set grid
set style line 1 lc rgb "#0060ad" lt 1 lw 2 pt 7 ps 1
plot "profile/samples/pull_parser/big_xml.txt" \
using 0:($1 / 1024 ** 2) \
with linespoints ls 1 \
title "Memory"
# vim: set ft=gnuplot:

View File

@ -1,5 +1,10 @@
require 'timeout'
require 'time'
require_relative '../lib/oga'
Thread.abort_on_exception = true
##
# Returns memory usage in bytes. This relies on the /proc filesystem, it won't
# work without it.
@ -20,22 +25,52 @@ def read_big_xml
end
##
# Writes memory samples to a file until the thread is killed.
# Runs the specified block for at least N seconds while profiling memory usage
# at semi random intervals.
#
# @param [String] name The name of the samples file.
# @param [Fixnum] interval The sample interval. The default is 200 ms.
# @return [Thread]
# @param [String] duration The amount of seconds to run.
#
def profile_memory(name, interval = 0.2)
return Thread.new do
def profile_memory(name, duration = 30)
monitor = true
threads = []
threads << Thread.new do
puts 'Starting sampler...'
path = File.expand_path("../samples/#{name}.txt", __FILE__)
handle = File.open(path, 'w')
handle.sync = true
loop do
handle.write("#{memory_usage}\n")
while monitor
usage = memory_usage
usage_mb = (usage / 1024 / 1024).round(2)
time = Time.now.strftime('%Y-%m-%dT%H:%M:%S')
sleep(interval)
handle.write("#{time} #{usage}\n")
puts "#{time}: #{usage_mb} MB"
sleep(rand)
end
puts 'Stopping sampler...'
handle.close
end
threads << Thread.new do
start = Time.now
begin
Timeout.timeout(duration) { loop { yield} }
rescue Timeout::Error
diff = Time.now - start
monitor = false
puts "Finished running after #{diff.round(3)} seconds"
end
end
threads.each(&:join)
end

View File

@ -1,8 +1,8 @@
require_relative '../profile_helper'
xml = read_big_xml
parser = Oga::XML::PullParser.new(xml)
profile_memory('pull_parser/big_xml')
profile_memory('pull_parser/big_xml') do
Oga::XML::PullParser.new(xml).parse { }
end
parser.parse { |node| }