Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Commits on Mar 15, 2015
  1. @hsbt

    Merge pull request #1190 from friederbluemle/patch-1

    hsbt authored
    Fix release date of 2.4.6
  2. @friederbluemle
Commits on Mar 13, 2015
  1. @tenderlove

    remove puts

    tenderlove authored
  2. @mfazekas @tenderlove

    Add test for find_in_unresolved_tree

    mfazekas authored tenderlove committed
  3. @tenderlove

    Merge pull request #1188 from tenderlove/omg

    tenderlove authored
    drop millions of allocations by using a linked list
  4. @tenderlove

    drop millions of allocations by using a linked list

    tenderlove authored
    Use a linked list to drop array allocations.  The previous
    implementation would dup arrays on every call to `traverse`.  This patch
    uses a linked list so that any block that is interested in keeping a
    reference to `trail` can just keep the trail node around (the trail node
    points at it's parents).
    
    This approach reduces allocations from 11173668, to 2940.
    
    Here is the test I used:
    
    ```ruby
    require 'stackprof'
    require 'allocation_tracer'
    require 'rubygems/test_case'
    require 'rubygems/ext'
    require 'rubygems/specification'
    require 'benchmark'
    
    class TestGemSpecification < Gem::TestCase
      def test_runtime
        make_gems do
          StackProf.run(mode: :wall, out: '/tmp/out.dump') do
            assert_raises(LoadError) { require 'no_such_file_foo' }
          end
        end
      end
    
      def test_alone
        make_gems do
          tms = Benchmark.measure {
            assert_raises(LoadError) { require 'no_such_file_foo' }
          }
          p tms.total
          assert_operator tms.total, :<=, 10
        end
      end
    
      def test_memory
        make_gems do
          ObjectSpace::AllocationTracer.setup(%i{path line type})
          r = ObjectSpace::AllocationTracer.trace do
            assert_raises(LoadError) { require 'no_such_file_foo' }
          end
    
          r.sort_by { |k,v| v.first }.each do |k,v|
            p k => v
          end
          p hash_alloc: ObjectSpace::AllocationTracer.allocated_count_table[:T_HASH]
          p array_alloc: ObjectSpace::AllocationTracer.allocated_count_table[:T_ARRAY]
          p :TOTAL => ObjectSpace::AllocationTracer.allocated_count_table.values.inject(:+)
        end
      end
    
      def make_gems
        save_loaded_features do
          num_of_pkg = 7
          num_of_version_per_pkg = 3
          packages = (0..num_of_pkg).map do |pkgi|
            (0..num_of_version_per_pkg).map do |pkg_version|
              deps = Hash[(pkgi..num_of_pkg).map { |deppkgi| ["pkg#{deppkgi}", ">= 0"] }]
              new_spec "pkg#{pkgi}", pkg_version.to_s, deps
            end
          end
          base = new_spec "pkg_base", "1", {"pkg0" => ">= 0"}
    
          Gem::Specification.reset
          install_specs base,*packages.flatten
          base.activate
    
          yield
        end
      end
    end
    ```
    
    Before:
    
    {:TOTAL=>11173668}
    
    After:
    
    {:TOTAL=>2940}
  5. @hsbt
  6. @tenderlove

    add nodes to the head of the list so we only have to reverse once

    tenderlove authored
    `trail` is deepest on the left so that we only have to reverse one list
  7. @tenderlove

    make sure there are regression tests surrounding runtime?

    tenderlove authored
    besides the actual use of the method, we should probably have unit tests
    for it
  8. @tenderlove

    drop array allocations and add a runtime? predicate

    tenderlove authored
    `runtime_dependencies` allocates an array every time it's called (this
    may be a good place for caching).  This commit adds a predicate method
    to Dependency so that we can check whether or not the dependency is a
    runtime dependency without knowing the magic symbol `:runtime`.  Then
    switch some hotspots to use `dependencies` and skip unless it's a
    runtime dependency.
    
    We may consider splitting runtime dependencies earlier on (maybe at
    gemspec load time?) so that we can implement an allocation-free version
    of `runtime_dependencies`.
    
    Here's the benchmark:
    
    ```ruby
    require 'stackprof'
    require 'allocation_tracer'
    require 'rubygems/test_case'
    require 'rubygems/ext'
    require 'rubygems/specification'
    require 'benchmark'
    
    class TestGemSpecification < Gem::TestCase
      def test_runtime
        make_gems do
          StackProf.run(mode: :wall, out: '/tmp/out.dump') do
            assert_raises(LoadError) { require 'no_such_file_foo' }
          end
        end
      end
    
      def test_alone
        make_gems do
          tms = Benchmark.measure {
            assert_raises(LoadError) { require 'no_such_file_foo' }
          }
          p tms.total
          assert_operator tms.total, :<=, 10
        end
      end
    
      def test_memory
        make_gems do
          ObjectSpace::AllocationTracer.setup(%i{path line type})
          r = ObjectSpace::AllocationTracer.trace do
            assert_raises(LoadError) { require 'no_such_file_foo' }
          end
    
          r.sort_by { |k,v| v.first }.each do |k,v|
            p k => v
          end
          p hash_alloc: ObjectSpace::AllocationTracer.allocated_count_table[:T_HASH]
          p array_alloc: ObjectSpace::AllocationTracer.allocated_count_table[:T_ARRAY]
          p :TOTAL => ObjectSpace::AllocationTracer.allocated_count_table.values.inject(:+)
        end
      end
    
      def make_gems
        save_loaded_features do
          num_of_pkg = 7
          num_of_version_per_pkg = 3
          packages = (0..num_of_pkg).map do |pkgi|
            (0..num_of_version_per_pkg).map do |pkg_version|
              deps = Hash[(pkgi..num_of_pkg).map { |deppkgi| ["pkg#{deppkgi}", ">= 0"] }]
              new_spec "pkg#{pkgi}", pkg_version.to_s, deps
            end
          end
          base = new_spec "pkg_base", "1", {"pkg0" => ">= 0"}
    
          Gem::Specification.reset
          install_specs base,*packages.flatten
          base.activate
    
          yield
        end
      end
    end
    ```
    
    Before:
    
    {:array_alloc=>8750333}
    {:TOTAL=>13048664}
    
    After:
    
    {:array_alloc=>6875337}
    {:TOTAL=>11173668}
