首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >BookSleeve -设置哈希时性能不佳

BookSleeve -设置哈希时性能不佳
EN

Stack Overflow用户
提问于 2013-09-09 00:48:01
回答 1查看 727关注 0票数 1

我正在更新我的web服务,以使用最新的BookSleeve库1.3.38。以前我用的是1.1.0.7

在进行一些基准测试时,我注意到在Redis中使用新版本的BookSleeve设置散列比旧版本慢很多倍。请考虑以下C#基准代码:

代码语言:javascript
复制
public void TestRedisHashes()
{
  int numItems = 1000; // number of hash items to set in redis 
  int numFields = 30; // number of fields in each redis hash
  RedisConnection redis = new RedisConnection("10.0.0.01", 6379);
  redis.Open();

  // wait until the connection is open
  while (!redis.State.Equals(BookSleeve.RedisConnectionBase.ConnectionState.Open)) { }

  Stopwatch timer = new Stopwatch();
  timer.Start();
  for (int i = 0; i < numItems; i++)
  {
    string key = "test_" + i.ToString();

    for (int j = 0; j < numFields; j++)
    {
      // set a value for each field in the hash
      redis.Hashes.Set(0, key, "field_" + j.ToString(), "testdata");
    }
    redis.Keys.Expire(0, key, 30); // 30 second ttl
  }
  timer.Stop();

  Console.WriteLine("Elapsed time for hash writes: {0} ms", timer.ElapsedMilliseconds);
}

BookSleeve 1.1.0.7需要大约20 to才能将1000散列设置为Redis2.6,而1.3.38则需要大约400 to。慢了20倍!我测试过的BookSleeve 1.3.38的其他部分与旧版本一样快或更快。我也尝试过使用Redis2.4进行同样的测试,以及在事务中包装所有东西。在这两种情况下,我都得到了类似的表现。

还有人注意到这样的事吗?我肯定做错什么了..。我是否使用新版本的BookSleeve正确设置散列?这是做火灾和遗忘命令的正确方式吗?虽然我把单元测试看作是如何使用散列的一个例子,但是还没有找到我正在做的不同的事情。在这种情况下,最新的版本有可能慢一些吗?

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2013-09-09 07:27:58

要实际测试总体速度,需要添加等待处理最后一条消息的代码,例如:

代码语言:javascript
复制
  Task last = null;
  for (int i = 0; i < numItems; i++)
  {
    string key = "test_" + i.ToString();

    for (int j = 0; j < numFields; j++)
    {
      // set a value for each field in the hash
      redis.Hashes.Set(0, key, "field_" + j.ToString(), "testdata");
    }
    last = redis.Keys.Expire(0, key, 30); // 30 second ttl
  }
  redis.Wait(last);

否则,您正在计时的是对Set/Expire的调用有多快。在这种情况下,这可能很重要。您可以看到,在1.1.0.7中,所有消息都会立即放置到队列中,然后一个单独的专用写入线程将该消息接收并将其写入流。在1.3.38中,专用的编写线程消失了(出于各种原因)。因此,如果套接字可用,则调用线程将写入底层流(如果套接字正在使用,则有一种机制来处理该机制)。更重要的是,在您最初针对1.1.0.7的测试中,还没有实际发生任何有用的工作--无法保证工作在套接字附近,等等。

但是,在大多数情况下,这不会导致任何开销(摊销时开销也会减少):在您的情况下,您可能受到运行中的有效缓冲区的影响--在1.1.0.7中,您会非常快地填充缓冲区,并且工作线程可能总是会找到更多的等待消息--因此直到最后它才会刷新流;在1.3.38中,它可能会在消息之间进行刷新。所以:让我们解决这个问题:

代码语言:javascript
复制
Task last = null;
redis.SuspendFlush();
try {
  for (int i = 0; i < numItems; i++)
  {
    string key = "test_" + i.ToString();

    for (int j = 0; j < numFields; j++)
    {
      // set a value for each field in the hash
      redis.Hashes.Set(0, key, "field_" + j.ToString(), "testdata");
    }
    last = redis.Keys.Expire(0, key, 30); // 30 second ttl
  }
}
finally {
  redis.ResumeFlush();
}
redis.Wait(last);

当在单个线程上调用大量操作时,SuspendFlush() / ResumeFlush()对是理想的,以避免任何额外的刷新。要复制intellisense注释:

代码语言:javascript
复制
//
// Summary:
// Temporarily suspends eager-flushing (flushing if the write-queue becomes
// empty briefly). Buffer-based flushing will still occur when the data is full.
// This is useful if you are performing a large number of operations in close
// duration, and want to avoid packet fragmentation. Note that you MUST call
// ResumeFlush at the end of the operation - preferably using Try/Finally so
// that flushing is resumed even upon error. This method is thread-safe; any
// number of callers can suspend/resume flushing concurrently - eager flushing
// will resume fully when all callers have called ResumeFlush.
//
// Remarks:
// Note that some operations (transaction conditions, etc) require flushing
// - this will still occur even if the buffer is only part full.

请注意,在大多数高吞吐量场景中,多个操作来自多个线程:在这些场景中,来自并发线程的任何工作都将自动排队,从而将线程数量降至最低。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/18690140

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档