Loading...
--- libmalloc/libmalloc-317.40.8/tests/MallocBenchTest/MALLOC_BENCH/run-malloc-benchmarks
+++ /dev/null
@@ -1,396 +0,0 @@
-#!/usr/bin/env ruby
-# coding: utf-8
-
-require 'getoptlong'
-require 'pathname'
-
-$benchmarks_all = [
- # Single-threaded benchmarks.
- "churn",
- "list_allocate",
- "tree_allocate",
- "tree_churn",
- "fragment",
- "fragment_iterate",
- "medium",
- "big",
-
- # Benchmarks based on browser recordings.
- "facebook",
- "reddit",
- "flickr",
- "theverge",
- "nimlang",
-
- # Multi-threaded benchmark variants.
- "message_one",
- "message_many",
- "churn --parallel",
- "list_allocate --parallel",
- "tree_allocate --parallel",
- "tree_churn --parallel",
- "fragment --parallel",
- "fragment_iterate --parallel",
-
- # These tests often crash TCMalloc: <rdar://problem/13657137>.
- "medium --parallel",
- "big --parallel",
-
- # Enable these tests to test memory footprint. The way they run is not
- # really compatible with throughput testing.
- # "reddit_memory_warning --runs 0",
- # "flickr_memory_warning --runs 0",
- # "theverge_memory_warning --runs 0",
-
- # Enable this test to test shrinking back down from a large heap while a process remains active.
- # The way it runs is not really compatible with throughput testing.
- # "balloon"
- "facebook --parallel",
- "reddit --parallel",
- "flickr --parallel",
- "theverge --parallel",
- # "nimlang --use-thread-id",
-]
-
-$benchmarks_memory = [
- "facebook",
- "reddit",
- "flickr",
- "theverge",
- "nimlang"
-]
-
-$benchmarks_memory_warning = [
- "reddit_memory_warning --runs 0",
- "flickr_memory_warning --runs 0",
- "theverge_memory_warning --runs 0",
-]
-
-$benchmarks = $benchmarks_all
-$heap = 0
-
-def usage
- puts "run-malloc-benchmarks [options] /path/to/MallocBench Name:/path/to/libmbmalloc.dylib [ Name:/path/to/libmbmalloc.dylib ]"
- puts
- puts " Runs a suite of memory allocation and access benchmarks."
- puts
- puts " <Name:/path/to/libmbmalloc.dylib> is a symbolic name followed by a path to libmbmalloc.dylib."
- puts
- puts " Specify \"SystemMalloc\" to test the built-in libc malloc."
- puts " Specify \"NanoMalloc\" to test the built-in libc malloc using the NanoMalloc zone."
- puts
- puts " Example usage:"
- puts
- puts " run-malloc-benchmarks /BUILD/MallocBench SystemMalloc:/BUILD/libmbmalloc.dylib NanoMalloc:/BUILD/libmbmalloc.dylib"
- puts " run-malloc-benchmarks /BUILD/MallocBench FastMalloc:/BUILD/FastMalloc/libmbmalloc.dylib"
- puts " run-malloc-benchmarks --benchmark churn SystemMalloc:/BUILD/libmbmalloc.dylib FastMalloc:/BUILD/FastMalloc/libmbmalloc.dylib"
- puts
- puts "Options:"
- puts
- puts " --benchmark <benchmark> Select a single benchmark to run instead of the full suite."
- puts " --heap <heap> Set a baseline heap size."
- puts
-end
-
-class Dylib
- attr_reader :name
- attr_reader :path
-
- def initialize(name, path)
- @name = name
- @path = path
- end
-end
-
-class Results
- attr_reader :executionTime
- attr_reader :peakMemory
- attr_reader :memoryAtEnd
-
- def initialize(executionTime, peakMemory, memoryAtEnd)
- @executionTime = executionTime
- @peakMemory = peakMemory
- @memoryAtEnd = memoryAtEnd
- end
-end
-
-class Stat
- attr_reader :benchmark
- attr_reader :result
-
- def initialize(benchmark, result)
- @benchmark = benchmark
- @result = result[/\d+/].to_i
- end
-end
-
-class TimeStat < Stat
- def to_s
- @result + "ms"
- end
-end
-
-class MemoryStat < Stat
- def to_s
- @result + "kB"
- end
-end
-
-class PeakMemoryStat < Stat
- def to_s
- @result + "kB"
- end
-end
-
-def lpad(str, chars)
- if str.length > chars
- str
- else
- "%#{chars}s"%(str)
- end
-end
-
-def rpad(str, chars)
- while str.length < chars
- str += " "
- end
- str
-end
-
-def computeArithmeticMean(array)
- sum = 0.0
- array.each {
- | value |
- sum += value
- }
- (sum / array.length)
-end
-
-def computeGeometricMean(array)
- mult = 1.0
- array.each {
- | value |
- mult *= value ? value : 1.0
- }
- (mult ** (1.0 / array.length))
-end
-
-def computeHarmonicMean(array)
- 1.0 / computeArithmeticMean(array.collect{ | value | 1.0 / value })
-end
-
-def lowerIsBetter(a, b, better, worse)
- if b < a
- return "^ " + (a.to_f / b.to_f).round(2).to_s + "x " + better
- end
-
- if b == a
- return ""
- end
-
- "! " + (b.to_f / a.to_f).round(2).to_s + "x " + worse
-end
-
-
-def lowerIsFaster(a, b)
- lowerIsBetter(a, b, "faster", "slower")
-end
-
-def lowerIsSmaller(a, b)
- lowerIsBetter(a, b, "smaller", "bigger")
-end
-
-def numberWithDelimiter(number)
- number.to_s.reverse.gsub(/...(?=.)/,'\&,').reverse
-end
-
-def prettify(number, suffix)
- numberWithDelimiter(number) + suffix
-end
-
-def parseOptions
- GetoptLong.new(
- ['--benchmark', GetoptLong::REQUIRED_ARGUMENT],
- ['--memory', GetoptLong::NO_ARGUMENT],
- ['--memory_warning', GetoptLong::NO_ARGUMENT],
- ['--heap', GetoptLong::REQUIRED_ARGUMENT],
- ['--help', GetoptLong::NO_ARGUMENT],
- ).each {
- | opt, arg |
- case opt
- when '--benchmark'
- $benchmarks = [ arg ]
- when '--memory'
- $benchmarks = $benchmarks_memory
- when '--memory_warning'
- $benchmarks = $benchmarks_memory_warning
- when '--heap'
- $heap = arg
- when '--help'
- usage
- exit 1
- else
- raise "bad option: #{opt}"
- end
- }
-
- if ARGV.length < 1
- puts "Error: No MallocBench specified."
- exit 1
- end
-
- if ARGV.length < 2
- puts "Error: No dylib specified."
- exit 1
- end
-
- $mallocBench = File.absolute_path(ARGV.shift)
- if !File.exists?($mallocBench)
- puts "File not found: #{$mallocBench}."
- exit 1
- end
-
- $buildDir = Pathname.new($mallocBench).dirname
-
- dylibs = []
- ARGV.each {
- | arg |
- name, path = arg.split(":")
- if !name || name.length < 1 ||
- !path || path.length < 1
- puts "Invalid <Name:/path/to/dylib>: '#{arg}'."
- exit 1
- end
-
- dylib = Dylib.new(name, File.expand_path(path))
-
- if !File.exists?(dylib.path)
- puts "File not found: #{dylib.path}."
- exit 1
- end
-
- dylibs.push(dylib)
- }
- dylibs
-end
-
-def runBenchmarks(dylibs)
- executionTime = []
- peakMemory = []
- memoryAtEnd = []
-
- $benchmarks.each {
- | benchmark |
-
- executionTime.push([])
- peakMemory.push([])
- memoryAtEnd.push([])
-
- dylibs.each {
- | dylib |
-
- $stderr.print "\rRUNNING #{dylib.name}: #{benchmark}... "
- env = "DYLD_LIBRARY_PATH='#{Pathname.new(dylib.path).dirname}' "
- env += "LD_LIBRARY_PATH='#{Pathname.new(dylib.path).dirname}' "
- if dylib.name == "NanoMalloc"
- env += "MallocNanoZone=1 "
- elsif dylib.name == "SystemMalloc"
- env += "MallocNanoZone=0 "
- end
- input = "cd '#{$buildDir}'; #{env} '#{$mallocBench}' --benchmark #{benchmark} --heap #{$heap}}"
- output =`#{input}`
- splitOutput = output.split("\n")
-
- executionTime[-1].push(TimeStat.new(benchmark, splitOutput[1]))
- peakMemory[-1].push(PeakMemoryStat.new(benchmark, splitOutput.length > 3 ? splitOutput[2] : "0"))
- memoryAtEnd[-1].push(MemoryStat.new(benchmark, splitOutput.length > 2 ? splitOutput[3] : "0"))
- }
- }
- $stderr.print "\r \n"
-
- Results.new(executionTime, peakMemory, memoryAtEnd)
-end
-
-def printResults(dylibs, results)
- def printHeader(dylibs, fieldSize)
- print
- print lpad("", fieldSize)
- print lpad(dylibs[0].name, fieldSize)
- if dylibs.length > 1
- print lpad(dylibs[1].name, fieldSize)
- print lpad("Δ", fieldSize)
- end
- print "\n"
- end
-
- def printMetric(name, results, compareFunction, suffix, fieldSize)
- def printMean(name, results, meanFunction, compareFunction, suffix, fieldSize)
- means = []
-
- means.push(meanFunction.call(results.collect { | stats | stats[0].result }))
- print rpad(" " + name, fieldSize)
- print lpad("#{prettify(means[0].round, suffix)}", fieldSize)
-
- if results[0][1]
- means.push(meanFunction.call(results.collect { | stats | stats[1].result }))
- print lpad("#{prettify(means[1].round, suffix)}", fieldSize)
- print lpad(compareFunction.call(means[0], means[1]), fieldSize)
- end
-
- print "\n"
- end
-
- if results[0][0].result == 0
- return
- end
-
- print name + ":\n"
- results.each {
- | stats |
-
- print rpad(" " + stats[0].benchmark, fieldSize)
- print lpad("#{prettify(stats[0].result, suffix)}", fieldSize)
-
- if stats[1]
- print lpad("#{prettify(stats[1].result, suffix)}", fieldSize)
- print lpad(compareFunction.call(stats[0].result, stats[1].result), fieldSize)
- end
-
- print "\n"
- }
-
- print "\n"
-
- printMean("<geometric mean>", results, method(:computeGeometricMean), compareFunction, suffix, fieldSize)
- printMean("<arithmetic mean>", results, method(:computeArithmeticMean), compareFunction, suffix, fieldSize)
- printMean("<harmonic mean>", results, method(:computeHarmonicMean), compareFunction, suffix, fieldSize)
-
- print "\n"
- end
-
- fieldSize = ($benchmarks + ["<arithmetic mean>"]).collect {
- | benchmark |
- benchmark.size
- }.max + 4
-
- printHeader(dylibs, fieldSize)
- printMetric("Execution Time", results.executionTime, method(:lowerIsFaster), "ms", fieldSize)
- printMetric("Peak Memory", results.peakMemory, method(:lowerIsSmaller), "kB", fieldSize)
- printMetric("Memory at End", results.memoryAtEnd, method(:lowerIsSmaller), "kB", fieldSize)
-end
-
-def main
- begin
- dylibs = parseOptions()
- results = runBenchmarks(dylibs)
- printResults(dylibs, results)
- rescue => exception
- puts
- puts
- puts exception
- puts exception.backtrace
- puts
- end
-end
-
-main()