Module: Polyrun::SpecQuality::Profile

Defined in:
lib/polyrun/spec_quality/profile.rb

Overview

Stdlib per-example CPU / allocation / IO snapshots.

Class Method Summary collapse

Class Method Details

.diff(before, after) ⇒ Object



33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
# File 'lib/polyrun/spec_quality/profile.rb', line 33

def diff(before, after)
  before ||= {}
  after ||= {}
  out = {}
  %w[cpu_user cpu_system gc_allocated gc_heap_live io_read_bytes io_write_bytes].each do |k|
    b = before[k]
    a = after[k]
    next if b.nil? && a.nil?

    delta = numeric(a) - numeric(b)
    out[k] = delta if delta.positive? || k.start_with?("cpu")
    out[k] = delta
  end
  out
end

.enabled_dimensions(profile_list) ⇒ Object



49
50
51
# File 'lib/polyrun/spec_quality/profile.rb', line 49

def enabled_dimensions(profile_list)
  Array(profile_list).map(&:to_s).map(&:downcase)
end

.read_proc_ioObject

rubocop:enable Metrics/AbcSize



76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
# File 'lib/polyrun/spec_quality/profile.rb', line 76

def read_proc_io
  path = "/proc/self/io"
  return {read_bytes: nil, write_bytes: nil} unless File.readable?(path)

  read_bytes = nil
  write_bytes = nil
  File.foreach(path) do |line|
    case line
    when /\Aread_bytes:\s+(\d+)/
      read_bytes = Regexp.last_match(1).to_i
    when /\Awrite_bytes:\s+(\d+)/
      write_bytes = Regexp.last_match(1).to_i
    end
  end
  {read_bytes: read_bytes, write_bytes: write_bytes}
rescue SystemCallError
  {read_bytes: nil, write_bytes: nil}
end

.slice_profile(diff, dimensions) ⇒ Object

rubocop:disable Metrics/AbcSize -- profile dimension slice



54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
# File 'lib/polyrun/spec_quality/profile.rb', line 54

def slice_profile(diff, dimensions)
  dims = enabled_dimensions(dimensions)
  return diff if dims.empty?

  out = {}
  out["wall"] = diff["wall"] if diff.key?("wall") && dims.include?("wall")
  if dims.include?("cpu")
    out["cpu_user"] = diff["cpu_user"] if diff.key?("cpu_user")
    out["cpu_system"] = diff["cpu_system"] if diff.key?("cpu_system")
  end
  if dims.include?("mem")
    out["gc_allocated"] = diff["gc_allocated"] if diff.key?("gc_allocated")
    out["gc_heap_live"] = diff["gc_heap_live"] if diff.key?("gc_heap_live")
  end
  if dims.include?("io")
    out["io_read_bytes"] = diff["io_read_bytes"] if diff.key?("io_read_bytes")
    out["io_write_bytes"] = diff["io_write_bytes"] if diff.key?("io_write_bytes")
  end
  out
end

.snapshot(dimensions: %w[cpu mem io wall])) ⇒ Object



7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
# File 'lib/polyrun/spec_quality/profile.rb', line 7

def snapshot(dimensions: %w[cpu mem io wall])
  dims = enabled_dimensions(dimensions)
  capture_all = dims.empty?
  out = {}

  if capture_all || dims.include?("cpu") || dims.include?("wall")
    cpu = Process.times
    out["cpu_user"] = cpu.utime
    out["cpu_system"] = cpu.stime
  end

  if capture_all || dims.include?("mem")
    gc = GC.stat
    out["gc_allocated"] = gc[:total_allocated_objects]
    out["gc_heap_live"] = gc[:heap_live_slots]
  end

  if capture_all || dims.include?("io")
    io = read_proc_io
    out["io_read_bytes"] = io[:read_bytes]
    out["io_write_bytes"] = io[:write_bytes]
  end

  out
end