ronin-rb / ronin-support

A support library for Ronin. Like activesupport, but for hacking!
https://ronin-rb.dev
GNU Lesser General Public License v3.0
25 stars 9 forks source link

Optimize `IPRange::Glob#each` to use a single format string to format each IP #494

Open postmodern opened 4 months ago

postmodern commented 4 months ago

Using String#% to format an Array of values with a C-style format string is faster than formatting each individual value and joining them using Array#join. This will require parsing the glob string and building the @ranges Array and dynamically building a format string. Note that while IPv4 addresses can always be formatted using "%d.%d.%d.%d", IPv6 addresses may be truncated (ex: 11:22::0-10:*) and may contain 2 - 8 octets.

Micro-Benchmark

#!/usr/bin/env ruby

require 'benchmark'

Benchmark.bm do |b|
  n = 1_000

  b.report('String#%') do
    n.times do
       fmt = '%d.%d.%d.%d'

       [1].each do |a|
         [2].each do |b|
           [1,2,4,8].each do |c|
             (0..255).each do |d|
               fmt % [a, b, c, d]
             end
           end
         end
       end
    end
  end

  b.report('String#% + Array#join') do
    n.times do
      [1].each do |a|
        [2].each do |b|
          [1,2,4,8].each do |c|
            (0..255).each do |d|
              ['%d' % a, '%d' % b, '%d' % c, '%d' % d].join('.')
            end
          end
        end
      end
    end
  end

  b.report('Integer#to_s + Array#join') do
    n.times do
      [1].each do |a|
        [2].each do |b|
          [1,2,4,8].each do |c|
            (0..255).each do |d|
              [a, b, c, d].join('.')
            end
          end
        end
      end
    end
  end
end
$ ./benchmark.rb
       user     system      total        real
String#%  0.629813   0.004036   0.633849 (  0.638783)
String#% + Array#join  2.409461   0.008812   2.418273 (  2.435780)
Integer#to_s + Array#join  1.650891   0.001975   1.652866 (  1.664543)