Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Case when splat #2143

Merged
merged 2 commits into from
Aug 21, 2015
Merged

Case when splat #2143

merged 2 commits into from
Aug 21, 2015

Conversation

rrosenblum
Copy link
Contributor

This is part 1 of memory performance improvements.

There is a slight risk in the auto-correct. If more than one when condition could apply to the same input, and the earlier condition is used as a short circuiting, then auto-correct could change the code to do the wrong thing. I do not think this is a large concern. If somebody thinks otherwise, I will gladly disable auto-correct by default. I also wasn't sure if I should document this risk inside of the description, class, or not at all.

Example

case foo
when 2
  puts 'special'
when *[2, 4, 6]
  puts 'even'
end

# auto-corrected
case foo
when *[2, 4, 6]
  puts 'even'
when 2
  puts 'special'
end

While running memory_profiler on RuboCop. The sample for the data came from running RuboCop against lib/rubocop/cop/performance, lib/rubocop/cop/rails, and lib/rubocop/cop/lint. I could not sample running against the entire project because of the time and resources needed to analyze that much memory.

Total memory consumption dropped by about 2%
The memory allocation for variable_force.rb dropped by 30%.
There was little impact on locatable.rb, and safe_assignment.rb didn't fall into the top 50 most memory consuming files.

@rrosenblum rrosenblum changed the title Case when splat [WIP] - Case when splat Aug 14, 2015
# case foo
# when 3
# baz
# when *[1, 2, 3, 4]
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's strange to use an example where rearranging the whens has changed the semantics. So remove 3 from the array.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good catch. I didn't mean to have overlap in the example.

@jonas054
Copy link
Collaborator

If the splat operator is being applied to an array literal you could also just change

when *[1, 2, 3]

to

when 1, 2, 3

Perhaps that's a better way to auto-correct in that particular case, provided that it gives the same improvement regarding memory allocation.

@rrosenblum
Copy link
Contributor Author

Good idea about auto-correcting splat on array literal to be a list without the array. I will see what this does to memory usage. Assuming that it does not have the same issue that using splat does, I will make that correction.

@rrosenblum
Copy link
Contributor Author

I was able to test case when with replacing splat array with its expanded form. As expected, there was a noticeable drop in memory allocation. There is an increase in the retained memory, but that is negligible compared to the drop in allocated memory. If presented with the opportunity, refactoring out the splat is the best option.

variable_force.rb
master
  allocated - 2822517
  retained  - 120
reorder (not maintaining relative defined order)
  allocated - 1995877
  retained  - 120
no splat
  allocated - 770733
  retained  - 352
locatable.rb - allocated
  master - 3140792
  reorder (not maintaining relative defined order) - 3158712
  no splat - 2503656

@rrosenblum rrosenblum force-pushed the case_when_splat branch 4 times, most recently from 8a4dbe0 to ad9171f Compare August 17, 2015 20:07
@rrosenblum
Copy link
Contributor Author

I have updated the cop to maintain relative condition order and correct splat array literal to remove the splat and square brackets. There is potential for increased performance by rearranging the splat when conditions, but it is impossible to RuboCop to automatically handle those conditions.

@rrosenblum rrosenblum changed the title [WIP] - Case when splat Case when splat Aug 17, 2015
@rrosenblum rrosenblum force-pushed the case_when_splat branch 2 times, most recently from f5a0a9a to a97c154 Compare August 20, 2015 03:43
@rrosenblum
Copy link
Contributor Author

The code has been modified and rebased. Let me know if I need to tweak anything else.

@jonas054
Copy link
Collaborator

👍 LGTM

# the expansion.
#
# This is not a guaranteed performance improvement. If the data being
# processed by the `case` condition is normalized in a manor that favors
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

manor -> manner

@rrosenblum
Copy link
Contributor Author

updated

bbatsov added a commit that referenced this pull request Aug 21, 2015
@bbatsov bbatsov merged commit 693e6b9 into rubocop:master Aug 21, 2015
@rrosenblum rrosenblum deleted the case_when_splat branch August 21, 2015 12:44
urbanautomaton added a commit to urbanautomaton/rubocop that referenced this pull request Aug 7, 2018
This cop was implemented[1] to optimise memory allocations in case
statements with splatted conditions. In profiling over some of the most
case-heavy parts of the rubocop codebase it showed a 2% improvement in
allocations.

However, as the original PR notes, the suggested change:

* is only safe to make if the case conditions are disjoint
* doesn't confer performance benefits in all conditions

This commit therefore removes the cop and marks it as obsolete.

[1] rubocop#2143
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants