StackExchange.Redis异步调用比同步调用慢

5

我知道异步方法的目的并不是为了提高性能,但我发现StackExchange.Redis上的异步方法比同步方法慢得多。

public static async Task<bool> GetScoresFromSetAsync(int score, string name)
{
  string redisConnection = ConfigurationManager.AppSettings["RedisAccount"].ToString();
  ConnectionMultiplexer connection = ConnectionMultiplexer.Connect(redisConnection);
  IDatabase _cache = connection.GetDatabase();

  List<string> scores = new List<string>();

  var resultAsync = await _cache.SortedSetRangeByScoreAsync(name, score, score);
  var result = _cache.SortedSetRangeByScore(name score, score);
  return true;
}

异步调用大约需要5000毫秒,而非异步调用平均只需要30毫秒。我的redis托管在Azure上。有什么想法吗?
编辑:我正在谈论一个单独的请求。SortedSetRangeByScore API调用在30毫秒内返回,而SortedSetRangeByScoreAsync API调用在5000毫秒内返回。

抱歉,_cache 只是一个数据库连接。我已经编辑了代码。我会尝试你建议的方法。 - Kaladin
1
@James 我调换了一下,但异步调用仍然慢得多。 - Kaladin
1
重点在于提高性能,而不是缩短执行单个操作所需的时间。 - i3arnon
这个性能差异肯定不是由于开销造成的。在一个无限循环中运行查询。使用任务管理器查看哪个资源达到了最大值。是客户端的CPU吗?还是Redis?是磁盘吗?这应该缩小搜索范围。我猜测:根本没有达到最大值。 - usr
2
由于我们没有看到您的同步测试,我们甚至无法开始理解这是如何发生的。我的建议是 - 创建一个适当的测试(不要忘记JITting开销),并将其与结果一起发布。 - Yuval Itzchakov
显示剩余2条评论
1个回答

2

想知道您是如何进行延迟比较的?我尝试使用以下代码来测量,SE.Redis进行异步与同步所花费的时间非常接近。希望这可以帮助到您。

我的客户端代码运行在Azure Iaas VM上,并连接到同一地区的Azure Redis Cache。

针对排序集长度为10000、迭代次数为10000进行同步与异步测量

10000个同步调用平均完成时间为1.41190622毫秒

10000个异步调用平均完成时间为1.43989741毫秒

针对排序集长度为100000、迭代次数为1进行同步与异步测量

1个同步调用平均完成时间为0.9513毫秒

1个异步调用平均完成时间为1.1436毫秒

using StackExchange.Redis;

using System;

using System.Collections.Generic;

using System.Diagnostics;

using System.Threading;

using System.Threading.Tasks;

namespace RedisLatency

{

    class Program

    {

        private const string host = "myazurecache.redis.cache.windows.net";

        private const string password = "password";

        private static int sortedsetlength;

        private static int iterations;

        private static IDatabase _cache;

        static void Main(string[] args)

        {

            sortedsetlength = Int32.Parse(args[0]);

            iterations = Int32.Parse(args[1]);

            CreateMultiplexer(host,password);

            PopulateTestData();

            RunTestSync();

            RunTestAsync();

        }

        private static void CreateMultiplexer(string host, string password)

        {

            Console.WriteLine("Measuring sync vs async for sorted set length {0}, iteration {1}", sortedsetlength,iterations);

            ConfigurationOptions configoptions = new ConfigurationOptions();

            configoptions.EndPoints.Add(host);

            configoptions.Password = password;

            configoptions.Ssl = true;

            ConnectionMultiplexer connection =   ConnectionMultiplexer.Connect(configoptions);

            _cache = connection.GetDatabase();
        }

        private static void PopulateTestData()

        {

          for (int i = 0; i < sortedsetlength; i++)

            {
                _cache.SortedSetAdd("testsorted", "user" + i, i);
            }
        }

        static void RunTestSync()

        {

            for (int warmup = 0; warmup < 100; warmup++)

            {

                MeasureSync();

            }

            Stopwatch sw = Stopwatch.StartNew();

            for (int i = 0; i < iterations;i++ )

            {
                MeasureSync();
            }

            sw.Stop();

            Console.WriteLine("{0} sync calls completed in average {1} ms", iterations, sw.Elapsed.TotalMilliseconds/iterations);
        }

        async static void RunTestAsync()

        {

            //warm up

            for (int warmup = 0; warmup < 100; warmup++)
            {
                MeasureAsync().Wait();    
            }

            Stopwatch sw = Stopwatch.StartNew();

            for (int i = 0; i < iterations; i++)

            {

                MeasureAsync().Wait();

            }

            sw.Stop();

            Console.WriteLine("{0} async calls completed in average {1} ms", iterations, sw.Elapsed.TotalMilliseconds/iterations);

        }

        static public void MeasureSync()

        {

            var result = _cache.SortedSetRangeByScore("testset", 1.0, sortedsetlength / 1.0);

        }

        async static public Task MeasureAsync()
        {
            var result = await _cache.SortedSetRangeByScoreAsync("testset", 1.0, sortedsetlength / 1.0);
        }
    }

}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接