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

Optimize push_state_for_requirements by removing N^2 lookup #160

Draft
wants to merge 1 commit into
base: master
Choose a base branch
from
Draft
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
19 changes: 14 additions & 5 deletions lib/molinillo/resolution.rb
Original file line number Diff line number Diff line change
Expand Up @@ -155,6 +155,7 @@ def initialize(specification_provider, resolver_ui, requested, base)
@original_requested = requested
@base = base
@states = []
@states_by_requirement = {}
@iteration_counter = 0
@parents_of = Hash.new { |h, k| h[k] = [] }
end
Expand All @@ -174,8 +175,7 @@ def resolve
debug(depth) { "Creating possibility state for #{requirement} (#{possibilities.count} remaining)" }
state.pop_possibility_state.tap do |s|
if s
states.push(s)
activated.tag(s)
push_state(s)
end
end
end
Expand All @@ -200,6 +200,10 @@ def resolve
attr_accessor :states
private :states

# @return [Hash{Object => ResolutionState}] states keyed by their requirement
attr_accessor :states_by_requirement
private :states

private

# Sets up the resolution process
Expand Down Expand Up @@ -586,7 +590,7 @@ def requirement_for_existing_name(name)
# `requirement`.
def find_state_for(requirement)
return nil unless requirement
states.find { |i| requirement == i.requirement }
states_by_requirement[requirement]
end

# @param [Object] underlying_error
Expand Down Expand Up @@ -755,7 +759,7 @@ def push_state_for_requirements(new_requirements, requires_sort = true, new_acti
new_requirement = nil
loop do
new_requirement = new_requirements.shift
break if new_requirement.nil? || states.none? { |s| s.requirement == new_requirement }
break if new_requirement.nil? || states_by_requirement[new_requirement].nil?
end
new_name = new_requirement ? name_for(new_requirement) : ''.freeze
possibilities = possibilities_for_requirement(new_requirement)
Expand Down Expand Up @@ -831,9 +835,14 @@ def handle_missing_or_push_dependency_state(state)
state.activated.detach_vertex_named(state.name)
push_state_for_requirements(state.requirements.dup, false, state.activated)
else
states.push(state).tap { activated.tag(state) }
push_state(state)
end
end

def push_state(state)
states_by_requirement[state.requirement] = state
Copy link
Member

Choose a reason for hiding this comment

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

I think this needs to be ||=, and also popping needs to remove / update the hash

states.push(state).tap { activated.tag(state) }
end
end
end
end