Skip to content

Commit

Permalink
perf: Speeds up the performance by 2x
Browse files Browse the repository at this point in the history
  • Loading branch information
svyatov committed Mar 4, 2024
1 parent 2e6483f commit 32236ed
Show file tree
Hide file tree
Showing 3 changed files with 26 additions and 21 deletions.
24 changes: 12 additions & 12 deletions benchmark/run.rb
Original file line number Diff line number Diff line change
Expand Up @@ -19,29 +19,29 @@
# puts clsx(*massive_args)

def clsx_optimized(*args)
clsx_args_processor_optimized(*args).join(' ').presence
result = clsx_args_processor_optimized(*args)
result.uniq!
result.join(' ').presence
end

def clsx_args_processor_optimized(*args)
result = Set.new
result = []
complex_keys = []

args.flatten!
args.each do |arg|
next if arg.blank? || arg.is_a?(TrueClass) || arg.is_a?(Proc)
next result << arg.to_s unless arg.is_a?(Hash)

case arg
when Array
result += clsx_args_processor_optimized(*arg)
when Hash
arg.each { |k, v| result += clsx_args_processor_optimized(k) if v }
else
result << arg.to_s
end
arg.each { |key, value| complex_keys << key if value }
end

result
return result if complex_keys.empty?

result + clsx_args_processor_optimized(*complex_keys)
end

unless clsx(*massive_args) == clsx_optimized(*massive_args)
unless clsx(*massive_args).split.sort == clsx_optimized(*massive_args).split.sort
puts 'The optimized version produces a different result!'
puts "Original: #{clsx(*massive_args)}"
puts "Optimized: #{clsx_optimized(*massive_args)}"
Expand Down
19 changes: 12 additions & 7 deletions lib/clsx/helper.rb
Original file line number Diff line number Diff line change
Expand Up @@ -26,27 +26,32 @@ module Helper
# <div class="<%= clsx('foo', active: @is_active, 'another-class' => @condition) %>">
# <%= tag.div class: clsx(%w[foo bar], hidden: @condition) do ... end %>
def clsx(*args)
clsx_args_processor(*args).join(' ').presence
result = clsx_args_processor(*args)
result.uniq!
result.join(' ').presence
end
alias cn clsx

private

# @param [Mixed] args
#
# @return [Set]
def clsx_args_processor(*args) # rubocop:disable Metrics/CyclomaticComplexity
result = Set.new
args.flatten!
# @return [Array]
def clsx_args_processor(*args) # rubocop:disable Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity
result = []
complex_keys = []

args.flatten!
args.each do |arg|
next if arg.blank? || arg.is_a?(TrueClass) || arg.is_a?(Proc)
next result << arg.to_s unless arg.is_a?(Hash)

arg.each { |k, v| result += clsx_args_processor(k) if v }
arg.each { |key, value| complex_keys << key if value }
end

result
return result if complex_keys.empty?

result + clsx_args_processor(*complex_keys)
end
end
end
4 changes: 2 additions & 2 deletions test/clsx/helper_test.rb
Original file line number Diff line number Diff line change
Expand Up @@ -92,7 +92,7 @@ def test_with_procs_and_lambdas

def test_with_mixed_types
assert_nil clsx(nil, false, '', {}, [])
assert_equal 'foo bar', clsx(nil, false, '', { foo: true }, ['bar'])
assert_equal 'bar foo', clsx(nil, false, '', { foo: true }, ['bar'])
end

# Source: https://github.com/lukeed/clsx/blob/master/test/classnames.js
Expand All @@ -104,7 +104,7 @@ def test_compatiblity_with_classnames
assert_equal 'a 0 1 b', clsx('a', 0, nil, true, 1, 'b')

# (compat) supports heterogeneous arguments
assert_equal 'a b', clsx({ a: true }, 'b', false)
assert_equal 'b a', clsx({ a: true }, 'b', false)

# (compat) should be trimmed
assert_equal 'b', clsx('', 'b', {}, '')
Expand Down

0 comments on commit 32236ed

Please sign in to comment.