Redis和Ruby中的ZRANGEBYSCORE

时间:2014-06-24 23:03:16

标签: ruby redis big-o benchmarking

我正在尝试在Ruby中的Redis代码中优化ZRANGEBYSCORE。

具体来说,Redis网站(http://redis.io/commands/zrangebyscore)声明:

  

时间复杂度:O(log(N)+ M),其中N是元素的数量   排序集和M返回的元素数。如果M是   常数(例如总是要求LIMIT的前10个元素),   你可以认为它是O(log(N))。

所以,正如我读到的那样,只要我使用限制,大(O)应该在O(log(N)处保持不变,无论限制是设置为48还是6.但是,我的基准测试似乎另有建议。

require 'redis'

def bench(descr)
    start = Time.now
    yield
    puts "#{descr} #{Time.now-start} seconds"
end

def with_pipelining_48
    id = 26053643
    @@redis.pipelined {
        1000.times {
            @@redis.zrevrangebyscore("key:#{id}", "+inf", "-inf", :limit => [0, 48],:with_scores => true)
        }
    }
end

def with_pipelining_24
    id = 26053643
    @@redis.pipelined {
        1000.times {
            @@redis.zrevrangebyscore("key:#{id}", "+inf", "-inf", :limit => [0, 24],:with_scores => true)
        }
    }
end

def with_pipelining_12
    id = 26053643
    @@redis.pipelined {
        1000.times {
            @@redis.zrevrangebyscore("key:#{id}", "+inf", "-inf", :limit => [0, 12],:with_scores => true)
        }
    }
end

def with_pipelining_6
    id = 26053643
    @@redis.pipelined {
        1000.times {
            @@redis.zrevrangebyscore("key:#{id}", "+inf", "-inf", :limit => [0, 6],:with_scores => true)
        }
    }
end

bench("with pipelining_48") {
    with_pipelining_48
}
bench("with pipelining_24") {
    with_pipelining_24
}
bench("with pipelining_12") {
    with_pipelining_12
}
bench("with pipelining_6") {
    with_pipelining_6
}

返回以下结果:

with pipelining_48 1.709097 seconds
with pipelining_24 0.930054 seconds
with pipelining_12 0.801045 seconds
with pipelining_6 0.633037 seconds

我的结果似乎与Redis文档不一致。有人可以说明可能导致分歧的原因。

2 个答案:

答案 0 :(得分:1)

因此,首先,对于真正的基准测试,您应该在抛弃异常值后取平均值。所有这些操作之间的差异都是以毫秒为单位,所以如果你只是有一个微小的网络打嗝,或者你的盒子上发生了一些奇怪的事情,它就会把数字丢掉。如果你这样做,你的数字可能会有所不同。

其次,当您对Redis进行操作时,除了操作成本之外,还会发生更多事情。需要与Redis建立连接以及其他相关的启动成本。数据也需要传输,并且将来回进行网络传输。您的时间安排不仅仅是运营成本,还包括所有这些辅助成本。这些也将是非线性的,因为可以根据数据大小使用用于保持数据的不同格式。总而言之,要点是zrevrangebyscore是O(log(n)+ m),但操作中也涉及辅助成本,并且运营成本低(几乎总是如此) Redis),这些成本使操作的实际成本相形见绌。这是一件好事。

答案 1 :(得分:0)

我相信你误解了Big(O)的含义。 Big(O)是一个复杂性度量,正如Redis的文档所述,通过保持M不变,你可以放弃它对复杂性的“贡献”(基本上,O(常数)= O(1))。这意味着如果你要比较这些操作,只要M保持不变,只有N起作用。

然而,这并不意味着性能是相同的。返回6个元素或24个不同,因为您正在移动不同数量的数据(无论复杂程度如何)。