Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Stacking Boxes

Stacking Boxes

Euruko 2026

Avatar for Satoshi Tagomori

Satoshi Tagomori

September 17, 2026

More Decks by Satoshi Tagomori

Other Decks in Technology

Transcript

  1. 田籠 聡 (Satoshi Tagomori) @tagomoris SAKURA internet (2024.08〜) Cloud Business

    Strategy Division Maintainer/Founder: OSS: Ruby, Fluentd, MessagePack, Norikra, Woothee, … Event: ISUCON Service: Pathtraq
  2. This Talk • What’s Ruby Box • How Ruby Box

    Works • (Why Ruby Box Works) • The Future of Ruby Box
  3. What’s Ruby Box? A New Experimental Feature Introduce in Ruby

    4.0 Accessed by Ruby::Box Enabled by an ENV value RUBY_BOX=1
  4. The Feature Ruby Box provides a type of separation in

    a process • Separating apps/libs into isolated spaces • Load apps/libs in a space • Hide changes from apps/libs in the space to others • Run methods de ned in the space with the de nition • Separation for… • Monkey patches fi fi • Different versions of Ruby on Rails
  5. Before Ruby Box: Global Only All classes/modules are shared in

    the entire Ruby process Ruby Process Application Code App::Func User Library Code DB::Client (v2) Library Code ActiveSupport (v7)
  6. Before Ruby Box: Global Only Monkey patches overwrite things globally

    Ruby Process Application Code App::Func User User Library Code class String def +(other) = “self:#{other}” Library Code DB::Client (v2) Library Code ActiveSupport (v7)
  7. Before Ruby Box: Global Only Monkey patches overwrite things globally

    Ruby Process Application Code App::Func User User Library Code 😵 class String def +(other) = “self:#{other}” Library Code DB::Client (v2) Library Code ActiveSupport (v7) 😵 😵
  8. Using Ruby Box Ruby Box provides separation for funky monkey

    patches! Ruby Process Application Code App::Func User User Library Code 😀 class String def +(other) = “self:#{other}” Ruby Box Library Code DB::Client (v2) Library Code ActiveSupport (v7) 😀 😀
  9. Using Ruby Box Ruby Box can load different sets of

    applications&libraries! Ruby Process App with Older lib versions Application Code App::Func User Ruby Box App with Newer lib versions Application Code App::Func User Ruby Box Library Code DB::Client (v2) Library Code ActiveSupport (v7) Library Code DB::Client (v3) Library Code ActiveSupport (v8)
  10. Box Step by Step: 1 Process Starts with RUBY_BOX=1 Main

    Box String Array Hash Root Box Builtin class (unique in the process)
  11. Box Step by Step: 1 # main.rb "euruko".upcase Process Starts

    with RUBY_BOX=1 Main Box String Array Hash upcase Root Box Builtin class (unique in the process)
  12. Box Step by Step: 1 # main.rb "euruko".upcase De ne

    a class Foo in main class Foo def bar = :bar end Main Box Foo.new.bar Foo bar String Array Hash fi fi Root Box Builtin class (unique in the process) User class (de ned per box)
  13. Box Step by Step: 1 # main.rb str = "euruko"

    str.upcase De ne a class Foo in main class String def to_s = self.capitalize end Main Box String str.to_s to_s Same object Di erent de nitions per box String Array Hash Builtin class (unique in the process) upcase fi fi fi ff Root Box User class (de ned per box)
  14. Box Step by Step: 2 # capitalized.rb module Capitalized def

    self.str(val) myval = “#{val}” puts myval.to_s myval end end class String def to_s = self.capitalize end Making a box Main Box Box b1 # main.rb b1 = Ruby::Box.new String Array Hash fi Root Box Builtin class (unique in the process) User class (de ned per box)
  15. Box Step by Step: 2 # capitalized.rb module Capitalized def

    self.str(val) myval = “#{val}” puts myval.to_s myval end end class String def to_s = self.capitalize end Making a box Main Box Box b1 Capitalized str # main.rb b1 = Ruby::Box.new b1.require “capitalized” String to_s String Array Hash fi Root Box Builtin class (unique in the process) User class (de ned per box)
  16. Box Step by Step: 2 # capitalized.rb module Capitalized def

    self.str(val) myval = “#{val}” puts myval.to_s myval end end class String def to_s = self.capitalize end Making a box Main Box Box b1 Capitalized str # main.rb b1 = Ruby::Box.new b1.require “capitalized” b1::Capitalized.str(“euruko”) # Euruko String to_s “euruko” String Array Hash Builtin class (unique in the process) capitalize fi Root Box User class (de ned per box)
  17. Box Step by Step: 2 # capitalized.rb module Capitalized def

    self.str(val) myval = “#{val}” puts myval.to_s myval end end class String def to_s = self.capitalize end Making a box Main Box Box b1 Capitalized str “euruko” # main.rb b1 = Ruby::Box.new b1.require “capitalized” puts b1::Capitalized.str(“euruko”).to_s # Euruko # euruko String to_s String Array Hash Builtin class (unique in the process) capitalize fi to_s Root Box User class (de ned per box)
  18. Box Step by Step: 3 # my_data.rb MyData = Data.define(:a,

    :b) module App def self.my_data(a:, b:) MyData.new(a:, b:) end end De ne classes in boxes Main Box Box b1 # main.rb b1 = Ruby::Box.new b1.require “my_data” MyData a b App my_data String Array Hash fi fi Root Box Builtin class (unique in the process) User class (de ned per box)
  19. Box Step by Step: 3 De ne classes in boxes

    Main Box Di erent class object Box b1 Box b2 MyData a MyData a b b my_data Array fi fi my_data Hash Root Box ff # main.rb b1 = Ruby::Box.new b1.require “my_data” b2 = Ruby::Box.new b2.require “my_data” App App String # my_data.rb MyData = Data.define(:a, :b) module App def self.my_data(a:, b:) MyData.new(a:, b:) end end Builtin class (unique in the process) User class (de ned per box)
  20. Box Step by Step: 3 # my_data.rb MyData = Data.define(:a,

    :b) module App def self.my_data(a:, b:) MyData.new(a:, b:) end end De ne classes in boxes Main Box d1 d2 Box b1 Box b2 MyData a MyData a b b App App my_data String Array fi my_data Hash Root Box fi # main.rb b1 = Ruby::Box.new b1.require “my_data” b2 = Ruby::Box.new b2.require “my_data” d1 = b1::App.my_data(a: 1, b: 2) d2 = b2::App.my_data(a: 1, b: 2) Builtin class (unique in the process) User class (de ned per box)
  21. Box Step by Step: 3 # my_data.rb MyData = Data.define(:a,

    :b) module App def self.my_data(a:, b:) MyData.new(a:, b:) end end De ne classes in boxes Main Box d1 d1 != d2 because d1.class != d2.class d2 String Box b1 Box b1 MyData a MyData a b b App App my_data Array fi my_data Hash Root Box fi # main.rb b1 = Ruby::Box.new b1.require “my_data” b2 = Ruby::Box.new b2.require “my_data” d1 = b1::App.my_data(a: 1, b: 2) d2 = b2::App.my_data(a: 1, b: 2) p(e: d1 == d2) #=> false Builtin class (unique in the process) User class (de ned per box)
  22. Ruby Box Separation Internals De nitions per Box, Loading in

    Box, Detecting Box • Class de nitions (rb_classext_t) per box • with method tables, super/sub-classes, class/class-instance variables, etc • Library loading in box • like `load(feature, mod)` to de ne loaded classes under mod • using per-box copy of .so/.dll les • Detecting/de ning the current box fi fi fi fi fi • by updating control frame structure / environment
  23. Ruby Box Separation Internals De nitions per Box, Loading in

    Box, Detecting Box • Class de nitions (rb_classext_t) per box • “Namespace, What and Why” https://rubykaigi.org/2024/presentations/tagomoris.html • Library loading in box • “State of Namespace” https://rubykaigi.org/2025/presentations/tagomoris.html • Detecting/de ning the current box fi fi fi • “The Journey of Box Building” https://rubykaigi.org/2026/presentations/tagomoris.html
  24. Testing in boxes Don’t you need a funky monkey patches

    in tests? • Applications tests sometimes need monkey patches • to mock library behaviors, IO objects, … • Most of tests can run without box. Ruby Process Application Code Test Case Test Case Just some of them can’t. • How about running tests in boxes? • Running all tests in boxes is too expensive • Run just some of them in boxes! Test Runner Test Case Monkey Patches Test Case Ruby Box
  25. Works for Tests in Boxes by tagomoris • “Run .box.rb

    su x test cases in Ruby Box - #382” https://github.com/test-unit/test-unit/pull/382 Loads test code of les like *.box.rb in separated boxes! Merged, and will be released in the next test-unit version (Available with Ruby 4.1 or later) fi ffi • RSpec? Rake::TestTask?
  26. Running Boxes App-server supporting Ruby Box (just idea!) Server Ruby

    Process • Running 2 sets of RoR applications App/libs ver 1 • For modular-monolith applications • For updating Rails versions • For in-process blue-green deployments • My next goal? or others? Ruby Box Application Server App/libs ver 2 Ruby Box
  27. Find your box usage! Tests, Multi-Apps, Multi-ver Gems, Funky DSLs…

    Your Idea and Inspiration Changes the World! Thank you.