【问题标题】:What are the most important optimizing performance best practices in C# [closed]C#中最重要的优化性能最佳实践是什么[关闭]
【发布时间】:2010-10-17 22:33:47
【问题描述】:

当我阅读this tutorial 时,我注意到以下有关在 C# 中使用结构的性能提示:

除非你需要引用类型 语义,一个更小的类 超过 16 个字节可能更有效 由系统作为结构处理。

我在 stackoverflow 中寻找了类似的问题,我发现了一些在 ADO.NetNetworkingStreams 中讨论性能最佳实践的问题,而不是关于 C#(语言)中的性能最佳实践。

我想补充一点关于使用整数类型的提示:

运行时优化性能 32 位整数类型(Int32 和 UInt32),所以使用这些类型 计数器和其他经常访问的 积分变量。

【问题讨论】:

标签: c# .net performance


【解决方案1】:

简单地说:个人资料。

每个应用程序都不同。如果这不是您的应用程序的瓶颈,花时间减少一些代码以使其“更高效”是没有意义的。另外 - 如果您没有数字来支持更改,您甚至可能会让事情变得更糟

在大多数情况下,IO 是关键,因此考虑 IO 是轻而易举的事。同上数据库访问。但除此之外:测量它。

【讨论】:

    【解决方案2】:
    1. 字符串是Immutable
    2. 了解using 语句。
    3. 了解Boxing 以及Generics 如何提供帮助。
    4. 了解Garbage Collector 的工作原理。
    5. Parallel programming 在 .Net 4.0 中
    6. 了解File IO 如何影响性能。

    Eric Lippert 经常谈论优化。我会读他的blog
    我也会看看 Jon Skeet 的 blog

    【讨论】:

    • 7:过早的优化是万恶之源。先让它工作;如果它适用于一系列附加字符串的行,那就太好了。如果这导致您想要改进的执行时间明显变慢,您可以稍后重构以使用 StringBuilder。
    • @KeithS:过早的优化是一件坏事,但使用 StringBuilder 并不仅仅针对速度问题。它还清楚地表明您打算更改您创建的字符串。对于很多设置来说,这是一个语义上合理的选择。
    【解决方案3】:

    【讨论】:

      【解决方案4】:

      不要在非异常情况下使用异常。

      【讨论】:

      • 嗯。虽然这绝对是好的做法,但它们并不会真正影响现实世界的性能。我记得很久以前,当我尝试用 Java2D 制作游戏时,我实现并发的方法是在两个线程同时尝试从同一个 ArrayList 读取时捕获异常。我们正在谈论每秒数千个异常。当您连接了调试器时,异常似乎真的很慢,但如果没有它,它们不会影响性能,除非您有一些严重的错误设计(例如基于异常的并行性..)。
      • 与 IO 的方式不同,但与无法理解字符串不可变的数量级相同!
      • Late:但我想澄清一下,异常本身并不坏。当开发人员throw 时,代码开始有异味。创建和捕获异常与任何其他执行相同。正如 Paul 所说,抛出异常会执行 Non-Local GoTo,这是控制代码流的禁忌,也会损害性能,其数量级与无法理解字符串是不可变的相同。我的意思是要说明它是 Throw 造成的伤害。不是问题。
      【解决方案5】:

      不仅在 C# 中,而且在任何鼓励您创建大量数据结构类的 OO 语言中,可能都需要一些性能调整和分析经验来学习这一点,但保持简单不仅仅是陈词滥调。

      必须尽量减少您拥有的类的数量,尽量减少数据的冗余,尤其是尽量减少使用通知式更新以尽量保持数据一致。

      如果数据结构的不同组件需要彼此保持一致,最好能够容忍暂时的不一致,而不是尝试通过通知来保持一致。

      数据结构中的许多复杂性源于一种模糊但普遍的愿望,即使其“更高效”,例如交叉链接数据结构,以便通知可以实现即时更新。这不仅会使代码变得非常复杂,导致错误,而且当您进行性能调优时,您会发现那些结构可能是最大的性能杀手。

      【讨论】:

        【解决方案6】:

        避免在循环中装箱和拆箱。

        例如,使用 List 代替 ArrayList。泛型集合不仅是类型安全的,而且在将它们与值类型一起使用时也比非泛型更快。

        【讨论】:

          【解决方案7】:

          在许多应用程序中,尤其是网络应用程序,您的应用程序大部分时间都在访问数据库。 (这不是 C# 特定的)使用分析工具来确保您没有长时间运行的数据库查询,选择好的索引,并在适当的情况下使用预加载来减少您必须发出的数据库请求的数量。这可能是提高使用数据库、C# 或其他方式的应用程序性能所能做的最重要的事情。

          【讨论】:

            【解决方案8】:

            如果您从对象“B”订阅对象“A”上的事件,请务必在“B”更改之前取消订阅“A”中“B”的事件,否则,“B”可能永远无法获得 GC 'd.

            【讨论】:

              【解决方案9】:

              在进行大量操作时,尽可能避免字符串操作(查找、.Contains("blah") 等)。我发现在可能的情况下删除此类操作后,性能得到了显着提升。

              【讨论】:

                【解决方案10】:

                我可以说出很多性能优化:

                1. String.Format / StringBuilder 用于字符串操作,因为字符串是不可变的。
                2. 继承 IDisposable 以编写您自己的代码来处理对象,这样您就可以删除非托管内存引用,并且当您只使用托管内存时也不要实现 IDisposable。
                3. 不要将本地引用设置为 null,因为它是自动完成的。
                4. 在抛出异常时不要创建新异常。使用 throw 而不是 throw ex
                5. 将大对象作为 WeakReference,使其立即可供 GC 使用。 http://www.abhisheksur.com/2010/07/garbage-collection-algorithm-with-use.html
                6. 避免装箱/拆箱。使用泛型。

                等等。

                【讨论】:

                • -1 你的一些建议是正确的,但如果没有更多的上下文,它们可能会产生误导,尤其是第 3 点和第 5 点。“不要将本地引用设置为 null”是模糊的,可能会产生误导.我想我知道你的意思,但这需要更多的解释。弱引用仅适用于极少数情况,不适用于任何大型对象。
                • 是的。我只是把分数。多一点解释是值得的。感谢您指出。
                • -1。首先,您的意思是实现 IDisposable,而不是继承。其次,我更愿意告诉开发人员永远不要实现 IDisposable,而不是将其用于他认为需要处理的代码。一般的 C# 开发人员应该了解 .NET Framework 中的每个类都是托管的。如果它处理非托管资源,它已经实现了 IDisposable。只有高级或架构师应该在手动处理非托管资源的服务边界上工作。错误地实现 IDisposable 会对性能造成巨大影响,而且大多数情况下都是不正确的。臭代码气味。
                • 另外,您将异常处理作为性能的痛点是正确的。但痛点是投掷和投掷前任。抛出是异常处理的坏部分。创建新的异常一点也不坏。同样注意:您不应该捕获无法处理的异常,因此几乎永远不会看到 throw 和 throw ex。如果您需要部分处理它,那么捕获、处理它并返回一个向消费者描述操作状态的 monad。或者,在最坏的情况下,抛出一个描述相同的自定义异常。
                猜你喜欢
                • 2011-01-22
                • 2011-11-21
                • 2014-01-29
                • 1970-01-01
                • 1970-01-01
                • 1970-01-01
                • 1970-01-01
                • 2010-09-07
                • 1970-01-01
                相关资源
                最近更新 更多