diff --git a/profile/gnuplot/memory_time.gpi b/profile/gnuplot/memory_time.gpi new file mode 100644 index 0000000..b9391b6 --- /dev/null +++ b/profile/gnuplot/memory_time.gpi @@ -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" diff --git a/profile/lexer/big_xml.rb b/profile/lexer/big_xml.rb index 20db5bf..f528693 100644 --- a/profile/lexer/big_xml.rb +++ b/profile/lexer/big_xml.rb @@ -1,8 +1,7 @@ require_relative '../profile_helper' -xml = read_big_xml -lexer = Oga::XML::Lexer.new(xml) +xml = read_big_xml -profile_memory('lexer/big_xml') - -lexer.advance { |tok| } +profile_memory('lexer/big_xml') do + Oga::XML::Lexer.new(xml).advance { } +end diff --git a/profile/parser/big_xml.rb b/profile/parser/big_xml.rb index 4baea58..c2af762 100644 --- a/profile/parser/big_xml.rb +++ b/profile/parser/big_xml.rb @@ -1,8 +1,7 @@ require_relative '../profile_helper' -xml = read_big_xml -parser = Oga::XML::Parser.new(xml) +xml = read_big_xml -profile_memory('parser/big_xml') - -parser.parse +profile_memory('parser/big_xml') do + Oga::XML::Parser.new(xml).parse +end diff --git a/profile/plot.sh b/profile/plot.sh new file mode 100755 index 0000000..5aa706b --- /dev/null +++ b/profile/plot.sh @@ -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}" diff --git a/profile/plot/lexer/big_xml.gnuplot b/profile/plot/lexer/big_xml.gnuplot deleted file mode 100755 index 4de691c..0000000 --- a/profile/plot/lexer/big_xml.gnuplot +++ /dev/null @@ -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: diff --git a/profile/plot/parser/big_xml.gnuplot b/profile/plot/parser/big_xml.gnuplot deleted file mode 100755 index a836605..0000000 --- a/profile/plot/parser/big_xml.gnuplot +++ /dev/null @@ -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: diff --git a/profile/plot/pull_parser/big_xml.gnuplot b/profile/plot/pull_parser/big_xml.gnuplot deleted file mode 100755 index c8b7df3..0000000 --- a/profile/plot/pull_parser/big_xml.gnuplot +++ /dev/null @@ -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: diff --git a/profile/profile_helper.rb b/profile/profile_helper.rb index d021579..763069a 100644 --- a/profile/profile_helper.rb +++ b/profile/profile_helper.rb @@ -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 diff --git a/profile/pull_parser/big_xml.rb b/profile/pull_parser/big_xml.rb index 716498c..7e6e4d5 100644 --- a/profile/pull_parser/big_xml.rb +++ b/profile/pull_parser/big_xml.rb @@ -1,8 +1,8 @@ require_relative '../profile_helper' -xml = read_big_xml -parser = Oga::XML::PullParser.new(xml) +xml = read_big_xml -profile_memory('pull_parser/big_xml') +profile_memory('pull_parser/big_xml') do + Oga::XML::PullParser.new(xml).parse { } +end -parser.parse { |node| }