bitfab 0.57.0 → 0.57.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 1cd6fe2aaa2d03dea82e1d6a14b63e5a60eec3169c33489ce54795840ab6db8c
4
- data.tar.gz: 1637726e4aa1cfa7940ecb65e1b10684b0d1236885a3c1ddd0d3748c8c7a874f
3
+ metadata.gz: '054905de819e592d260f623159ed33c50c6062e24a35f28005940005c45c8652'
4
+ data.tar.gz: fbf28893c51b904efc74fc2d880d375df4c2d8cd6af46b2421d554083e706a87
5
5
  SHA512:
6
- metadata.gz: 391ca0dbc155bf7826f8ff4245d305d6d426cd8cd330a2c92564de8eac72ee229d928faad6d74f72f3d7163cf8a950fab1c6dfc96c5ddefdbd215ba0167382a1
7
- data.tar.gz: c8a4c5172ecb6f78b309303062167073384bbdd7079c5fc5618200b877526a44bd495f85b2e6120b9a602542f883b80d2872ba2519f81109d3e17d83977b301f
6
+ metadata.gz: 0d5dfb24ef74d933781ad9b6f8d445583dceffcfe0eaf5189b9ba2ec2405b5ef4b108ed828ea8fbb42c66f3bd3e82d171f88d873bb77ae99640185fcbbacf01c
7
+ data.tar.gz: f5509659a2e3f8d8df265d3abba09b106f6553bce8b7d1d9c4227d43c10f58ad74b01400f102e6140d2b37d6a8f518217a11a5914269b7a1a1de779489e0bcf0
@@ -5,8 +5,23 @@ require "open3"
5
5
  module Bitfab
6
6
  class ReplayMemoryThrottle
7
7
  MIB = 1024 * 1024
8
+ MAX_SWAP_USED_RATIO = 0.85
9
+ CRITICAL_PRESSURE_LEVEL = 4
10
+ CRITICAL_STALL_PERCENT = 10.0
11
+ STALL_FILES = ["/sys/fs/cgroup/memory.pressure", "/proc/pressure/memory"].freeze
8
12
  attr_reader :condition
9
13
 
14
+ def self.pressure_critical_from_level(raw)
15
+ level = Integer(raw.to_s.strip, exception: false)
16
+ return nil unless level&.positive?
17
+ level >= CRITICAL_PRESSURE_LEVEL
18
+ end
19
+
20
+ def self.pressure_critical_from_stall(raw)
21
+ percent = raw.to_s[/^full\b[^\n]*?\bavg10=([\d.]+)/, 1]
22
+ percent && percent.to_f >= CRITICAL_STALL_PERCENT
23
+ end
24
+
10
25
  def initialize(enabled: true)
11
26
  @enabled = enabled && !%w[0 off false no].include?(ENV.fetch("BITFAB_REPLAY_MEMORY_THROTTLE", "").strip.downcase)
12
27
  @initial_budget = env_bytes("BITFAB_REPLAY_CHILD_MEMORY_MB", 2048 * MIB)
@@ -50,7 +65,7 @@ module Bitfab
50
65
  def headroom?
51
66
  return true if @resident.empty?
52
67
  snapshot = memory_snapshot
53
- return false if snapshot[:swap_used_ratio] && snapshot[:swap_used_ratio] >= 0.85
68
+ return false if under_strain?(snapshot)
54
69
  return true unless snapshot[:available]
55
70
  budget = [@peak.positive? ? @peak : @initial_budget, *@resident.values].max
56
71
  unrealized = @resident.values.sum { |rss| [budget - rss, 0].max }
@@ -61,14 +76,15 @@ module Bitfab
61
76
  if File.file?("/proc/meminfo")
62
77
  fields = File.read("/proc/meminfo").scan(/^(\w+):\s+(\d+)/).to_h.transform_values { |value| value.to_i * 1024 }
63
78
  total = fields["SwapTotal"].to_i
