当前位置: 首页 > news >正文

做网站好做吗ip形象设计报价明细

做网站好做吗,ip形象设计报价明细,网站开发与规划,网站商城注意事项原文来自互联网#xff0c;由长沙DotNET技术社区编译。如译文侵犯您的署名权或版权#xff0c;请联系小编#xff0c;小编将在24小时内删除。作者介绍#xff1a;史蒂夫戈登#xff08;Steve Gordon#xff09;是Microsoft MVP#xff0c;Pluralsight的作者#xff0c;… 原文来自互联网由长沙DotNET技术社区编译。如译文侵犯您的署名权或版权请联系小编小编将在24小时内删除。作者介绍史蒂夫·戈登Steve Gordon是Microsoft MVPPluralsight的作者布莱顿英国西南部城市的高级开发人员和社区负责人。在本文中我将继续有关编写高性能C和.NET代码的系列文章[1]。这次我将重点介绍String类型–String.Create-一种可用的新方法。.NET Core 2.1中首次引入该方法目前计划将该方法发布后作为.NET Standard 2.1的一部分包含在内。STRING.CREATE做什么String.Create方法支持有效创建需要在运行时构建或计算的字符串。在我进一步讨论之前让我们花一点时间来介绍有关字符串的一些事实。•在.NET中字符串是一种流行的类型用于表示文本数据。•字符串是引用类型它们的数据存储在托管堆中。•根据设计字符串是不可变的这意味着一旦创建就无法修改其数据。从高性能的角度来看这些事实的结合会导致字符串出现问题。从高层次上讲我们编写高性能代码的目标通常是减少运行该代码的执行时间并删除内存分配。由于其不变性对字符串进行操作通常会导致分配过多。如果要提取字符串的一部分则会导致创建新字符串以及在旧字符串和新字符串占用的内存之间复制字符串数据。如果我们想将字符串转换为大写这也会导致在堆上分配新的字符串。如果我们想使用仅在运行时可用的数据以编程方式创建字符串则也会出现问题。串联字符串也将导致分配和复制。对于长字符串尤其是由许多组成部分组成的字符串此成本可能会显着增加。这并不意味着在适当的时候不应该使用字符串但是在编写高度优化的代码时就成为一个问题。在运行时构造字符串时使用的标准解决方案是使用StringBuilder该StringBuilder使用附加了字符的内部缓冲区。当您在StringBuilder上调用build方法时这将导致最终的字符串分配。当串联多个元素时StringBuilder通常比普通串联更有效始终使用基准测试来验证您的方案。StringBuilder仍然需要字符的中间缓冲区因此在那里要分配堆并在从缓冲区构建字符串时再加上一个副本。StringBuilder本身是一个类因此使用其中的分配。在ASP.NET Core团队已经在热路径上通过池化和共享StringBuilder的实例来解决这个分配成本问题这是有意义的例如在中间件等地方。什么时候使用STRING.CREATE在日常开发过程中不需要String.Create。它有一个特定的目的即以高度优化的方式从某些现有数据实用地创建字符串或者可能仅通过算法来创建字符串。在这种情况下主要的优化是帮助我们避免不必要的分配和数据复制。我们将在几分钟后看一个可行的示例但在此之前让我们考虑一些更通用的用例。在用于ASP.NET Core的Kestrel Web服务器中每个请求都会创建唯一的ID。在这种情况下要求构建一个长度和格式已知的字符串该字符串将唯一地标识请求。由于此操作每秒可能完成数千次因此使其性能良好至关重要。String.Create允许在这种情况下有效地构造字符串。STRING.CREATE如何工作String.Creates提供了一个非常短的窗口允许我们从本质上打破字符串的不变性规则。这听起来有些吓人但还不如我讲的那么糟糕。可能发生数据突变的窗口仅在返回对字符串的第一个引用之前。在此简短窗口之后将无法修改现有字符串的数据。在内部String.Create在堆上分配适当的内存部分以包含字符串数据的char数组。为此该方法将字符串所需的长度作为第一个参数。这是一个重要的限制您必须知道或能够预先计算出要创建的字符串的确切字符长度。这是Create方法的签名 public static string CreateTState (int length, TState state, System.Buffers.SpanActionchar,TState action); 该方法采用第二个参数这是构造字符串所需的一般状态。一会儿我们来专门介绍这个状态。 最后create方法接受一个委托该委托应在分配的堆内存上进行操作以设置最终的字符串数据。在这种情况下参数是SpanAction它在System.Buffers中定义。由于Span 类型不能用作泛型类型参数因此不能使用标准的Action委托。相反SpanAction支持采用将用作内部Span 的类型的类型。在这种情况下我们正在处理字符。SpanAction委托就是魔力所在。在分配了字符串所需的char []内存之后然后可以使用我们传递的委托来填充该数组中的字符。委托完成后将返回内部使用该数组的字符串并已正确设置其值。让我们考虑一下不使用此方法即可构建字符串的最低分配方式之一。我们可能会使用临时char数组作为缓冲区来构建字符串数据然后将该数组传递给字符串的构造函数。这基本上就是StringBuilder为我们所做的。这种方法将导致两种分配一种分配给缓冲区另一种分配给字符串。所涉及的阵列之间也会发生一些内存复制。可能是这样的 using System;namespace StringCreateSample{class Program{private const char spaceSeparator ; // space separator characterstatic void Main(){// Our source data (state) which will be composed into the final string.var context new ContextData{FirstString Hello,SecondString .NET,ThirdString friends.};var length context.FirstString.Length 1 context.SecondString.Length 1 context.ThirdString.Length;var buffer new char[length]; // allocationvar position 0;for (var i 0; i context.FirstString.Length; i){buffer[i] context.FirstString[i];position;}buffer[position] spaceSeparator;for (var i 0; i context.SecondString.Length; i){buffer[position] context.SecondString[i];}buffer[position] spaceSeparator;for (var i 0; i context.ThirdString.Length; i){buffer[position] context.ThirdString[i];}Console.WriteLine(new string(buffer)); // string allocation copy}}internal struct ContextData{public string FirstString { get; set; }public string SecondString { get; set; }public string ThirdString { get; set; }}} 另一个选择是使用不安全的代码或者在.NET Core 2.1及更高版本中我们可以使用Span 支持来安全地使用小的堆栈分配缓冲区而不是堆分配的数组。只要缓冲区的大小不是太大这将是一个不错的选择并且我们将仅针对最后一个字符串进行一次堆分配。但是将需要一个副本来将数据从堆栈内存中移到字符串堆内存中。这具有很小的执行时间成本。 我们的示例Main方法中为实现此目的所做的更改如下所示static void Main(){// Our source data (state) which will be composed into the final string.var context new ContextData{FirstString Hello,SecondString .NET,ThirdString friends.};var length context.FirstString.Length 1 context.SecondString.Length 1 context.ThirdString.Length;// In real-world code we should ensure we dont try to allocate too much on the stack!// Ignoring that risk for this example.Spanchar buffer stackalloc char[length]; // DOES NOT heap allocatevar position 0;for (var i 0; i context.FirstString.Length; i){buffer[i] context.FirstString[i];position;}buffer[position] spaceSeparator;for (var i 0; i context.SecondString.Length; i){buffer[position] context.SecondString[i];}buffer[position] spaceSeparator;for (var i 0; i context.ThirdString.Length; i){buffer[position] context.ThirdString[i];}Console.WriteLine(new string(buffer)); // string allocation copy from stack memory} 回到String.Create我们现在可以了解这如何为我们提供最佳性能。通过避免对字符进行预缓冲即使该字符在堆栈中这意味着用于构造字符串的逻辑将直接作用于该字符串将引用的存储器的最终区域。正确完成后我们可以以编程方式构建字符串而无需中间分配并且具有很高的性能。 在SpanAction中我们可以通过字符串占用的内存访问Span 。我们可以通过Span修改该内存将其切成适当的位置并将字符写入基础数组。传入的状态将允许我们使用现有数据来构建字符串。您可能已经在想一个重要的问题。为什么将状态直接传递给Create方法为什么我们不能仅仅从委托代码中引用我们需要的数据原因是如果我们捕获变量则后一种方法将导致关闭。编译器将必须生成一个类来处理此问题这是我们在此处要避免的堆分配。另外这里的关闭将防止委托的缓存这本身就是我们无法承受的性能损失。相反Create方法接受状态作为参数以避免委托形成闭包。解释起来有点复杂但是这里的要点是确保状态中需要包含为创建字符串而需要访问的所有对象。如果要传递多个对象建议的模式是使用ValueTuple[2]。由于这是一个结构因此它不会分配任何内容一旦进入委托您就可以对其进行解构以获取组成部分。使用STRING.CREATE的快速示例在深入研究真实示例之前让我们快速看一下如何使用String.Create。using System;namespace StringCreateSample{class Program{private const char spaceSeparator ; // space separator characterstatic void Main(){// Our source data (state) which will be composed into the final string.var context new ContextData{FirstString Hello,SecondString .NET,ThirdString friends.};var length context.FirstString.Length 1 context.SecondString.Length 1 context.ThirdString.Length;var myString string.Create(length, context, (chars, state) {// NOTE: We dont access the context variable in this delegate since // it would cause a closure and allocation.// Instead we access the state parameter.// will track our position within the string data we are populatingvar position 0;// copy the first string data to index 0 of the Spancharstate.FirstString.AsSpan().CopyTo(chars);position state.FirstString.Length; // update the position// add a space in the current position and increement position by 1chars[position] spaceSeparator;// copy the second string data to a slice at current positionstate.SecondString.AsSpan().CopyTo(chars.Slice(position)); position state.SecondString.Length; // update the position// add a space in the current position and increement position by 1chars[position] spaceSeparator;// copy the third string data to a slice at current positionstate.ThirdString.AsSpan().CopyTo(chars.Slice(position)); });Console.WriteLine(myString);}}internal struct ContextData{public string FirstString { get; set; }public string SecondString { get; set; }public string ThirdString { get; set; }}} 这段代码中的注释逐步说明了正在发生的事情。 从上面我们可以看出一个结论我们有一个ContextData对象其中包含三个我们要用来构建最终字符串的字符串。首先我们计算最终字符串所需的长度该长度包括组成部分及其之间的间距。我们将长度传递给string.Create并将上下文作为状态参数传递。最后我们定义SpanAction委托的代码该代码切片为基础Span 以将组件部分复制到最终字符串中的正确位置。所有这些都是通过为字符串所需的内存分配单个堆来实现的。如何使用STRING.CREATE –一个真实的例子现在让我们根据我遇到的实际情况看一个可行的示例。请注意这仍然是演示代码。它基于我的生产要求但是我已经对其进行了简化以便我们可以专注于特定技术。我有把握地确定它可以进一步优化在我的演讲“Turbocharged: Writing High-Performance C# and .NET Code”中我讨论了一个服务示例其中从AWS SQS队列中读取消息后我需要将消息正文存储到S3存储桶中。将内容存储到S3中时我们必须为对象提供唯一的键。因此此服务必须计算在上载对象时传递到AWS开发工具包的密钥。在我们的案例中这种情况每天发生1800万次因此即使是很小的性能提升也会对规模产生重大影响。密钥由传入消息中的八个元素组成。最终键中仅允许使用小写字母数字和下划线并且任何空格都应转换为下划线。构造字符串的第一种方法是使用数组固定组成部分然后将各个片段连接在一起以形成最终字符串。我不会在这篇文章中显示所有代码但是您可以在我的GitHub repo中[3]查看一个示例[4]。第二次迭代使用堆栈分配的字符数组作为缓冲区以形成字符串的最终数据。通过在该内存上使用Span 我便能够将各种元素复制到堆栈分配的缓冲区中。在Span 上调用ToString导致创建了对象键的最终字符串。再次我不会在这里显示该代码因为它很长。如果您想签出也可以在我的仓库中[5]找到。在最后的迭代中我利用了String.Create这意味着我可以避免将内存从堆栈分配的缓冲区复制到字符串的堆内存中。如果您想浏览该代码也可以在我的GitHub repo中找到[6]。请记住这些样本尚未完全优化其设计目的是演示某些特定技术而非完整的优化。在我的案例中String.Create在运行的基准测试中仅稍快一些。将来我将对此进行更深入的探讨。这是我比较这两种方法的基准结果。图片在大多数情况下String.Create方法的速度要快几纳秒但是在某些基准测试运行中它的速度要慢几纳秒。潜在地我可以对转换逻辑进行一些进一步的优化从而可以解决这一问题。从逻辑上讲将数据从堆栈内存复制到字符串堆内存所需的工作较少应该会更有效率但是对于您的实际情况而言它始终值得测试。为了对此进行研究我对纯String.Create和stackalloc创建进行了一些基准测试。对于较短的字符串stackalloc似乎只快一点。这是一个基准测试在此基准下我使用两种方法将10个字符的短字符串组合在一起。在这种情况下每个测试中组合的字符串数中的计数。只有五个项目根本没有太多。到组合100个字符串时使用String.Create带来的性能提升更加明显。图片如果您对String.Create的另一个示例用例感兴趣我已经在ASP.NET Core基于代码的地方确定了String.Create应该改善性能的地方。我提出了一个GitHub问题来[7]证明这一点并希望参与创建PR以提出最终优化方案。字符串创建最佳实践这篇文章中已经有很多信息可以解释一个方法。最后让我们回顾最重要的几点。•String.Create提供了一种高性能低分配的方法来以编程方式创建字符串。•与所有性能优化一样对原始解决方案进行基准测试并确保所做的更改具有积极作用。•避免闭包并确保不要在SpanAction委托中捕获外部变量。•使用ValueTuples可以为状态传递多个对象。STRING.CREATE的局限性与您可能熟悉的其他一些创建新字符串的方法相比使用String.Create涉及更多。我不建议在每个地方都使用此功能但是在性能较高的应用程序中它可能会提供一些有价值的收益。您可能遇到的最大限制是您必须事先知道或能够计算所需字符串的确切长度。您可能需要访问所有组成状态对象的长度以便计算最终字符串的长度。在某些情况下构建字符串时有很多条件逻辑仅知道部件的长度可能还不够。摘要String.Create在高性能方案中很有用。一旦了解了它的运行规则就可以直接使用它。因此如果您正在优化应用程序中的热路径那么它是一个值得记住的工具并且在解析和生成字符串通常是其主要功能的一部分的应用程序中可能会获得重大收益。谢谢阅读如果您想了解有关高性能.NET和C代码的更多信息可以在此处[8]查看我的完整博客文章系列。References[1] 有关编写高性能C和.NET代码的系列文章: https://www.stevejgordon.co.uk/writing-high-performance-csharp-and-dotnet-code[2] ValueTuple: https://blogs.msdn.microsoft.com/mazhou/2017/05/26/c-7-series-part-1-value-tuples/[3] 在我的GitHub repo中: https://github.com/stevejgordon/TurbochargedDemos/blob/master/src/1%20-%20ObjectKeyBuilderDemo/S3ObjectKeyGenerator.cs[4] 一个示例: https://github.com/stevejgordon/TurbochargedDemos/blob/master/src/1%20-%20ObjectKeyBuilderDemo/S3ObjectKeyGenerator.cs[5] 可以在我的仓库中: https://github.com/stevejgordon/TurbochargedDemos/blob/master/src/1%20-%20ObjectKeyBuilderDemo/S3ObjectKeyGeneratorNew.cs[6] GitHub repo中找到: https://github.com/stevejgordon/TurbochargedDemos/blob/master/src/1%20-%20ObjectKeyBuilderDemo/S3ObjectKeyGeneratorNewV2.cs[7] 提出了一个GitHub问题: https://github.com/aspnet/AspNetCore/issues/10290[8] 在此处: https://www.stevejgordon.co.uk/writing-high-performance-csharp-and-dotnet-code
http://www.huolong8.cn/news/240920/

