Class: A2A::Utils::Performance

Inherits:
Object
  • Object
show all
Defined in:
lib/a2a/utils/performance.rb

Class Attribute Summary collapse

Class Method Summary collapse

Class Attribute Details

.memory_snapshotsObject (readonly)

Returns the value of attribute memory_snapshots.



17
18
19
# File 'lib/a2a/utils/performance.rb', line 17

def memory_snapshots
  @memory_snapshots
end

.performance_dataObject (readonly)

Returns the value of attribute performance_data.



17
18
19
# File 'lib/a2a/utils/performance.rb', line 17

def performance_data
  @performance_data
end

Class Method Details

.available_optimizationsHash

Check if performance optimizations are available

Returns:

  • (Hash)

    Available optimizations



192
193
194
195
196
197
198
199
# File 'lib/a2a/utils/performance.rb', line 192

def available_optimizations
  {
    oj_json: defined?(Oj),
    gc_compact: defined?(GC) && GC.respond_to?(:compact),
    gc_tune: defined?(GC.tune),
    net_http_persistent: defined?(Net::HTTP::Persistent)
  }
end

.batch_process(items, batch_size = 100) {|Array| ... } ⇒ Array

Batch process items for better performance

Parameters:

  • items (Array)

    Items to process

  • batch_size (Integer) (defaults to: 100)

    Size of each batch

Yields:

  • (Array)

    Block to process each batch

Returns:

  • (Array)

    Results from all batches



156
157
158
159
160
161
162
163
164
165
# File 'lib/a2a/utils/performance.rb', line 156

def batch_process(items, batch_size = 100)
  results = []

  items.each_slice(batch_size) do |batch|
    batch_result = yield(batch)
    results.concat(Array(batch_result))
  end

  results
end

.create_string_buffer(initial_capacity = 8192) ⇒ StringIO

Create an optimized string buffer for large message handling

Parameters:

  • initial_capacity (Integer) (defaults to: 8192)

    Initial buffer capacity

Returns:

  • (StringIO)

    Optimized string buffer



139
140
141
142
143
144
145
146
147
# File 'lib/a2a/utils/performance.rb', line 139

def create_string_buffer(initial_capacity = 8192)
  buffer = StringIO.new
  buffer.set_encoding(Encoding::UTF_8)

  # Pre-allocate capacity if possible
  buffer.capacity = initial_capacity if buffer.respond_to?(:capacity=)

  buffer
end

.format_bytes(bytes) ⇒ String (private)

Format bytes for human-readable output

Parameters:

  • bytes (Integer)

    Number of bytes

Returns:

  • (String)

    Formatted string



235
236
237
238
239
240
241
242
243
# File 'lib/a2a/utils/performance.rb', line 235

def format_bytes(bytes)
  return "0 B" if bytes.zero?

  units = %w[B KB MB GB TB]
  exp = (Math.log(bytes.abs) / Math.log(1024)).floor
  exp = [exp, units.length - 1].min

  "#{(bytes / (1024.0**exp)).round(2)} #{units[exp]}"
end

.memory_snapshot(label = Time.now.to_s) ⇒ Object

Take a memory snapshot

Parameters:

  • label (String) (defaults to: Time.now.to_s)

    Label for the snapshot



66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
# File 'lib/a2a/utils/performance.rb', line 66

def memory_snapshot(label = Time.now.to_s)
  snapshot = {
    label: label,
    timestamp: Time.now,
    memory: memory_usage,
    gc_stats: defined?(GC.stat) ? GC.stat : {}
  }

  @memory_snapshots << snapshot

  # Keep only last 100 snapshots
  @memory_snapshots = @memory_snapshots.last(100) if @memory_snapshots.size > 100

  snapshot
end

.memory_usageInteger

Get current memory usage in bytes

Returns:

  • (Integer)

    Memory usage in bytes



50
51
52
53
54
55
56
57
58
59
60
# File 'lib/a2a/utils/performance.rb', line 50

def memory_usage
  if defined?(GC.stat)
    # Use GC stats for more accurate memory tracking
    GC.stat(:heap_allocated_pages) * GC.stat(:heap_page_size)
  else
    # Fallback to process memory (less accurate)
    `ps -o rss= -p #{Process.pid}`.to_i * 1024
  end
