【问题标题】:StackExchange.Redis Async calls slower than sync callsStackExchange.Redis 异步调用比同步调用慢
【发布时间】:2015-01-16 09:54:49
【问题描述】:

我知道异步方法的目的不是为了提高性能,但我发现 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 只是一个数据库连接。我已经编辑了代码。我会尝试你的建议。
  • @James 我换了它,异步调用仍然慢很多。
  • 重点是,以提高性能。只是不要缩短执行单个操作所需的时间。
  • 性能差异肯定不是由于开销。在无限循环中运行查询。使用 taskmgr 查看已用完的资源。是客户端的CPU吗?在 Redis 中?是磁盘吗?那应该缩小查看的范围。我的猜测:根本没有达到极限。
  • 由于我们没有看到您的同步测试,我们甚至无法开始理解这是如何发生的。我的建议 - 创建一个适当的测试(不要忘记 JITting 开销)并将其与结果一起发布。

标签: c# async-await stackexchange.redis


【解决方案1】:

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

我的客户端代码在 Azure Iaas VM 上运行并连接到同一区域中的 Azure Redis 缓存。

测量排序集长度 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);
        }
    }

}

【讨论】:

    猜你喜欢
    • 2019-02-28
    • 1970-01-01
    • 2023-04-09
    • 2019-11-15
    • 2016-03-24
    • 2014-03-06
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多