相关文章:

  • 网站文字代码湖北 商城网站建设
  • 外贸手工做兼职的网站宁波工业设计公司排名
  • 建筑工程网站免费西安黑马程序员培训机构
  • 网站开发最好用什么软件c蔡甸区城乡建设局网站
  • ui设计师怎么做自己的网站优化培训内容
  • 深圳商城手机网站建设安卓原生开发
  • 上海品划网络做网站淘宝网页版电脑版入口
  • 无做a视频网站用哪个网站做简历更好
  • 网站模板 seowordpress企业网站cms
  • 广州市城乡建设部网站首页怎么修改网站关键词
  • 网站建设公司西安网站系统设计论文
  • 网站后缀com微网站 建设
  • 微网站购物网站网页模板免费版
  • 文友胜做的网站小程序++wordpress
  • 公众号里的网站怎么做的购物网站php模板
  • 外链的论坛网站sem seo 区别
  • 网站导航条和表格怎么做网页小游戏插件不支持
  • 西安php网站建设酷家乐在线设计网页版
  • 网站制作遨游免费奔牛网络推广
  • 国家批准做新闻的网站新竹自助网站
  • wordpress零基础建站教程英文网站google推广
  • 青岛市做网站济南学习做网站
  • 初学者的网站建设cms开发语言有哪些
  • 陕西省建设厅管理中心网站国内现货交易平台
  • 网站整体设计风格怎么查域名服务商
  • 重庆做网站公司电话网店网络营销与推广策划书
  • 自适应手机网站开发手机网站建设 移商动力
  • 怎么看一个网站用什么语言做的青岛网站推广 软件
  • 一个网站不兼容ie怎么做03340 网站建设与管理
  • 桂林论坛网站有哪些前端工程师招聘