Skip to content

Instantly share code, notes, and snippets.

@joeyAghion
Created October 13, 2010 16:00

Revisions

  1. joeyAghion renamed this gist Oct 14, 2010. 1 changed file with 0 additions and 0 deletions.
    File renamed without changes.
  2. joeyAghion revised this gist Oct 14, 2010. 1 changed file with 6 additions and 6 deletions.
    12 changes: 6 additions & 6 deletions simple_redis_profile
    Original file line number Diff line number Diff line change
    @@ -28,22 +28,22 @@ def redis_size(db, k)
    end

    def array_sum(array)
    array.inject(0){|sum,e| sum += e }
    array.inject(0){ |sum, e| sum + e }
    end

    def redis_db_profile(db_name, sample_size = SAMPLE_SIZE)
    db = Redis.new(:db => db_name)
    keys = []
    sample_size.times { |i| keys << db.randomkey }
    key_types = keys.group_by{|k| k.gsub(/\d+/, '#')}
    data = key_types.keys.collect{ |k|
    [k, {'keys' => key_types[k].size, 'size' => array_sum(key_types[k].collect{|k| redis_size(db, k)})}]
    }.sort_by{|a| a.last['size'] }.reverse
    key_patterns = keys.group_by{ |key| key.gsub(/\d+/, '#') }
    data = key_patterns.map{ |pattern, keys|
    [pattern, {'keys' => keys.size, 'size' => array_sum(keys.map{ |k| redis_size(db, k) })}]
    }.sort_by{ |a| a.last['size'] }.reverse
    size_sum = data.inject(0){|sum, d| sum += d.last['size'] }
    data.each { |d| d.last['percent'] = '%.2f%' % (d.last['size'].to_f*100/size_sum) }
    end

    db_names = `redis-cli info | grep ^db[0-9]`.split.map{|line| line.scan(/^db\d*/).first }
    db_names = `redis-cli info | grep ^db[0-9]`.split.map{ |line| line.scan(/^db\d+/).first }
    db_names.each do |name|
    puts "\nProfiling \"#{name}\"...\n#{'-'*20}"
    y redis_db_profile(name)
  3. joeyAghion revised this gist Oct 14, 2010. 1 changed file with 11 additions and 18 deletions.
    29 changes: 11 additions & 18 deletions simple_redis_profile
    Original file line number Diff line number Diff line change
    @@ -1,11 +1,12 @@
    #!/usr/bin/env ruby

    #
    # Evaluates a sample of keys/values from each redis database, computing statistics for each key pattern:
    # keys: number of keys matching the given pattern
    # size: approximation of the associated memory occupied (based on size/length of key)
    # size: approximation of the associated memory occupied (based on size/length of value)
    # percent: the proportion of this 'size' relative to the sample's total
    #
    # Copyright Weplay, Inc. 2010. Available for use under the MIT license.


    require 'rubygems'
    require 'redis'
    @@ -14,19 +15,15 @@ require 'yaml'
    SAMPLE_SIZE = 10_000 # number of keys to sample from each db before computing stats


    # Silly approximation of memory footprint: size/length of value.
    # TODO accommodate new types
    # Naive approximation of memory footprint: size/length of value.
    def redis_size(db, k)
    t = db.type(k)
    case t
    when 'string'
    db.get(k).length
    when 'list'
    db.lrange(k, 0, -1).size
    when 'zset'
    db.zrange(k, 0, -1).size
    when 'set'
    db.smembers(k).size
    when 'string' then db.get(k).length
    when 'list' then db.lrange(k, 0, -1).size
    when 'zset' then db.zrange(k, 0, -1).size
    when 'set' then db.smembers(k).size
    else raise("Redis type '#{t}' not yet supported.") # TODO accommodate more types
    end
    end

    @@ -37,17 +34,13 @@ end
    def redis_db_profile(db_name, sample_size = SAMPLE_SIZE)
    db = Redis.new(:db => db_name)
    keys = []
    sample_size.times do |i|
    keys << db.randomkey
    end
    sample_size.times { |i| keys << db.randomkey }
    key_types = keys.group_by{|k| k.gsub(/\d+/, '#')}
    data = key_types.keys.collect{ |k|
    [k, {'keys' => key_types[k].size, 'size' => array_sum(key_types[k].collect{|k| redis_size(db, k)})}]
    }.sort_by{|a| a.last['size'] }.reverse
    size_sum = data.inject(0){|sum, d| sum += d.last['size'] }
    data.each do |d|
    d.last['percent'] = '%.2f%' % (d.last['size'].to_f*100/size_sum)
    end
    data.each { |d| d.last['percent'] = '%.2f%' % (d.last['size'].to_f*100/size_sum) }
    end

    db_names = `redis-cli info | grep ^db[0-9]`.split.map{|line| line.scan(/^db\d*/).first }
  4. joeyAghion revised this gist Oct 13, 2010. 1 changed file with 3 additions and 7 deletions.
    10 changes: 3 additions & 7 deletions simple_redis_profile
    Original file line number Diff line number Diff line change
    @@ -3,7 +3,7 @@
    #
    # Evaluates a sample of keys/values from each redis database, computing statistics for each key pattern:
    # keys: number of keys matching the given pattern
    # size: approximation of the associated memory occupied (based on size/length of key+value)
    # size: approximation of the associated memory occupied (based on size/length of key)
    # percent: the proportion of this 'size' relative to the sample's total
    #

    @@ -14,13 +14,9 @@ require 'yaml'
    SAMPLE_SIZE = 10_000 # number of keys to sample from each db before computing stats


    # silly approximation of memory footprint: length of key + size/length of value
    def redis_size(db, k)
    k.length + redis_value_size(db, k)
    end

    # Silly approximation of memory footprint: size/length of value.
    # TODO accommodate new types
    def redis_value_size(db, k)
    def redis_size(db, k)
    t = db.type(k)
    case t
    when 'string'
  5. joeyAghion created this gist Oct 13, 2010.
    64 changes: 64 additions & 0 deletions simple_redis_profile
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,64 @@
    #!/usr/bin/env ruby

    #
    # Evaluates a sample of keys/values from each redis database, computing statistics for each key pattern:
    # keys: number of keys matching the given pattern
    # size: approximation of the associated memory occupied (based on size/length of key+value)
    # percent: the proportion of this 'size' relative to the sample's total
    #

    require 'rubygems'
    require 'redis'
    require 'yaml'

    SAMPLE_SIZE = 10_000 # number of keys to sample from each db before computing stats


    # silly approximation of memory footprint: length of key + size/length of value
    def redis_size(db, k)
    k.length + redis_value_size(db, k)
    end

    # TODO accommodate new types
    def redis_value_size(db, k)
    t = db.type(k)
    case t
    when 'string'
    db.get(k).length
    when 'list'
    db.lrange(k, 0, -1).size
    when 'zset'
    db.zrange(k, 0, -1).size
    when 'set'
    db.smembers(k).size
    end
    end

    def array_sum(array)
    array.inject(0){|sum,e| sum += e }
    end

    def redis_db_profile(db_name, sample_size = SAMPLE_SIZE)
    db = Redis.new(:db => db_name)
    keys = []
    sample_size.times do |i|
    keys << db.randomkey
    end
    key_types = keys.group_by{|k| k.gsub(/\d+/, '#')}
    data = key_types.keys.collect{ |k|
    [k, {'keys' => key_types[k].size, 'size' => array_sum(key_types[k].collect{|k| redis_size(db, k)})}]
    }.sort_by{|a| a.last['size'] }.reverse
    size_sum = data.inject(0){|sum, d| sum += d.last['size'] }
    data.each do |d|
    d.last['percent'] = '%.2f%' % (d.last['size'].to_f*100/size_sum)
    end
    end

    db_names = `redis-cli info | grep ^db[0-9]`.split.map{|line| line.scan(/^db\d*/).first }
    db_names.each do |name|
    puts "\nProfiling \"#{name}\"...\n#{'-'*20}"
    y redis_db_profile(name)
    end

    puts "\nOverall statistics:\n#{'-'*20}"
    puts `redis-cli info | grep memory`