64
- {available: fields["MemAvailable"], swap_used_ratio: total.positive? ? 1.0 - fields["SwapFree"].to_f / total : 0.0}
79
+ {available: fields["MemAvailable"], swap_used_ratio: total.positive? ? 1.0 - fields["SwapFree"].to_f / total : 0.0, pressure_critical: stall_files_pressure_critical}
65
80
  elsif RUBY_PLATFORM.include?("darwin")
66
81
  total = Integer(read_command("sysctl", "-n", "hw.memsize").to_s, exception: false)
67
82
  percent = Integer(read_command("sysctl", "-n", "kern.memorystatus_level").to_s, exception: false)
68
83
  swap = read_command("sysctl", "-n", "vm.swapusage").to_s
69
84
  total_swap = swap[/total = ([\d.]+)/, 1].to_f
70
85
  used_swap = swap[/used = ([\d.]+)/, 1].to_f
71
- {available: (percent && total&.positive?) ? total * percent.to_i.clamp(0, 100) / 100 : nil, swap_used_ratio: total_swap.positive? ? used_swap / total_swap : 0.0}
86
+ pressure = self.class.pressure_critical_from_level(read_command("sysctl", "-n", "kern.memorystatus_vm_pressure_level"))
87
+ {available: (percent && total&.positive?) ? total * percent.to_i.clamp(0, 100) / 100 : nil, swap_used_ratio: total_swap.positive? ? used_swap / total_swap : 0.0, pressure_critical: pressure}
72
88
  else
73
89
  {}
74
90
  end
@@ -89,6 +105,22 @@ module Bitfab
89
105
 
90
106
  private
91
107
 
108
+ def under_strain?(snapshot)
109
+ return snapshot[:pressure_critical] unless snapshot[:pressure_critical].nil?
110
+ !!(snapshot[:swap_used_ratio] && snapshot[:swap_used_ratio] >= MAX_SWAP_USED_RATIO)
111
+ end
112
+
113
+ def stall_files_pressure_critical
114
+ STALL_FILES.each do |path|
115
+ next unless File.file?(path)
116
+ critical = self.class.pressure_critical_from_stall(File.read(path))
117
+ return critical unless critical.nil?
118
+ end
119
+ nil
120
+ rescue
121
+ nil
122
+ end
123
+
92
124
  def env_bytes(key, fallback)
93
125
  value = Integer(ENV.fetch(key, "0"), exception: false)
94
126
  value&.positive? ? value * MIB : fallback
@@ -91,6 +91,14 @@ module Bitfab
91
91
 
92
92
  module_function
93
93
 
94
+ # get_assertions returns every state so a reviewer can see drafts, but only an
95
+ # approved assertion is checked on a replay, so narrowing on anything else
96
+ # would pick traces the run cannot be judged against. The server applies the
97
+ # same rule when it revalidates the selection.
98
+ def approved_assertion?(assertions)
99
+ assertions.any? { |assertion| assertion["approvalState"] == "approved" }
100
+ end
101
+
94
102
  def bound_trace_ids(client, trace_ids, limit, only_with_assertions)
95
103
  unless limit.is_a?(Integer) && limit.positive?
96
104
  raise ArgumentError, "Replay limit must be a positive integer."
@@ -100,13 +108,13 @@ module Bitfab
100
108
  selected = []
101
109
  trace_ids.each do |trace_id|
102
110
  result = client.traces.get_assertions(trace_id)
103
- if result.fetch("inheritedFrom").nil? && !result.fetch("assertions").empty?
111
+ if result.fetch("inheritedFrom").nil? && approved_assertion?(result.fetch("assertions"))
104
112
  selected << trace_id
105
113
  break if selected.length == limit
106
114
  end
107
115
  end
108
116
  if selected.empty?
109
- raise ArgumentError, "No traces with active assertions matched this replay selection."
117
+ raise ArgumentError, "No traces with approved assertions matched this replay selection."
110
118
  end
111
119
  selected
112
120
  end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Bitfab
4
- VERSION = "0.57.0"
4
+ VERSION = "0.57.2"
5
5
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: bitfab
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.57.0
4
+ version: 0.57.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - Harvest Team