Commits on Mar 12, 2015
  1. @tenderlove

    calculate version object hash based on the @version string

    tenderlove authored
    `eql?` and `<=>` compare @version strings, so we can do the same in
    `hash`.  Yes, this will cause Version objects to have collisions with
    strings that contain the same data as `@version`, but we shouldn't mix
    types for hash keys, so I don't think this will be a problem in
    practice.
  2. @tenderlove

    fewer allocations on `eql?`

    tenderlove authored
    use _version that doesn't dup strings
  3. @hsbt

    Merge pull request #1187 from segiddins/patch-2

    hsbt authored
    [Travis] Test against latest rubies
  4. @tenderlove

    drop hash allocations and optimize for success cases

    tenderlove authored
    We rarely care what the conflicts on a spec are, just whether or not
    there are conflicts.  This commit introduces an allocation-free method
    that returns whether or not there are conflicts.  The only case we
    actually need to know the conflicts are in the case that an exception is
    raised, and in that case we can do the work twice since the program will
    exit anyway.  This drops hash allocations.
    
    Benchmark:
    
    ```ruby
    require 'stackprof'
    require 'allocation_tracer'
    require 'rubygems/test_case'
    require 'rubygems/ext'
    require 'rubygems/specification'
    
    class TestGemSpecification < Gem::TestCase
      def test_find_in_unresolved_tree_is_not_exponentiental
        save_loaded_features do
          num_of_pkg = 7
          num_of_version_per_pkg = 3
          packages = (0..num_of_pkg).map do |pkgi|
            (0..num_of_version_per_pkg).map do |pkg_version|
              deps = Hash[(pkgi..num_of_pkg).map { |deppkgi| ["pkg#{deppkgi}", ">= 0"] }]
              new_spec "pkg#{pkgi}", pkg_version.to_s, deps
            end
          end
          base = new_spec "pkg_base", "1", {"pkg0" => ">= 0"}
    
          Gem::Specification.reset
          install_specs base,*packages.flatten
          base.activate
    
          require 'benchmark'
          ObjectSpace::AllocationTracer.setup(%i{path line type})
          r = ObjectSpace::AllocationTracer.trace do
            assert_raises(LoadError) { require 'no_such_file_foo' }
          end
          r.sort_by { |k,v| v.first }.each do |k,v|
            p k => v
          end
          p hash_alloc: ObjectSpace::AllocationTracer.allocated_count_table[:T_HASH]
          p :TOTAL => ObjectSpace::AllocationTracer.allocated_count_table.values.inject(:+)
        end
      end
    end
    ```
    
    Before: 1562496 Hash allocations
    After: 0 Hash allocations
  5. @tenderlove

    drop array allocations

    tenderlove authored
    Benchmark:
    
    ```ruby
    require 'stackprof'
    require 'allocation_tracer'
    require 'rubygems/test_case'
    require 'rubygems/ext'
    require 'rubygems/specification'
    
    class TestGemSpecification < Gem::TestCase
      def test_find_in_unresolved_tree_is_not_exponentiental
        save_loaded_features do
          num_of_pkg = 7
          num_of_version_per_pkg = 3
          packages = (0..num_of_pkg).map do |pkgi|
            (0..num_of_version_per_pkg).map do |pkg_version|
              deps = Hash[(pkgi..num_of_pkg).map { |deppkgi| ["pkg#{deppkgi}", ">= 0"] }]
              new_spec "pkg#{pkgi}", pkg_version.to_s, deps
            end
          end
          base = new_spec "pkg_base", "1", {"pkg0" => ">= 0"}
    
          Gem::Specification.reset
          install_specs base,*packages.flatten
          base.activate
    
          require 'benchmark'
          ObjectSpace::AllocationTracer.setup(%i{path line type})
          r = ObjectSpace::AllocationTracer.trace do
            assert_raises(LoadError) { require 'no_such_file_foo' }
          end
          r.sort_by { |k,v| v.first }.each do |k,v|
            p k => v
          end
          p ObjectSpace::AllocationTracer.allocated_count_table[:T_ARRAY]
          p :TOTAL => ObjectSpace::AllocationTracer.allocated_count_table.values.inject(:+)
        end
      end
    end
    ```
    
    Before: 10312603 Array allocations
    After: 8750107 Array allocations
