Implement custom delegators for drop methods (#8183)
Merge pull request 8183
This commit is contained in:
parent
c5d4bbd434
commit
53f175516b
|
@ -0,0 +1,83 @@
|
||||||
|
#!/usr/bin/env ruby
|
||||||
|
# frozen_string_literal: true
|
||||||
|
|
||||||
|
require "forwardable"
|
||||||
|
require "colorator"
|
||||||
|
require "liquid"
|
||||||
|
require "benchmark/ips"
|
||||||
|
require "memory_profiler"
|
||||||
|
|
||||||
|
# Set up (memory) profiler
|
||||||
|
|
||||||
|
class Profiler
|
||||||
|
def self.run
|
||||||
|
yield new(ARGV[0] || 10_000)
|
||||||
|
end
|
||||||
|
|
||||||
|
def initialize(count)
|
||||||
|
@count = count.to_i
|
||||||
|
end
|
||||||
|
|
||||||
|
def report(label, color, &block)
|
||||||
|
prof_report = MemoryProfiler.report { @count.to_i.times(&block) }
|
||||||
|
|
||||||
|
allocated_memory = prof_report.scale_bytes(prof_report.total_allocated_memsize)
|
||||||
|
allocated_objects = prof_report.total_allocated
|
||||||
|
retained_memory = prof_report.scale_bytes(prof_report.total_retained_memsize)
|
||||||
|
retained_objects = prof_report.total_retained
|
||||||
|
|
||||||
|
puts <<~MSG.send(color)
|
||||||
|
With #{label} calls
|
||||||
|
|
||||||
|
Total allocated: #{allocated_memory} (#{allocated_objects} objects)
|
||||||
|
Total retained: #{retained_memory} (#{retained_objects} objects)
|
||||||
|
MSG
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
# Set up stage
|
||||||
|
|
||||||
|
class Drop < Liquid::Drop
|
||||||
|
def initialize(obj)
|
||||||
|
@obj = obj
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
class ForwardDrop < Drop
|
||||||
|
extend Forwardable
|
||||||
|
def_delegators :@obj, :name
|
||||||
|
end
|
||||||
|
|
||||||
|
class StaticDrop < Drop
|
||||||
|
def name
|
||||||
|
@obj.name
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
class Document
|
||||||
|
def name
|
||||||
|
"lipsum"
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
# Set up actors
|
||||||
|
|
||||||
|
document = Document.new
|
||||||
|
alpha = ForwardDrop.new(document)
|
||||||
|
beta = StaticDrop.new(document)
|
||||||
|
count = ARGV[0] || 10_000
|
||||||
|
|
||||||
|
# Run profilers
|
||||||
|
puts "\nMemory profiles for #{count} calls to invoke drop key:"
|
||||||
|
Profiler.run do |x|
|
||||||
|
x.report("forwarded", :cyan) { alpha["name"] }
|
||||||
|
x.report("static", :green) { beta["name"] }
|
||||||
|
end
|
||||||
|
|
||||||
|
# Benchmark
|
||||||
|
puts "\nBenchmarking the two scenarios..."
|
||||||
|
Benchmark.ips do |x|
|
||||||
|
x.report("forwarded".cyan) { alpha["name"] }
|
||||||
|
x.report("static".green) { beta["name"] }
|
||||||
|
x.compare!
|
||||||
|
end
|
|
@ -7,10 +7,10 @@ module Jekyll
|
||||||
|
|
||||||
mutable false
|
mutable false
|
||||||
|
|
||||||
def_delegator :@obj, :write?, :output
|
delegate_method_as :write?, :output
|
||||||
def_delegators :@obj, :label, :docs, :files, :directory, :relative_directory
|
delegate_methods :label, :docs, :files, :directory, :relative_directory
|
||||||
|
|
||||||
private def_delegator :@obj, :metadata, :fallback_data
|
private delegate_method_as :metadata, :fallback_data
|
||||||
|
|
||||||
def to_s
|
def to_s
|
||||||
docs.to_s
|
docs.to_s
|
||||||
|
|
|
@ -11,10 +11,11 @@ module Jekyll
|
||||||
|
|
||||||
mutable false
|
mutable false
|
||||||
|
|
||||||
def_delegator :@obj, :relative_path, :path
|
delegate_method_as :relative_path, :path
|
||||||
def_delegators :@obj, :id, :output, :content, :to_s, :relative_path, :url, :date
|
private delegate_method_as :data, :fallback_data
|
||||||
|
|
||||||
private def_delegator :@obj, :data, :fallback_data
|
delegate_methods :id, :output, :content, :to_s, :relative_path, :url, :date
|
||||||
|
data_delegators "title", "categories", "tags"
|
||||||
|
|
||||||
def collection
|
def collection
|
||||||
@obj.collection.label
|
@obj.collection.label
|
||||||
|
@ -64,18 +65,6 @@ module Jekyll
|
||||||
result[key] = doc[key] unless NESTED_OBJECT_FIELD_BLACKLIST.include?(key)
|
result[key] = doc[key] unless NESTED_OBJECT_FIELD_BLACKLIST.include?(key)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
def title
|
|
||||||
@obj.data["title"]
|
|
||||||
end
|
|
||||||
|
|
||||||
def categories
|
|
||||||
@obj.data["categories"]
|
|
||||||
end
|
|
||||||
|
|
||||||
def tags
|
|
||||||
@obj.data["tags"]
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -7,6 +7,7 @@ module Jekyll
|
||||||
|
|
||||||
NON_CONTENT_METHODS = [:fallback_data, :collapse_document].freeze
|
NON_CONTENT_METHODS = [:fallback_data, :collapse_document].freeze
|
||||||
|
|
||||||
|
class << self
|
||||||
# Get or set whether the drop class is mutable.
|
# Get or set whether the drop class is mutable.
|
||||||
# Mutability determines whether or not pre-defined fields may be
|
# Mutability determines whether or not pre-defined fields may be
|
||||||
# overwritten.
|
# overwritten.
|
||||||
|
@ -14,14 +15,67 @@ module Jekyll
|
||||||
# is_mutable - Boolean set mutability of the class (default: nil)
|
# is_mutable - Boolean set mutability of the class (default: nil)
|
||||||
#
|
#
|
||||||
# Returns the mutability of the class
|
# Returns the mutability of the class
|
||||||
def self.mutable(is_mutable = nil)
|
def mutable(is_mutable = nil)
|
||||||
@is_mutable = is_mutable || false
|
@is_mutable = is_mutable || false
|
||||||
end
|
end
|
||||||
|
|
||||||
def self.mutable?
|
def mutable?
|
||||||
@is_mutable
|
@is_mutable
|
||||||
end
|
end
|
||||||
|
|
||||||
|
# public delegation helper methods that calls onto Drop's instance
|
||||||
|
# variable `@obj`.
|
||||||
|
|
||||||
|
# Generate private Drop instance_methods for each symbol in the given list.
|
||||||
|
#
|
||||||
|
# Returns nothing.
|
||||||
|
def private_delegate_methods(*symbols)
|
||||||
|
symbols.each { |symbol| private delegate_method(symbol) }
|
||||||
|
nil
|
||||||
|
end
|
||||||
|
|
||||||
|
# Generate public Drop instance_methods for each symbol in the given list.
|
||||||
|
#
|
||||||
|
# Returns nothing.
|
||||||
|
def delegate_methods(*symbols)
|
||||||
|
symbols.each { |symbol| delegate_method(symbol) }
|
||||||
|
nil
|
||||||
|
end
|
||||||
|
|
||||||
|
# Generate public Drop instance_method for given symbol that calls `@obj.<sym>`.
|
||||||
|
#
|
||||||
|
# Returns delegated method symbol.
|
||||||
|
def delegate_method(symbol)
|
||||||
|
define_method(symbol) { @obj.send(symbol) }
|
||||||
|
end
|
||||||
|
|
||||||
|
# Generate public Drop instance_method named `delegate` that calls `@obj.<original>`.
|
||||||
|
#
|
||||||
|
# Returns delegated method symbol.
|
||||||
|
def delegate_method_as(original, delegate)
|
||||||
|
define_method(delegate) { @obj.send(original) }
|
||||||
|
end
|
||||||
|
|
||||||
|
# Generate public Drop instance_methods for each string entry in the given list.
|
||||||
|
# The generated method(s) access(es) `@obj`'s data hash.
|
||||||
|
#
|
||||||
|
# Returns nothing.
|
||||||
|
def data_delegators(*strings)
|
||||||
|
strings.each do |key|
|
||||||
|
data_delegator(key) if key.is_a?(String)
|
||||||
|
end
|
||||||
|
nil
|
||||||
|
end
|
||||||
|
|
||||||
|
# Generate public Drop instance_methods for given string `key`.
|
||||||
|
# The generated method access(es) `@obj`'s data hash.
|
||||||
|
#
|
||||||
|
# Returns method symbol.
|
||||||
|
def data_delegator(key)
|
||||||
|
define_method(key.to_sym) { @obj.data[key] }
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
# Create a new Drop
|
# Create a new Drop
|
||||||
#
|
#
|
||||||
# obj - the Jekyll Site, Collection, or Document required by the
|
# obj - the Jekyll Site, Collection, or Document required by the
|
||||||
|
|
|
@ -7,10 +7,10 @@ module Jekyll
|
||||||
|
|
||||||
mutable false
|
mutable false
|
||||||
|
|
||||||
def_delegator :@obj, :site_data, :data
|
delegate_method_as :site_data, :data
|
||||||
def_delegators :@obj, :time, :pages, :static_files, :tags, :categories
|
delegate_methods :time, :pages, :static_files, :tags, :categories
|
||||||
|
|
||||||
private def_delegator :@obj, :config, :fallback_data
|
private delegate_method_as :config, :fallback_data
|
||||||
|
|
||||||
def [](key)
|
def [](key)
|
||||||
if key != "posts" && @obj.collections.key?(key)
|
if key != "posts" && @obj.collections.key?(key)
|
||||||
|
|
|
@ -4,11 +4,11 @@ module Jekyll
|
||||||
module Drops
|
module Drops
|
||||||
class StaticFileDrop < Drop
|
class StaticFileDrop < Drop
|
||||||
extend Forwardable
|
extend Forwardable
|
||||||
def_delegators :@obj, :name, :extname, :modified_time, :basename
|
delegate_methods :name, :extname, :modified_time, :basename
|
||||||
def_delegator :@obj, :relative_path, :path
|
delegate_method_as :relative_path, :path
|
||||||
def_delegator :@obj, :type, :collection
|
delegate_method_as :type, :collection
|
||||||
|
|
||||||
private def_delegator :@obj, :data, :fallback_data
|
private delegate_method_as :data, :fallback_data
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -7,8 +7,8 @@ module Jekyll
|
||||||
|
|
||||||
mutable false
|
mutable false
|
||||||
|
|
||||||
def_delegator :@obj, :cleaned_relative_path, :path
|
delegate_method :output_ext
|
||||||
def_delegator :@obj, :output_ext, :output_ext
|
delegate_method_as :cleaned_relative_path, :path
|
||||||
|
|
||||||
def collection
|
def collection
|
||||||
@obj.collection.label
|
@obj.collection.label
|
||||||
|
|
Loading…
Reference in New Issue