Add bin and edit workflow
Gitea Actions Demo / Explore-Gitea-Actions (push) Failing after 9s

This commit is contained in:
2026-09-16 13:11:16 -06:00
parent c8ac4fcae5
commit 4cee170d66
17576 changed files with 895740 additions and 2 deletions
@@ -0,0 +1,76 @@
# frozen_string_literal: true
require_relative 'ruby_object_leak_tracker'
require_relative 'os_memory_leak_tracker'
module MemoryTestHelpers
class << self
attr_accessor :gc_proc, :iterations, :logger
def setup
if RUBY_PLATFORM == "java"
# for leak detection
JRuby.objectspace = true if defined?(JRuby)
# for gc
require 'java'
java_import 'java.lang.System'
self.gc_proc = proc { System.gc }
else
self.gc_proc = proc { GC.start }
end
end
end
module TestMethods
def memory_leak_test(description, &block)
context(description) do
it "doesn't leak ruby objects" do
object_leak_tracker = RubyObjectLeakTracker.new
track_memory_usage(object_leak_tracker, &block)
object_leak_tracker.total_difference_between_runs.should be <= 10
end
it "doesn't leak OS memory (C interop check)" do
os_memory_leak_tracker = OSMemoryLeakTracker.new
track_memory_usage(os_memory_leak_tracker, &block)
os_memory_leak_tracker.total_difference_between_runs.should be <= 10
end
end
end
end
def track_memory_usage(tracker)
# Intentionally do all this setup before we do any testing
logger = MemoryTestHelpers.logger
iterations = MemoryTestHelpers.iterations
checkpoint_frequency = (iterations / 10.0).to_i
gc_frequency = 20
warmup_iterations = [(iterations / 3.0).to_i, 500].min
logger.info "Performing #{warmup_iterations} warmup iterations"
warmup_iterations.times do
yield
MemoryTestHelpers.gc_proc.call
end
tracker.capture_initial_memory_usage
logger.info "Performing #{iterations} iterations (checkpoint every #{checkpoint_frequency})"
iterations.times do |i|
yield
last_iteration = (i == iterations - 1)
checkpoint = last_iteration || (i % checkpoint_frequency == 0)
if checkpoint || (i % gc_frequency == 0)
MemoryTestHelpers.gc_proc.call
end
if checkpoint
logger.info "Iteration #{i} checkpoint"
tracker.capture_memory_usage
tracker.dump_status(logger)
end
end
end
end
@@ -0,0 +1,48 @@
# frozen_string_literal: true
class OSMemoryLeakTracker
attr_reader :current_run
def initialize
@previous_run = @current_run = 0
end
def difference_between_runs(basis=@previous_run)
@current_run - basis
end
def total_difference_between_runs
difference_between_runs(@initial_count_run)
end
def capture_initial_memory_usage
capture_memory_usage
@initial_count_run = @current_run
end
def capture_memory_usage
@previous_run = @current_run
@current_run = rss_bytes
end
def dump_status(logger)
delta = difference_between_runs
logger.add(log_level(delta), sprintf("\tTotal memory usage (kb): %d (%+d)", current_run, delta))
end
private
# amount of memory the current process "is using", in RAM
# (doesn't include any swap memory that it may be using, just that in actual RAM)
# Code loosely based on https://github.com/rdp/os/blob/master/lib/os.rb
# returns 0 on windows
def rss_bytes
if ENV['OS'] == 'Windows_NT'
0
else
`ps -o rss= -p #{Process.pid}`.to_i # in kilobytes
end
end
def log_level(delta)
delta > 0 ? Logger::WARN : Logger::DEBUG
end
end
@@ -0,0 +1,49 @@
# frozen_string_literal: true
class RubyObjectLeakTracker
attr_reader :previous_count_hash, :current_count_hash
def initialize
@previous_count_hash = @current_count_hash = {}
end
def difference_between_runs(basis=@previous_count_hash)
@difference_between_runs ||= Hash[@current_count_hash.map do |object_class, count|
[object_class, count - (basis[object_class] || 0)]
end]
end
def total_difference_between_runs
difference_between_runs(@initial_count_hash).values.inject(0) { |sum, count| sum + count }
end
def capture_initial_memory_usage
capture_memory_usage
@initial_count_hash = @current_count_hash
end
def capture_memory_usage
@difference_between_runs = nil
@previous_count_hash = @current_count_hash
class_to_count = Hash.new { |hash, key| hash[key] = 0 }
ObjectSpace.each_object { |obj| class_to_count[obj.class] += 1 }
sorted_class_to_count = class_to_count.sort_by { |k, v| -v }
@current_count_hash = Hash[sorted_class_to_count]
end
def dump_status(logger)
diff = difference_between_runs
most_used_objects = current_count_hash.to_a.sort_by(&:last).reverse[0, 20]
most_used_objects.each do |object_class, count|
delta = diff[object_class]
logger.add(log_level(delta), sprintf("\t%s: %d (%+d)", object_class, count, delta))
end
end
private
def log_level(delta)
delta > 0 ? Logger::WARN : Logger::DEBUG
end
end