Class: Omnizip::Chunked::MemoryManager

Inherits:
Object
  • Object
show all
Defined in:
lib/omnizip/chunked/memory_manager.rb

Overview

Manage memory usage and enforce limits during chunked operations

Constant Summary collapse

DEFAULT_MAX_MEMORY =

256MB

256 * 1024 * 1024

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(max: DEFAULT_MAX_MEMORY, temp_dir: nil, strategy: :disk) ⇒ MemoryManager

Initialize memory manager

Parameters:

  • options (Hash)

    Manager options



18
19
20
21
22
23
24
25
# File 'lib/omnizip/chunked/memory_manager.rb', line 18

def initialize(max: DEFAULT_MAX_MEMORY, temp_dir: nil, strategy: :disk)
  @max_memory = max
  @current_usage = 0
  @buffers = {} # buffer => size mapping
  @temp_files = []
  @temp_dir = temp_dir
  @strategy = strategy
end

Instance Attribute Details

#current_usageObject (readonly)

Returns the value of attribute current_usage.



11
12
13
# File 'lib/omnizip/chunked/memory_manager.rb', line 11

def current_usage
  @current_usage
end

#max_memoryObject (readonly)

Returns the value of attribute max_memory.



11
12
13
# File 'lib/omnizip/chunked/memory_manager.rb', line 11

def max_memory
  @max_memory
end

Class Method Details

.with_manager(**options) {|manager| ... } ⇒ Object

Execute block with automatic cleanup

Yields:

  • (manager)

    Block to execute with manager

Returns:

  • (Object)

    Block result



96
97
98
99
100
101
102
103
# File 'lib/omnizip/chunked/memory_manager.rb', line 96

def self.with_manager(**options)
  manager = new(**options)
  begin
    yield manager
  ensure
    manager.cleanup
  end
end

Instance Method Details

#allocate(size) ⇒ String, Tempfile

Allocate memory or spill to disk

Parameters:

  • size (Integer)

    Size to allocate in bytes

Returns:

  • (String, Tempfile)

    Buffer or temp file



30
31
32
33
34
35
36
# File 'lib/omnizip/chunked/memory_manager.rb', line 30

def allocate(size)
  if can_allocate_in_memory?(size)
    allocate_buffer(size)
  else
    handle_overflow(size)
  end
end

#availableInteger

Get available memory

Returns:

  • (Integer)

    Available memory in bytes



54
55
56
# File 'lib/omnizip/chunked/memory_manager.rb', line 54

def available
  [@max_memory - @current_usage, 0].max
end

#cleanupself

Cleanup all resources

Returns:

  • (self)


74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
# File 'lib/omnizip/chunked/memory_manager.rb', line 74

def cleanup
  @buffers.clear
  @temp_files.each do |tf|
    begin
      tf.close
    rescue StandardError
      nil
    end
    begin
      tf.unlink
    rescue StandardError
      nil
    end
  end
  @temp_files.clear
  @current_usage = 0
  self
end

#over_limit?Boolean

Check if over memory limit

Returns:

  • (Boolean)

    True if over limit



60
61
62
# File 'lib/omnizip/chunked/memory_manager.rb', line 60

def over_limit?
  @current_usage > @max_memory
end

#release(buffer) ⇒ Integer

Release allocated memory or temp file

Parameters:

  • buffer (String, Tempfile)

    Buffer to release

Returns:

  • (Integer)

    Bytes released



41
42
43
44
45
46
47
48
49
50
# File 'lib/omnizip/chunked/memory_manager.rb', line 41

def release(buffer)
  case buffer
  when String
    release_buffer(buffer)
  when Tempfile, File
    release_temp_file(buffer)
  else
    0
  end
end

#spill_to_disk(buffer = nil) ⇒ Tempfile

Spill buffer to disk

Parameters:

  • buffer (String) (defaults to: nil)

    Buffer data to spill

Returns:

  • (Tempfile)

    Temporary file



108
109
110
111
112
113
114
# File 'lib/omnizip/chunked/memory_manager.rb', line 108

def spill_to_disk(buffer = nil)
  tf = create_temp_file
  tf.write(buffer) if buffer
  tf.rewind
  @temp_files << tf
  tf
end

#usage_ratioFloat

Get memory usage ratio

Returns:

  • (Float)

    Usage from 0.0 to 1.0



66
67
68
69
70
# File 'lib/omnizip/chunked/memory_manager.rb', line 66

def usage_ratio
  return 0.0 if @max_memory.zero?

  @current_usage.to_f / @max_memory
end