技术频道导航
HTML/CSS
.NET技术
IIS技术
PHP技术
Js/JQuery
Photoshop
Fireworks
服务器技术
操作系统
网站运营

赞助商

分类目录

赞助商

最新文章

搜索

[C#技巧]使用using块比没有using块语句消耗更少的内存

作者:admin    时间:2023-5-5 17:46:3    浏览:

在前面我们介绍了几个C#性能优化技巧,你可以看出如下文章:

今天我再介绍一些C#技巧,这些方法可以使C#程序消耗更少的内存,从而达到优化性能的目的。

using块比没有using块语句消耗更少的内存

下面的例子可以证明 using 块比没有 using 块语句消耗更少的内存。

我们知道,如果我们实现一个 using 块,代码大小可能会更大,因为 using 块在内部会在 IL 代码中创建一个 try ... catch,但是一旦它在运行时在 IL 代码中实现,它就会有效地处理系统内存。为了证明这一点,我编写了一个简单的程序,如下所示。

using System;  
using System.Collections.Generic;  
using System.Linq;  
using System.Text;  
using System.Diagnostics;  
using System.IO;  
using System.Net;  
using System.Net.NetworkInformation;  
using System.Threading;  
using System.Globalization;  
using System.Data.SqlClient;  
namespace Test1  
{  
    class Test  
    {  
        public void Test1()  
        {  
             StreamWriter wr = new StreamWriter(@"D:\text.txt");  
        }  
        public void Test2()  
        {  
             using (StreamWriter wr = new StreamWriter(@"D:\abc.txt"))  
             {   
             }  
        }  
    }   
    class Program  
    {  
        static void Main(string[] args)  
        {  
            Test t = new Test();  
            t.Test1();  
            t.Test2();   
        }  
    }  
}  

在输出部分,我组合了三个输出屏幕。

 

在分配图中,我们看到 using 块比没有 using 块消耗更少的资源,因为如果我们实现 using 块,程序可以有效地管理内存。

通常高级别的方法,其速度越慢

通常,你使用的方法级别越高,它就越慢。我在这里发现的一个常见示例是,当处于代码的繁忙部分(可能在被调用数百万次的循环中)时使用 LINQLINQ非常适合快速表达可能需要大量代码行的内容,但大家经常会把性能搁置一旁。

别误会我的意思——LINQ 非常适合开发出可运行的应用程序。但是在代码库中以性能为中心的部分,可能会放弃太多。特别是因为将如此多的操作链接在一起非常容易。

我自己的具体示例涉及 .SelectMany().Distinct().Count(),鉴于它被调用了数千万次,它累积了大量的运行时间。我采用了另一种方法,将执行时间减少了几个数量级。

  • 虽然高级别的方法看起来更简洁、更快,但它也可以隐藏不必要的复杂性和冗余运行时。

不要使用空析构函数

标题说明了一切——不要在你的类中添加空的析构函数。对于每个具有析构函数的类,都会将一个条目添加到 Finalize 队列中。然后,垃圾收集器 (GC) 在调用析构函数的时候调用处理队列。一个空的析构函数意味着这一切都是无用的。

请记住,正如我们已经提到的,GC 执行在性能方面并不便宜。不要不必要地为 GC 工作。

  • 避免使用空的析构函数来保留 GC:除非必要,否则不要使用终结器,并在需要时使用 SafeHandle。

避免不必要的分配

在这里,我将重点关注一个技巧:避免不必要的分配。这意味着要避免这样的事情:

List<Product> products = new List<Product>();

products = productRepo.All();

第一行创建了一个完全无用的列表实例,因为紧接着的下一行返回另一个实例并将其引用分配给变量。现在想象上面的两行代码在一个执行数千次的循环中?

不要关注示例本身,而是关注一般建议:

  • 除非确实需要,否则不要创建对象。

C#/.NET 具有垃圾收集功能,该过程确定哪些对象当前已过时并将其删除以释放内存空间。这意味着在 C# 中,与 C++ 等语言不同,你不必手动处理删除不再有用的对象以声明其内存空间的问题。相反,垃圾收集器 (GC) 会处理所有这些,因此你不必这样做。

问题是天下没有免费的午餐,收集过程本身会导致性能损失,所以你真的不希望 GC 一直收集,那么你就应该尽量避免这种情况。

避免不必要的装箱和拆箱

装箱和拆箱——就像垃圾收集——在性能方面是昂贵的过程。因此,我们希望避免不必要地包含它们。

装箱就像创建一个引用类型的框并在其中放入一个值类型的值。换句话说,它包括将值类型转换为“对象”或此值类型实现的接口类型。拆箱正好相反——它打开盒子并从里面提取值类型。

然而,装箱和拆箱本身就是昂贵的过程。除此之外,当装箱一个值时,就会在堆上创建另一个对象,这会给 GC 带来额外的压力。

那么,如何避免装箱和拆箱呢?

通常,可以通过避免 .NET(1.0 版)中早于泛型的旧 API 来实现这一点,因此必须依赖于使用对象类型。例如,更喜欢 System.Collections.Generic.List 之类的通用集合,而不是 System.Collections.ArrayList 之类的集合。

  • 装箱对于将小值类型视为引用类型非常有效,并且可以简化你的编码过程,但会以性能为代价。
  • 避免使用依赖于对象类型的旧 API。

总结

本文介绍了一些C#技巧,这些方法可以使C#程序消耗更少的内存,从而达到优化性能的目的。

相关文章

标签: asp.net  CSharp  代码性能  优化  using块  
x
  • 站长推荐
/* 左侧显示文章内容目录 */