Commits on Mar 11, 2015
  1. @tenderlove

    cut string allocations on version comparison.

    tenderlove authored
    Here is the benchmark:
    
    ```ruby
    require 'stackprof'
    require 'allocation_tracer'
    require 'rubygems/test_case'
    require 'rubygems/ext'
    require 'rubygems/specification'
    
    class TestGemSpecification < Gem::TestCase
      def test_find_in_unresolved_tree_is_not_exponentiental
        save_loaded_features do
          num_of_pkg = 7
          num_of_version_per_pkg = 3
          packages = (0..num_of_pkg).map do |pkgi|
            (0..num_of_version_per_pkg).map do |pkg_version|
              deps = Hash[(pkgi..num_of_pkg).map { |deppkgi| ["pkg#{deppkgi}", ">= 0"] }]
              new_spec "pkg#{pkgi}", pkg_version.to_s, deps
            end
          end
          base = new_spec "pkg_base", "1", {"pkg0" => ">= 0"}
    
          Gem::Specification.reset
          install_specs base,*packages.flatten
          base.activate
    
          require 'benchmark'
          ObjectSpace::AllocationTracer.setup(%i{path line type})
          r = ObjectSpace::AllocationTracer.trace do
            assert_raises(LoadError) { require 'no_such_file_foo' }
          end
          r.sort_by { |k,v| v.first }.each do |k,v|
            p k => v
          end
          p ObjectSpace::AllocationTracer.allocated_count_table[:T_STRING]
          p :TOTAL => ObjectSpace::AllocationTracer.allocated_count_table.values.inject(:+)
        end
      end
    end
    ```
    
    Before: 3125611 string allocations
    After: 603 string allocations
  2. @indirect

    Merge pull request #1186 from segiddins/patch-1

    indirect authored
    [BinScript] Allow running pre-release versions
  3. @segiddins
  4. @segiddins
  5. @tenderlove

    Merge pull request #1181 from nobu/remove_tmpdirs

    tenderlove authored
    Remove temporary directories
  6. @hsbt
  7. @hsbt

    Merge pull request #1185 from kant/patch-1

    hsbt authored
    Update links (minor fix)
  8. @kant

    Update links (minor fix)

    kant authored
Commits on Mar 5, 2015
  1. @nobu

    Remove temporary directories

    nobu authored
    Remove temporary directories for GEM_HOME and GEM_PATH at exit.
    Entries under these directories are removed usually, but top
    directories are left.
Commits on Feb 19, 2015
  1. @zzak

    Move test to test_levenshtein_distance_remove as @yuki24 suggested.

    zzak authored
    ありがとうゆうきくん!
  2. @zzak

    Add History for #1173

    zzak authored
  3. @zzak

    Merge pull request #1173 from schneems/schneemsn/fix-fuzzy

    zzak authored
    Fix edge case in `levenshtein_distance` for comparing longer strings
  4. @zzak

    Add History for #1131

    zzak authored
  5. @zzak

    Add History for #1145

    zzak authored
Commits on Feb 18, 2015
  1. @schneems

    Fix fuzzy search for long strings

    schneems authored
    When strings being compared are drastically different in length, the shortcut in the existing levenshtein_distance method is incorrect. 
    
    Currently it will report `levenshtein_distance("cat", "thundercatsarego")` as 3 since it will return n which is the number of characters in "cat". This is incorrect. It should return 13 (16 characters minus 3). 
    
    To fix we remove the shortcut.
Commits on Feb 17, 2015
  1. @tenderlove

    Merge pull request #1145 from arthurnn/move_methods_to_spec

    tenderlove authored
    Move abbreviate and sanitize to Gem::Specification
  2. @tenderlove

    Merge pull request #1131 from mvz/speed-up-fuzzy-requirement-comparison

    tenderlove authored
    Speed up fuzzy requirement comparison
  3. @zzak

    Add test for #1018 and use double equals to compare gem_name.

    zzak authored
    Since we're going to iterate specs eventually, we can skip at that time.
    In order to remove an extra loop and allocations.
  4. @zzak

    Add History for #1018

    zzak authored
  5. @zzak

    Merge pull request #1018 from windwiny/patch-1

    zzak authored
    Add --skip=gem_name to pristine command
Something went wrong with that request. Please try again.