mirror of
				https://github.com/ruby/ruby.git
				synced 2022-11-09 12:17:21 -05:00 
			
		
		
		
	[ruby/psych] Make Ractor-ready.
Config is Ractor-local. Benchmarking reveals that using `Ractor.local_storage` for storing cache is similar to accessing a constant (~15% slower).
This commit is contained in:
		
							parent
							
								
									3ee0ad9190
								
							
						
					
					
						commit
						c5a445d577
					
				
				
				Notes:
				
					git
				
				2020-12-23 15:09:02 +09:00 
				
			
			
			
		
		
					 4 changed files with 90 additions and 6 deletions
				
			
		| 
						 | 
				
			
			@ -632,9 +632,29 @@ module Psych
 | 
			
		|||
  private_class_method :warn_with_uplevel, :parse_caller
 | 
			
		||||
 | 
			
		||||
  class << self
 | 
			
		||||
    attr_accessor :load_tags
 | 
			
		||||
    attr_accessor :dump_tags
 | 
			
		||||
    attr_accessor :domain_types
 | 
			
		||||
    if defined?(Ractor)
 | 
			
		||||
      require 'forwardable'
 | 
			
		||||
      extend Forwardable
 | 
			
		||||
 | 
			
		||||
      class Config
 | 
			
		||||
        attr_accessor :load_tags, :dump_tags, :domain_types
 | 
			
		||||
        def initialize
 | 
			
		||||
          @load_tags = {}
 | 
			
		||||
          @dump_tags = {}
 | 
			
		||||
          @domain_types = {}
 | 
			
		||||
        end
 | 
			
		||||
      end
 | 
			
		||||
 | 
			
		||||
      def config
 | 
			
		||||
        Ractor.current[:PsychConfig] ||= Config.new
 | 
			
		||||
      end
 | 
			
		||||
 | 
			
		||||
      def_delegators :config, :load_tags, :dump_tags, :domain_types, :load_tags=, :dump_tags=, :domain_types=
 | 
			
		||||
    else
 | 
			
		||||
      attr_accessor :load_tags
 | 
			
		||||
      attr_accessor :dump_tags
 | 
			
		||||
      attr_accessor :domain_types
 | 
			
		||||
    end
 | 
			
		||||
  end
 | 
			
		||||
  self.load_tags = {}
 | 
			
		||||
  self.dump_tags = {}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -8,12 +8,26 @@ module Psych
 | 
			
		|||
 | 
			
		||||
      private
 | 
			
		||||
 | 
			
		||||
      DISPATCH = Hash.new do |hash, klass|
 | 
			
		||||
        hash[klass] = "visit_#{klass.name.gsub('::', '_')}"
 | 
			
		||||
      # @api private
 | 
			
		||||
      def self.dispatch_cache
 | 
			
		||||
        Hash.new do |hash, klass|
 | 
			
		||||
          hash[klass] = :"visit_#{klass.name.gsub('::', '_')}"
 | 
			
		||||
        end
 | 
			
		||||
      end
 | 
			
		||||
 | 
			
		||||
      if defined?(Ractor)
 | 
			
		||||
        def dispatch
 | 
			
		||||
          Ractor.current[:Psych_Visitors_Visitor] ||= Visitor.dispatch_cache
 | 
			
		||||
        end
 | 
			
		||||
      else
 | 
			
		||||
        DISPATCH = dispatch_cache
 | 
			
		||||
        def dispatch
 | 
			
		||||
          DISPATCH
 | 
			
		||||
        end
 | 
			
		||||
      end
 | 
			
		||||
 | 
			
		||||
      def visit target
 | 
			
		||||
        send DISPATCH[target.class], target
 | 
			
		||||
        send dispatch[target.class], target
 | 
			
		||||
      end
 | 
			
		||||
    end
 | 
			
		||||
  end
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -22,6 +22,9 @@ VALUE mPsych;
 | 
			
		|||
 | 
			
		||||
void Init_psych(void)
 | 
			
		||||
{
 | 
			
		||||
    #ifdef HAVE_RB_EXT_RACTOR_SAFE
 | 
			
		||||
	RB_EXT_RACTOR_SAFE(true);
 | 
			
		||||
    #endif
 | 
			
		||||
    mPsych = rb_define_module("Psych");
 | 
			
		||||
 | 
			
		||||
    rb_define_singleton_method(mPsych, "libyaml_version", libyaml_version, 0);
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										47
									
								
								test/psych/test_ractor.rb
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										47
									
								
								test/psych/test_ractor.rb
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,47 @@
 | 
			
		|||
# frozen_string_literal: true
 | 
			
		||||
require_relative 'helper'
 | 
			
		||||
 | 
			
		||||
class TestPsychRactor < Test::Unit::TestCase
 | 
			
		||||
  def test_ractor_round_trip
 | 
			
		||||
    assert_ractor(<<~RUBY, require_relative: 'helper')
 | 
			
		||||
      obj = {foo: [42]}
 | 
			
		||||
      obj2 = Ractor.new(obj) do |obj|
 | 
			
		||||
        Psych.load(Psych.dump(obj))
 | 
			
		||||
      end.take
 | 
			
		||||
      assert_equal obj, obj2
 | 
			
		||||
    RUBY
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  def test_not_shareable
 | 
			
		||||
    # There's no point in making these frozen / shareable
 | 
			
		||||
    # and the C-ext disregards begin frozen
 | 
			
		||||
    assert_ractor(<<~RUBY, require_relative: 'helper')
 | 
			
		||||
      parser = Psych::Parser.new
 | 
			
		||||
      emitter = Psych::Emitter.new(nil)
 | 
			
		||||
      assert_raise(Ractor::Error) { Ractor.make_shareable(parser) }
 | 
			
		||||
      assert_raise(Ractor::Error) { Ractor.make_shareable(emitter) }
 | 
			
		||||
    RUBY
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  def test_ractor_config
 | 
			
		||||
    assert_ractor(<<~RUBY, require_relative: 'helper')
 | 
			
		||||
      r = Ractor.new do
 | 
			
		||||
        Psych.add_builtin_type 'omap' do |type, val|
 | 
			
		||||
          val * 2
 | 
			
		||||
        end
 | 
			
		||||
        Psych.load('--- !!omap hello')
 | 
			
		||||
      end.take
 | 
			
		||||
      assert_equal 'hellohello', r
 | 
			
		||||
      assert_equal 'hello', Psych.load('--- !!omap hello')
 | 
			
		||||
    RUBY
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  def test_ractor_constants
 | 
			
		||||
    assert_ractor(<<~RUBY, require_relative: 'helper')
 | 
			
		||||
      r = Ractor.new do
 | 
			
		||||
        Psych.libyaml_version.join('.') == Psych::LIBYAML_VERSION
 | 
			
		||||
      end.take
 | 
			
		||||
      assert_equal true, r
 | 
			
		||||
    RUBY
 | 
			
		||||
  end
 | 
			
		||||
end
 | 
			
		||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue