gpt4 book ai didi

c# - 多次 Response.writeAsync 调用

转载 作者:行者123 更新时间:2023-11-30 15:23:47 31 4
gpt4 key购买 nike

我一直在研究 Asp.Net Security,我发现了一些令人惊讶的代码:

奇怪的代码?

context.Response.ContentType = "text/html";
await context.Response.WriteAsync("<html><body>");
await context.Response.WriteAsync("An remote error has occured: " + context.Request.Query["ErrorMessage"] + "<br>");
await context.Response.WriteAsync("<a href=\"/\">Home</a>");
await context.Response.WriteAsync("</body></html>");

让我吃惊的是使用短字符串多次调用 WriteAsync。

我会做什么

我会使用带有 String.Format 或 StringBuilder 的模板来连接字符串,然后在一次调用中编写:

var template = @"
<html><body>
An remote error has occured:{0}<br>
<a href=\"/\">Home</a>
</body></html>
";

var html = string.format(template, context.Request.Query["ErrorMessage"]);
await context.Response.WriteAsync(html);

我观察到的差异

  • 我的代码更容易修改。
  • 我有一些额外的空白。
  • 我的代码使用较大的硬编码字符串而不是一堆小的硬编码字符串。
  • 我使用 String.Format,与串联相比,可能性能受到影响。
  • 如果应避免字符串连接,则应拆分这部分:

    "An remote error has occured: " + context.Request.Query["ErrorMessage"] + "<br>"

问题

为了讨论的目的。假设这是在平均同时有约 10,000 个活跃用户的 Web 服务器的上下文中:因此性能很重要。

  • 为什么要这样做?
  • 它如何影响性能?
  • 什么时候应该调用 await Response.WriteAsync 而不是 Response.Write?
  • 应多久调用一次 Response.WriteAsync?
    • 尽可能频繁地使用少量数据
    • 仅当大量文本准备就绪时

最佳答案

我创建了一个 Azure 网站(在 Basic 1 - 1 小型实例上运行)来对其进行基准测试。然后我使用了https://loader.io的免费服务在 1 分钟内以每秒 100 个用户的速度运行每个测试。

我以不同的顺序对每个测试运行了 3 次。每次测试运行的时间都在 200 毫秒以内。

结果:

结果很明显:StringBuilder 显着获胜。每次异步调用的成本远远超过任何形式的字符串连接的成本(甚至 String.Format 的性能优于多次异步调用)。

  • 1992 毫秒 - StringBuilder.Append
  • 3071 毫秒 - StringBuilder.AppendFormat
  • 4257ms - WriteAsync with String.Format
  • 9265 毫秒 - 写异步

这是每个测试的代码:

    // Do not write this code - It is ugly and performs terribly
private async Task TestWriteAsync(HttpContext context)
{
var r = context.Response;

var id = "id";
var size = "12";
var text = "text";

await r.WriteAsync("<div style='display:none'>");

for (int i = 0; i < 10000; i++)
{
await r.WriteAsync("<li id='");
await r.WriteAsync(id);
await r.WriteAsync("' style='font-size:");
await r.WriteAsync(size);
await r.WriteAsync("'>");
await r.WriteAsync(text);
await r.WriteAsync("</li>");
}

await r.WriteAsync("</div>");
}

// This is much better, but still not great
private async Task TestWriteAsyncFormat(HttpContext context)
{
var r = context.Response;

var id = "id";
var size = "12";
var text = "text";
var template = "<li id='{0}' style='font-size:{1}'>{2}</li>";

await r.WriteAsync("<div style='display:none'>");

for (int i = 0; i < 10000; i++)
{
await r.WriteAsync(string.Format(template, id, size, text));
}

await r.WriteAsync("</div>");
}

// The Performance Winner, but ugly code
private async Task TestStringBuilder(HttpContext context)
{
var sb = new StringBuilder();

var id = "id";
var size = "12";
var text = "text";

sb.Append("<div style='display:none'>");

for (int i = 0; i < 10000; i++)
{
sb.Append("<li id='");
sb.Append(id);
sb.Append("' style='font-size:");
sb.Append(size);
sb.Append("'>");
sb.Append(text);
sb.Append("</li>");
}

sb.Append("</div>");

await context.Response.WriteAsync(sb.ToString());
}

// Decent performance and Clean Code
private async Task TestStringBuilderFormat(HttpContext context)
{
var sb = new StringBuilder();

var id = "id";
var size = "12";
var text = "text";
var template = "<li id='{0}' style='font-size:{1}'>{2}</li>";

sb.Append("<div style='display:none'>");

for (int i = 0; i < 10000; i++)
{
sb.AppendFormat(template, id, size, text);
}

sb.Append("</div>");

await context.Response.WriteAsync(sb.ToString());
}

因此,尽管旧的“Response.Write”比具有同步请求的 StringBuilder 快,但“await Response.WriteAsync”要慢得多(因为异步开销)。

测试截图:

enter image description here

enter image description here

enter image description here

enter image description here

关于c# - 多次 Response.writeAsync 调用,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/33940903/

31 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com