rescue StandardError
  0
end

.optimize_gc!Object

Optimize garbage collection



85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
# File 'lib/a2a/utils/performance.rb', line 85

def optimize_gc!
  return unless defined?(GC)

  # Force garbage collection
  GC.start

  # Compact heap if available (Ruby 2.7+)
  GC.compact if GC.respond_to?(:compact)

  # Tune GC settings for better performance
  return unless defined?(GC.tune)

  GC.tune(
    heap_growth_factor: 1.8,
    heap_growth_max_slots: 0,
    heap_init_slots: 10_000,
    heap_free_slots: 4096,
    heap_oldobject_limit_factor: 2.0
  )
end

.optimized_json_generate(object) ⇒ String

Optimize JSON generation performance

Parameters:

  • object (Object)

    Object to serialize

Returns:

  • (String)

    JSON string



125
126
127
128
129
130
131
132
# File 'lib/a2a/utils/performance.rb', line 125

def optimized_json_generate(object)
  # Use Oj if available for better performance
  if defined?(Oj)
    Oj.dump(object, mode: :compat)
  else
    JSON.generate(object)
  end
end

.optimized_json_parse(json_string) ⇒ Hash, Array

Optimize JSON parsing performance

Parameters:

  • json_string (String)

    JSON string to parse

Returns:

  • (Hash, Array)

    Parsed JSON



111
112
113
114
115
116
117
118
# File 'lib/a2a/utils/performance.rb', line 111

def optimized_json_parse(json_string)
  # Use Oj if available for better performance
  if defined?(Oj)
    Oj.load(json_string, mode: :strict)
  else
    JSON.parse(json_string)
  end
end

.profile(label = "operation") { ... } ⇒ Object

Profile a block of code and return execution time

Parameters:

  • label (String) (defaults to: "operation")

    Label for the profiling session

Yields:

  • Block to profile

Returns:

  • (Object)

    Result of the block



25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
# File 'lib/a2a/utils/performance.rb', line 25

def profile(label = "operation")
  start_time = Process.clock_gettime(Process::CLOCK_MONOTONIC)
  start_memory = memory_usage

  result = yield

  end_time = Process.clock_gettime(Process::CLOCK_MONOTONIC)
  end_memory = memory_usage

  duration = end_time - start_time
  memory_delta = end_memory - start_memory

  record_performance_data(label, duration, memory_delta)

  if A2A.configuration.respond_to?(:performance_logging) && A2A.configuration.performance_logging
    A2A.logger.info("Performance [#{label}]: #{duration.round(4)}s, Memory: #{format_bytes(memory_delta)}")
  end

  result
end

.record_performance_data(label, duration, memory_delta) ⇒ Object (private)

Record performance data

Parameters:

  • label (String)

    Operation label

  • duration (Float)

    Duration in seconds

  • memory_delta (Integer)

    Memory change in bytes



209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
# File 'lib/a2a/utils/performance.rb', line 209

def record_performance_data(label, duration, memory_delta)
  @performance_data[label] ||= {
    count: 0,
    total_time: 0.0,
    avg_time: 0.0,
    min_time: Float::INFINITY,
    max_time: 0.0,
    total_memory: 0,
    avg_memory: 0.0
  }

  data = @performance_data[label]
  data[:count] += 1
  data[:total_time] += duration
  data[:avg_time] = data[:total_time] / data[:count]
  data[:min_time] = [data[:min_time], duration].min
  data[:max_time] = [data[:max_time], duration].max
  data[:total_memory] += memory_delta
  data[:avg_memory] = data[:total_memory].to_f / data[:count]
end

.reset!Object

Reset performance tracking data



183
184
185
186
# File 'lib/a2a/utils/performance.rb', line 183

def reset!
  @memory_snapshots.clear
  @performance_data.clear
end

.statisticsHash

Get performance statistics

Returns:

  • (Hash)

    Performance statistics



171
172
173
174
175
176
177
178
# File 'lib/a2a/utils/performance.rb', line 171

def statistics
  {
    memory_snapshots: @memory_snapshots.size,
    current_memory: memory_usage,
    performance_data: @performance_data,
    gc_stats: defined?(GC.stat) ? GC.stat : {}
  }
end