Azure 存储队列在云中的辅助角色中速度非常慢,但在我的机器上则不然

发布于 2024-11-03 12:02:30 字数 3097 浏览 0 评论 0原文

我正在做一个非常简单的测试,队列指向真正的 Azure 存储,我不知道为什么,从我的计算机执行测试比将辅助角色部署到 azure 并在那里执行要快得多。当我在本地测试时,我没有使用开发存储,我的 .cscfg 具有到真实存储的连接字符串。

存储帐户和角色位于同一关联组中。

测试是一个Web角色和一个worker角色。该页面告诉工作人员要执行什么测试,工作人员执行该测试并返回所消耗的时间。此特定测试测量使用 32 条消息的批次从 Azure 队列获取 1000 条消息需要多长时间。首先,在将应用程序部署到 Azure 并从那里运行它之后,我使用 VS 测试运行调试。

结果是:

  • 从我的计算机:34805.6495 毫秒。
  • 来自 Azure 角色:7956828.2851 毫秒。

这可能意味着从 Azure 外部访问队列比从内部访问队列更快,但这是没有意义的。

我正在这样测试:

    private TestResult InQueueScopeDo(String test, Guid id, Int64 itemCount)
    {
        CloudStorageAccount account = CloudStorageAccount.Parse(_connectionString);
        CloudQueueClient client = account.CreateCloudQueueClient();
        CloudQueue queue = client.GetQueueReference(Guid.NewGuid().ToString());

        try
        {
            queue.Create();
            PreTestExecute(itemCount, queue);

            List<Int64> times = new List<Int64>();
            Stopwatch sw = new Stopwatch();
            for (Int64 i = 0; i < itemCount; i++)
            {
                sw.Start();
                Boolean valid = ItemTest(i, itemCount, queue);
                sw.Stop();
                if (valid)
                    times.Add(sw.ElapsedTicks);
                sw.Reset();
            }

            return new TestResult(id, test + " with " + itemCount.ToString() + " elements", TimeSpan.FromTicks(times.Min()).TotalMilliseconds,
                                                 TimeSpan.FromTicks(times.Max()).TotalMilliseconds,
                                                 TimeSpan.FromTicks((Int64)Math.Round(times.Average())).TotalMilliseconds);
        }
        finally
        {
            queue.Delete();
        }

        return null;
    }

PreTestExecute 将 1000 个项目放入队列中,每个项目 2048 字节。

这就是此测试的 ItemTest 方法中发生的情况:

    Boolean done = false;
    public override bool ItemTest(long itemCurrent, long itemCount, CloudQueue queue)
    {
        if (done)
            return false;

        CloudQueueMessage[] messages = null;

        while ((messages = queue.GetMessages((Int32)itemCount).ToArray()).Any())
        {
            foreach (var m in messages)
                queue.DeleteMessage(m);
        }

        done = true;

        return true;
    }

我不知道我做错了什么,相同的代码,相同的连接字符串,我得到了这些结果。

有什么想法吗?

更新:

问题似乎出在我的计算方式上。

我已经将 times.Add(sw.ElapsedTicks); 替换为 times.Add(sw.ElapsedMilliseconds); 和这个块:

return new TestResult(id, test + " with " + itemCount.ToString() + " elements",
TimeSpan.FromTicks(times.Min()).TotalMilliseconds,                             
TimeSpan.FromTicks(times.Max()).TotalMilliseconds,     
TimeSpan.FromTicks((Int64)Math.Round(times.Average())).TotalMilliseconds);

对于这个:

return new TestResult(id, test + " with " + itemCount.ToString() + " elements", 
times.Min(),times.Max(),times.Average());

现在结果是类似,所以显然在处理精度等方面存在差异。稍后我会研究这个。

I'm doing a very simple test with queues pointing to the real Azure Storage and, I don't know why, executing the test from my computer is quite faster than deploy the worker role into azure and execute it there. I'm not using Dev Storage when I test locally, my .cscfg is has the connection string to the real storage.

The storage account and the roles are in the same affinity group.

