From 1fb151f9ee31bc261f1738843054955332779f61 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cl=C3=A9ment=20Joubert?= Date: Fri, 6 Nov 2026 09:49:07 +0100 Subject: [PATCH] Allocate shape metadata on first write Every Shape and ShapeRef created an empty metadata Hash, though most never get any metadata. Loading the S3 and KMS APIs left 3,833 of them, about 0.6 MB of Ruby objects. Create the Hash on the first []= instead; [] reads nil as no metadata. Co-Authored-By: Claude Opus 5.5 --- gems/aws-sdk-core/CHANGELOG.md | 2 ++ gems/aws-sdk-core/lib/seahorse/model/shapes.rb | 12 ++++++------ gems/aws-sdk-core/spec/seahorse/model/shapes_spec.rb | 6 ++++++ 3 files changed, 14 insertions(+), 6 deletions(-) diff --git a/gems/aws-sdk-core/CHANGELOG.md b/gems/aws-sdk-core/CHANGELOG.md index 718762649a4..c9783720c9e 100644 --- a/gems/aws-sdk-core/CHANGELOG.md +++ b/gems/aws-sdk-core/CHANGELOG.md @@ -1,6 +1,8 @@ Unreleased Changes ------------------ +* Feature - Reduce memory usage of loaded service APIs by allocating shape metadata Hashes on first write. + 3.264.0 (2026-11-04) ------------------ diff --git a/gems/aws-sdk-core/lib/seahorse/model/shapes.rb b/gems/aws-sdk-core/lib/seahorse/model/shapes.rb index 5475c77bbe3..ef4418832f9 100644 --- a/gems/aws-sdk-core/lib/seahorse/model/shapes.rb +++ b/gems/aws-sdk-core/lib/seahorse/model/shapes.rb @@ -9,7 +9,7 @@ module Shapes class ShapeRef def initialize(options = {}) - @metadata = {} + @metadata = nil @required = false @deprecated = false @location = nil @@ -84,7 +84,7 @@ def location_name= location_name # Gets metadata for the given `key`. def [](key) - if @metadata.key?(key.to_s) + if @metadata&.key?(key.to_s) @metadata[key.to_s] elsif @shape @shape[key.to_s] @@ -93,7 +93,7 @@ def [](key) # Sets metadata for the given `key`. def []=(key, value) - @metadata[key.to_s] = value + (@metadata ||= {})[key.to_s] = value end end @@ -101,7 +101,7 @@ def []=(key, value) class Shape def initialize(options = {}) - @metadata = {} + @metadata = nil options.each_pair do |key, value| if respond_to?("#{key}=") send("#{key}=", value) @@ -122,12 +122,12 @@ def initialize(options = {}) # Gets metadata for the given `key`. def [](key) - @metadata[key.to_s] + @metadata && @metadata[key.to_s] end # Sets metadata for the given `key`. def []=(key, value) - @metadata[key.to_s] = value + (@metadata ||= {})[key.to_s] = value end end diff --git a/gems/aws-sdk-core/spec/seahorse/model/shapes_spec.rb b/gems/aws-sdk-core/spec/seahorse/model/shapes_spec.rb index 40815306285..3e38505471d 100644 --- a/gems/aws-sdk-core/spec/seahorse/model/shapes_spec.rb +++ b/gems/aws-sdk-core/spec/seahorse/model/shapes_spec.rb @@ -52,6 +52,12 @@ module Shapes expect(ref['key']).to eq('value') end + it 'returns nil for metadata that was never set' do + expect(ShapeRef.new[:key]).to be(nil) + expect(ShapeRef.new(shape: Shape.new)[:key]).to be(nil) + expect(Shape.new[:key]).to be(nil) + end + it 'can be populated via .new' do shape = double('shape') ref = ShapeRef.new(