Validator Speeds
require 'poro_validator'
require 'dry-validation'
require 'active_model'
require 'benchmark'
poro_validator = Class.new do
include PoroValidator.validator
validates :name, presence: true
validates :age, numeric: { minimum: 18 }
end.new
schema = Class.new(Dry::Validation::Schema) do
key(:name, &:filled?)
key(:age) { |v| v.int? & v.gt?(18) }
end.new
class User
include ActiveModel::Validations
validates :name, presence: true
validates :age, numericality: { greater_than: 18 }
attr_reader :name, :age
def initialize(attrs)
@name, @age = attrs.values_at(:name, :age)
end
end
count = 10_000
users = count.times.map { |i| { user: "User #{i}", age: 17 } }
Benchmark.bmbm do |x|
x.report('PV: 1 thread') do
users.each do |user|
poro_validator.valid?(user)
poro_validator.errors.full_messages
end
end
x.report('DV: 1 thread') do
users.each { |user| schema.(user).messages }
end
x.report('AM: 1 thread') do
users.each { |user| User.new(user).validate }
end
x.report('PV: 2 threads') do
g1, g2 = users.each_slice(count/2).to_a
t1 = Thread.new do
g1.each do |user|
poro_validator.valid?(user)
poro_validator.errors.full_messages
end
end
t2 = Thread.new do
g2.each do |user|
poro_validator.valid?(user)
poro_validator.errors.full_messages
end
end
t1.join
t2.join
end
x.report('DV: 2 threads') do
g1, g2 = users.each_slice(count/2).to_a
t1 = Thread.new { g1.each { |user| schema.(user).messages } }
t2 = Thread.new { g2.each { |user| schema.(user).messages } }
t1.join
t2.join
end
x.report('AM: 2 threads') do
g1, g2 = users.each_slice(count/2).to_a
t1 = Thread.new { g1.each { |user| User.new(user).validate } }
t2 = Thread.new { g2.each { |user| User.new(user).validate } }
t1.join
t2.join
end
end