The test is a web role and a worker role. The page tells to the worker what test to do, the the worker do it and returns the time consumed. This specific test meassures how long takes get 1000 messages from an Azure Queue using batches of 32 messages. First, I test running debug with VS, after I deploy the app to Azure and run it from there.

The results are:

  • From my computer: 34805.6495 ms.
  • From Azure role: 7956828.2851 ms.

That could mean that is faster to access queues from outside Azure than inside, and that doesn't make sense.

I'm testing like this:

    private TestResult InQueueScopeDo(String test, Guid id, Int64 itemCount)
    {
        CloudStorageAccount account = CloudStorageAccount.Parse(_connectionString);
        CloudQueueClient client = account.CreateCloudQueueClient();
        CloudQueue queue = client.GetQueueReference(Guid.NewGuid().ToString());

        try
        {
            queue.Create();
            PreTestExecute(itemCount, queue);

            List<Int64> times = new List<Int64>();
            Stopwatch sw = new Stopwatch();
            for (Int64 i = 0; i < itemCount; i++)
            {
                sw.Start();
                Boolean valid = ItemTest(i, itemCount, queue);
                sw.Stop();
                if (valid)
                    times.Add(sw.ElapsedTicks);
                sw.Reset();
            }

            return new TestResult(id, test + " with " + itemCount.ToString() + " elements", TimeSpan.FromTicks(times.Min()).TotalMilliseconds,
                                                 TimeSpan.FromTicks(times.Max()).TotalMilliseconds,
                                                 TimeSpan.FromTicks((Int64)Math.Round(times.Average())).TotalMilliseconds);
        }
        finally
        {
            queue.Delete();
        }

        return null;
    }

The PreTestExecute puts the 1000 items on the queue with 2048 bytes each.

And this is what happens in the ItemTest method for this test:

    Boolean done = false;
    public override bool ItemTest(long itemCurrent, long itemCount, CloudQueue queue)
    {
        if (done)
            return false;

        CloudQueueMessage[] messages = null;

        while ((messages = queue.GetMessages((Int32)itemCount).ToArray()).Any())
        {
            foreach (var m in messages)
                queue.DeleteMessage(m);
        }

        done = true;

        return true;
    }

I don't what I'm doing wrong, same code, same connection string and I got these resuts.

Any idea?

UPDATE:

The problem seems to be in the way I calculate it.

I have replaced the times.Add(sw.ElapsedTicks); for times.Add(sw.ElapsedMilliseconds); and this block:

return new TestResult(id, test + " with " + itemCount.ToString() + " elements",
TimeSpan.FromTicks(times.Min()).TotalMilliseconds,                             
TimeSpan.FromTicks(times.Max()).TotalMilliseconds,     
TimeSpan.FromTicks((Int64)Math.Round(times.Average())).TotalMilliseconds);

for this one:

return new TestResult(id, test + " with " + itemCount.ToString() + " elements", 
times.Min(),times.Max(),times.Average());

And now the results are similar, so apparently there is a difference in how the precision is handled or something. I will research this later on.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

浮生未歇 2024-11-10 12:02:30

该问题显然是 StopWatch 和 TimeSpan 刻度不同性质的问题,正如所讨论的此处。

Stopwatch.ElapsedTicks 属性

秒表刻度与 DateTime.Ticks 不同。 DateTime.Ticks 值中的每个刻度代表一个 100 纳秒的间隔。 ElapsedTicks 值中的每个刻度表示时间间隔,等于 1 秒除以频率。

The problem apparently was a issue with different nature of the StopWatch and TimeSpan ticks, as discussed here.

Stopwatch.ElapsedTicks Property

Stopwatch ticks are different from DateTime.Ticks. Each tick in the DateTime.Ticks value represents one 100-nanosecond interval. Each tick in the ElapsedTicks value represents the time interval equal to 1 second divided by the Frequency.

一张白纸 2024-11-10 12:02:30

你的CPU利用率如何?您的代码是否可能导致 CPU 峰值,并且您的工作站比您的 Azure 节点快得多?

How is your CPU utilization? Is this possible that your code is spiking the CPU and your workstation is much faster than your Azure node?

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文