class MetadataAnalysis
Constants
- GRANULARITY
- Unit
Public Class Methods
new(md)
click to toggle source
# File lib/thinp_xml/thinp/analysis.rb, line 12 def initialize(md) @md = md end
Public Instance Methods
block_length_histograms()
click to toggle source
# File lib/thinp_xml/thinp/analysis.rb, line 16 def block_length_histograms @md.devices.each do |dev| puts "device #{dev.dev_id}" block_length_histogram(dev) puts "" end end
fragmentations()
click to toggle source
# File lib/thinp_xml/thinp/analysis.rb, line 24 def fragmentations @md.devices.each do |dev| puts "device #{dev.dev_id}" printf(" %10s %10s %10s %10s\n", 'io size', 'seeks/io', 'distance/seek', 'distance/io') puts " -------------------------------------------------" power = 0 loop do io_size = 8 * 4 ** power r = fragmentation(dev, @md.superblock.data_block_size, io_size) break if r.nil? seeks, dist = r printf(" %10s\t%.3f\t%s\t\t%s\n", segments_to_human(io_size), seeks, segments_to_human(dist.to_i), segments_to_human(seeks * dist.to_i)) power += 1 end end end
Private Instance Methods
block_length_histogram(dev)
click to toggle source
# File lib/thinp_xml/thinp/analysis.rb, line 194 def block_length_histogram(dev) histogram = Hash.new {|hash, key| hash[key] = 0} dev.mappings.each do |m| histogram[nearest_power(m.length)] += m.length end format_histogram(histogram.sort) end
format_histogram(pairs)
click to toggle source
assumes the pairs are sorted
# File lib/thinp_xml/thinp/analysis.rb, line 184 def format_histogram(pairs) width = 80 m = pairs.inject(0) {|m, p| m = [m, p[1]].max} pairs.each do |bin, count| printf("%-8d: %s\n", 2 ** bin, '*' * (width * count / m)) end end
fragmentation(dev, block_size, io_size)
click to toggle source
# File lib/thinp_xml/thinp/analysis.rb, line 144 def fragmentation(dev, block_size, io_size) # Break the mappings up into logical segments. Each segment will # have one or more physical segments. logical_segments = to_logical_segments(mappings_to_phys_segments(dev.mappings, block_size)) total_ios = 0.0 total_seeks = 0.0 total_seek_distance = 0.0 logical_segments.each do |lseg| # calculate the nr of different ios of |io_size| can fit into nr_ios = unique_ios_per_lseg(lseg, io_size, GRANULARITY) next if nr_ios == 0 total_ios += nr_ios # now we look at the junctions between physical segments pre = 0 post = lseg.length psegs = lseg.physical_segments if psegs.length > 1 0.upto(psegs.length - 2) do |i| l = psegs[i].length pre += l post -= l nr_seeks = ios_that_overlap_junction(pre, post, io_size, GRANULARITY) total_seeks += nr_seeks # FIXME: check we can handle these large numbers total_seek_distance += nr_seeks * ((psegs[i].data_begin + psegs[i].length) - psegs[i + 1].data_begin).abs end end end (total_ios == 0) ? nil : [total_seeks / total_ios, total_seeks > 0 ? total_seek_distance / total_seeks : 0] end
ios_that_overlap_junction(pre, post, io_size, granularity)
click to toggle source
|pre| and |post| are the length in the lseg before and after the junction FIXME: check this
# File lib/thinp_xml/thinp/analysis.rb, line 115 def ios_that_overlap_junction(pre, post, io_size, granularity) pre /= granularity post /= granularity io_size /= granularity intersections = io_size - 1 r = intersections if pre < io_size r -= intersections - pre end if post < io_size r -= intersections - post end r end
mappings_to_phys_segments(mappings, block_size)
click to toggle source
# File lib/thinp_xml/thinp/analysis.rb, line 76 def mappings_to_phys_segments(mappings, block_size) mappings.map do |m| PhysicalSegment.new(m.origin_begin * block_size, m.data_begin * block_size, m.length * block_size) end end
nearest_power(n)
click to toggle source
# File lib/thinp_xml/thinp/analysis.rb, line 204 def nearest_power(n) 1.upto(32) do |p| if 2 ** p > n return p - 1 end end end
rand_io(max, io_size)
click to toggle source
# File lib/thinp_xml/thinp/analysis.rb, line 72 def rand_io(max, io_size) round_down(rand(max - io_size), 8) end
round_down(n, d)
click to toggle source
# File lib/thinp_xml/thinp/analysis.rb, line 68 def round_down(n, d) (n / d) * d end
segments_to_human(size)
click to toggle source
# File lib/thinp_xml/thinp/analysis.rb, line 54 def segments_to_human(size) units = [Unit.new(2048 * 1024, 'g'), Unit.new(2048, 'm'), Unit.new(2, 'k')] units.each do |u| if size >= u.factor return "%.2f #{u.abbrev}" % [Float(size) / Float(u.factor)] end end "#{size * 512}b" end
to_logical_segments(p_segs)
click to toggle source
FIXME: test this
# File lib/thinp_xml/thinp/analysis.rb, line 85 def to_logical_segments(p_segs) l_segs = Array.new if p_segs.empty? return l_segs end while !p_segs.empty? a = Array.new p = p_segs.shift a << p while !p_segs.empty? && (p_segs[0].origin_begin == p.origin_begin + p.length) p = p_segs.shift a << p end l_segs << LogicalSegment.new(a.inject(0) {|tot, ps| tot + ps.length}, a) end l_segs end
unique_ios_per_lseg(lseg, io_size, granularity)
click to toggle source
# File lib/thinp_xml/thinp/analysis.rb, line 109 def unique_ios_per_lseg(lseg, io_size, granularity) (lseg.length < io_size) ? 0 : ((lseg.length - io_size) / granularity) + 1 end