我可以使用哪些资源来学习分析/优化?

发布于 2024-07-14 02:19:40 字数 194 浏览 4 评论 0原文

我刚刚继承了一个 C# 项目,该项目运行速度很慢,必须开始优化它。 我首先想做的是更多地了解分析/优化,因为我以前不需要这样做。 所以问题是我从哪里开始,我可以阅读哪些书籍/博客/文章?

我确实知道 .net 分析器,例如 ANTS 分析器等,但我不知道如何有效地使用它们。 我还没有真正使用过它,只是让它在一些示例应用程序上运行来处理输出。

I just inherited a C# project that runs way to slow and will have to start optimizing it. What I wanted to do first is learn a little more about profiling/optimizing since I didnt have to do it before. So the question is where do I start, what books/blogs/articels can I read?

I do know OF the .net profilers like ANTS profiler and so on, but I have no idea how to use them efficiently. I have not really used it, just let it run on a few sample apps to play around with the output.

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

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

发布评论

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

评论(11

只为守护你 2024-07-21 02:19:40

优化代码有两个步骤。

首先,您需要找出慢的原因。 这就是分析,正如您可能猜到的,分析器通常用于此目的。 大多数分析器通常都易于使用。 您通过探查器运行您的应用程序,当它终止时,探查器将显示每个函数花费了多少时间,独占(此函数不计算从该函数调用的函数中花费的时间)以及包含(此函数中花费的时间)函数,包括子函数调用)。

换句话说,你会得到一个很大的调用树,你只需要寻找大数字。 通常,很少有函数消耗超过 10% 的执行时间。 因此,找到这些,您就知道要优化什么。

请注意,分析器既不是必需的,也不一定是最佳方法。 一种非常简单但有效的方法是在调试器中运行程序,然后在几次准随机的时间暂停执行并查看调用堆栈。 只需执行几次此操作,您就可以很好地了解执行时间都花在哪里了。 在这个答案下发表评论的@Mike Dunlavey 在其他地方深入描述了这种方法。

但既然您知道执行时间花在哪里,那么棘手的部分就来了,如何优化代码。

当然,最有效的方法往往是高层方法。 问题一定要这样解决吗? 它是否必须得到解决? 能否提前解决该问题并将结果缓存起来,以便在应用程序的其余部分需要时立即交付?
有没有更有效的算法来解决问题?

如果您可以应用此类高级优化,请执行此操作,看看是否可以充分提高性能,如果没有,请再次进行分析。

迟早,您可能必须深入研究更多低级优化。 但这是一个棘手的领域。 当今的计算机非常复杂,并且从它们获得的性能并不简单。 根据上下文的不同,分支或函数调用的成本可能会有很大差异。 将两个数字相加可能需要 0 到 100 个时钟周期,具体取决于两个值是否已在 CPU 寄存器中、当时正在执行的其他操作以及许多其他因素。 因此,此级别的优化需要 (1) 充分了解 CPU 的工作原理,以及 (2) 进行大量实验和测量。 您可以轻松地进行认为更快的更改,但您需要确定,因此请衡量更改前后的性能。

有一些一般经验法则通常可以帮助指导优化:

I/O 成本高昂。 CPU 指令以纳秒的几分之一来测量。 RAM 访问时间约为数十到数百纳秒。 硬盘访问可能需要数十毫秒秒。 通常,I/O 会减慢应用程序的速度。
您的应用程序是否执行少量大型 I/O 读取(读取一个大块中的 20MB 文件),还是执行无数小读取(从一个文件读取字节 2,052 到 2073,然后从另一个文件读取几个字节)? 更少的大读取可以将 I/O 速度提高数千倍。

页面错误也涉及硬盘访问。 内存中的页面必须推送到页面文件,而调出的页面必须读回到内存中。 如果这种情况发生很多,速度就会很慢。 您能否改进数据的局部性,从而减少同时需要的页面数量? 您是否可以简单地为主机购买更多 RAM 以避免将数据分页? (一般来说,硬件很便宜。升级计算机是一种完全有效的优化 - 但要确保升级会产生影响。购买更快的计算机不会使磁盘读取速度加快很多。如果一切都适合 RAM在您的旧系统上,购买 8 倍 RAM 的系统是没有意义的)

您的数据库也依赖于硬盘驱动器访问。 那么,您可以在 RAM 中缓存更多数据,而只是偶尔将其写入数据库吗? (当然存在风险。如果应用程序崩溃会发生什么?

然后是每个人都喜欢的线程。现代 CPU 有 2 到 16 个可用的 CPU 核心。您是否全部使用它们?您会从使用它们中受益吗? 存在可以异步执行的长时间运行的操作?应用程序在单独的线程中启动操作,然后能够立即恢复正常操作,而不是阻塞直到操作完成。

是否 . 它是如何花费执行时间的?内存消耗是一个问题吗?I/O 模式是什么(硬盘驱动器和网络访问,以及任何其他类型的 I/O)?
CPU 是否一直在运转,或者是否空闲等待某些外部事件(例如 I/O 或计时器)?

然后尽可能多地了解它所运行的计算机。 了解它有哪些可用资源(CPU 缓存、多核),以及它们对性能的意义。

这一切都非常模糊,因为优化大型数据库服务器的技巧将与优化某些大型数字运算算法的技巧非常不同。

There are two steps to optimizing code.

First, you need to find out what's slow. That's profiling, and, as you might guess, a profiler is commonly used for this. Most profilers are generally straightforward to use. You run your application through a profiler, and when it terminates, the profiler will show you how much time was spent in each function, exclusive (this function without counting time spent in function called from that) as well as inclusive (time spent in this function, including child function calls).

In other words, you get a big call tree, and you just have to hunt down the big numbers. Usually, you have very few functions consuming more than 10% of the execution time. So locate these and you know what to optimize.

Note that a profiler is neither necessary nor, necessarily, the best approach. A remarkably simple, but effective, approach is to just run the program in a debugger, and, at a few quasi-random times, pause execution and look at the call stack. Do this just a couple of times, and you have a very good idea of where your execution time is being spent. @Mike Dunlavey who commented under this answer has described this approach in depth elsewhere.

But now that you know where the execution time is being spent, then comes the tricky part, how to optimize the code.

Of course, the most effective approach is often the high-level one. Does the problem have to be solved in this way? Does it have to be solved at all? Could it have been solved in advance and the result cached so it could be delivered instantly when the rest of the app needed it?
Are there more efficient algorithms for solving the problem?

If you can apply such high-level optimizations, do that, see if that improved performance sufficiently, and if not, profile again.

Sooner or later, you may have to dive into more low-level optimizations. This is tricky territory though. Today's computers are pretty complex, and the performance you get from them is not straightforward. The cost of a branch or a function call can vary widely depending on the context. Adding two numbers together may take anywhere from 0 to 100 clock cycles depending on whether both values were already in the CPU's registers, what else is being executed at the time, and a number of other factors. So optimization at this level requires (1) a good understanding of how the CPU works, and (2) lots of experimentation and measurements. You can easily make a change that you think will be faster, but you need to be sure, so measure the performance before and after the change.

There are a few general rules of thumb that can often help guide optimizations:

I/O is expensive. CPU instructions are measured in fractions of a nanosecond. RAM access is in the order of tens to hundreds of nanoseconds. A harddrive access may take tens of milliseconds. So often, I/O will be what's slowing down your application.
Does your application perform few large I/O reads (read a 20MB file in one big chunk), or countless small ones (read bytes 2,052 to 2073 from one file, then read a couple of bytes from another file)? Fewer large reads can speed your I/O up by a factor of several thousand.

Pagefaults involve harddrive accesses too. In-memory pages have to be pushed to the pagefile, and paged-out ones have to be read back into memory. If this happens a lot, it's going to be slow. can you improve the locality of your data so fewer pages will be needed at the same time? Can you simply buy more RAM for the host computer to avoid having to page data out? (As a general rule, hardware is cheap. Upgrading the computer is a perfectly valid optimization - but make sure the upgrade will make a difference. Disk reads won't be a lot faster by buying a faster computer. And if everything fits into RAM on your old system, there's no point in buying one with 8 times as much RAM)

Your database relies on harddrive accesses too. So can you get away with caching more data in RAM, and only occasionally writing it out to the database? (Of course there's a risk there. What happens if the application crashes?

And then there's everyone favorite, threading. A modern CPU has anywhere from 2 to 16 CPU cores available. Are you using them all? Would you benefit from using them? Are there long-running operations that can be executed asynchronously? The application starts the operation in a separate thread, and is then able to resume normal operation instantly, rather than blocking until the operation is complete.

So basically, use the profiler to understand your application. How does it spend its execution time, where is it being spent? Is memory consumption a problem? What are the I/O patterns (both harddrive and network accesses, as well as any other kind of I/O)?
Is the CPU just churning away all the time, or is it idle waiting for some external events, such as I/O or timers?

And then understand as much as possible about the computer it's running on. Understand what resources it has available (CPU cache, multiple cores), and what each of them means for performance.

This is all pretty vague, because the tricks to optimizing a big database server are going to be very different from what you'd do to optimize some big number-crunching algorithm.

帥小哥 2024-07-21 02:19:40

我正在学习本科课程(一个主题是性能分析),推荐的文本是 计算机系统性能分析的艺术:实验设计、测量、模拟和建模技术。 这是关于这个主题的圣经,可能有点矫枉过正。

I'm taking an undergraduate course (one topic is Performance Analysis) and the recommended text is The Art of Computer Systems Performance Analysis: Techniques for Experimental Design, Measurement, Simulation, and Modeling. It's something of a bible on the subject and might be a bit overkill.

↙厌世 2024-07-21 02:19:40

如果您熟悉并且已经购买了 ANTS(一个非常好的分析器),那么请访问 这里为您提供快速入门和运行教程。

If you are familiar with and have already purchased ANTS (a very fine profiler) then go here for a quick tutorial to get you up and running.

落墨 2024-07-21 02:19:40

如果您有 Visual Studio Team System,我建议使用它包含的探查器。
它位于“分析->分析器”下
使用这个分析器非常简单。 你可以直接潜入其中,看看你能从中得到什么。 亲自实践比您将要阅读的任何文章或书籍都要好。

只需点击几下即可轻松找到前几个瓶颈。 解决它们可能有点棘手,但同样,优化代码只是一个问题或实践和经验。

If you have Visual Studio Team System I suggest using the Profiler it contains.
It is under "Analyze->Profiler"
Using this profiler is really simple. You can just dive in and see what you make of it. Hands on practice is better than any article or book you're going to read about it.

Finding your first couple of bottlenecks is easy as just a few clicks. Solving them might be abit more tricky but again, Optimizing code is just a matter or practice and experience.

智商已欠费 2024-07-21 02:19:40

阅读 Rico Mariani 的博客。 在升职之前,他是 .Net 的主要性能调优人员。 他的博客中的旧条目有很多好的建议。 我会从接近开始的地方开始,然后按照你的方式前进。

再加上您已经找到的文章(尤其是第一篇) 应该可以帮助你开始。

Read Rico Mariani's blog. Before he was promoted, he was a major performance tuning guy for .Net. The older entries in his blog have a ton of good advice. I'd start close to the beginning and work your way forward.

That, plus the articles you've already found (especially the first one) should get you started.

相守太难 2024-07-21 02:19:40

有分析器和性能分析工具,但是当您尝试寻找/购买/安装/学习一个工具时,只需尝试一下老手的技巧...

在 IDE 下运行应用程序,当它运行缓慢时,点击“暂停”按钮,并询问它正在做什么以及为什么。 回答这个问题的最佳方法是阅读调用堆栈。

如果它比应有的速度慢几倍,比如 10 倍,则意味着它花费了 90% 的时间做一些不必要的事情,这就是您发现它这样做的概率。 如果你重复几次,你就可以尽可能准确地证实你的怀疑。

所以你不需要昂贵/流行但模糊的放大镜。

所以找到缓慢的原因并不是难事,通常有好几个。

困难的部分是,在修复了一些“容易实现的目标”之后,您可能不得不面对这样一个事实:缓慢的主要原因是过度设计。

祝你好运。

There are profilers and performance analysis tools, but while you're trying to find / buy / install / learn one, just try an old-timer's trick...

Run the app under the IDE, and while it's being sluggish, hit the "Pause" button, and ask it what it is doing, and why. The best way to answer this is by reading the call stack.

If it is several times slower than it should be, like 10 times, that means it is spending 90% of its time doing something unnecessary, and that is the probability you will catch it doing it. If you repeat this several times, you can confirm your suspicions with as much accuracy as you want.

So you don't need an expensive / popular but fuzzy magnifying glass.

So finding the reason for the slowness is not the hard part, and there are usually several.

The hard part is, after you've fixed a few "low-hanging-fruits", you will probably have to face the fact that the main reason for the slowness is over-design.

Good luck.

两相知 2024-07-21 02:19:40

我以前使用过分析器,它们可能很有帮助,但是您只需创建一个单例秒表类型类并“单击”它即可获得很多帮助(让它打印出自上次单击以来的时间以及刚刚完成的操作)花了那个时间)您认为可能有问题的方法之前和之后。

如果速度是整个应用程序的一个问题,您可能无法对此做太多的事情,但您可能可以进行一些更改......

寻找内部循环。 这些都是性能死亡。 内部循环可能是由一些简单的事情引起的,例如对链接列表进行索引,或者对基于数组的列表进行插入排序。 (有一次我有一个列表框,需要 10-20 分钟才能填充数万个条目,尽管条目太多,但最糟糕的是它通过将每个条目插入到数组列表中来对其进行排序)。

查找您基于按键进行长时间操作的情况。 这些几乎总是应该在主线程之外完成。

甚至不要考虑优化诸如类数量或实例化频率、字符串连接(循环外)、清空变量或任何其他看起来应该有帮助的愚蠢策略之类的事情。 我已经尝试了一些,但当我实际上放慢速度时,总是感觉很愚蠢,因为我在大多数情况下都不如运行时那么聪明。

I've used profilers before, they can be helpful, but you can get a lot of help just from creating a singleton stopwatch type class and "Click" it (have it print out the time since the last click and what was just done that took that time) before and after methods you think might be problematic.

If speed is a problem throughout the app, you're probably not going to be able to do too much about it, but you might be able to make a few changes...

Look for inner loops. These are performance death. An inner loop can be caused by something as simple as indexing into a linked list, or doing an insertion sort into an array-based list. (Once I had a list box that was taking 10-20 minutes to fill with tens of thousands of entries, although that's too many entries, the worst part was that it was sorting it by inserting each entry into an array list).

Look for cases where you are doing long operations based on keypresses. These should almost always be done outside the main thread.

Don't even THINK of optimizing things like numbers of classes or how often they are instantiated, string concatenation (outside of loops), nulling out variables or any of the other silly strategies that seem like they should help. I've tried a few and always ended up feeling silly when I actually slowed things down because I wasn't as smart as the runtime is at most things.

赠我空喜 2024-07-21 02:19:40

我会下载一些可用的分析工具(免费试用)并开始使用它们。

我使用了 jetbrains ,还有其他的。 (例如蚂蚁devpartnerMS 一台?atomatedqa 等)运行它们应该不会有太多问题。 他们的报告为您提供了大量信息,您只需使用这些应用程序就可以快速学习。

其中任何一项都可能对您有所帮助,并且使用这些试用版是很好的选择。 然后,您可以搁置购买该工具的决定,或者购买最有帮助/最易于使用的工具。 一般来说,它们可以节省大量时间并且物有所值,尽管有些可能很昂贵。 (当有非常好的工具花费更少的钱时,我很难使用高端的工具)

您可能会在安装和运行它们的第一天发现一些严重/主要的性能问题。 我知道我做到了。

祝你好运。

只需下载一些工具并开始运行您的应用程序。

编辑:

至于书籍和学习 - 基本上了解代码问题的最佳方法是找到糟糕的代码。 很多时候与经验丰富的开发人员进行检查会很有帮助。

举个例子:我认为 Joel 很早就写过一篇文章,说他做了类似

for (int i = 0; i < strlen(some string); i++) 的

事情,很明显你会每次调用 strlen (昂贵)循环的迭代。

在探查器告诉您时间花在哪里之后,您必须查看一些代码,看看代码是否可以通过类似的简单事情轻松修复,或者必须在算法的设计中进行更改。

I would download a few of the profiling tools available (free trials) and start using them.

I used jetbrains , and there are others. (ants for example, devpartner and a MS one?, atomatedqa, etc) You should not have too much problems running them. They have reports that give you lots of information and you can learn pretty quickly just using the applications.

Any one of them will probably help you and it is nice to use the trials. You can then either just shelve the decision to buy the tool, or buy the one(s) that was the most helpful/easiest to use. In general they are great time savers and worth the money, though some can be expensive. (I have a hard time with the ones on the upper end when there are very good tools for a lot less money)

You might find some serious/major performance issues the first day you install and run them. I know I did.

good luck.

just download some tools and start running your app.

EDIT:

As for books and learning - basically the best way to learn about problems with code is to find bad code. Many times doing inspections with experienced developers will be helpful.

as an example: I think Joel wrote an article way back about he did something like

for (int i = 0; i < strlen(some string); i++)

that is pretty obvious that you are going to call strlen (expensive) every iteration of the loop.

You'll have to look at some of the code after the profiler tells you where time is being spent and see if the code can be fixed easily with simple things like that, or changes have to be made in the design of the algorithms.

空气里的味道 2024-07-21 02:19:40

这对 C# 没有多大帮助,但 OS X Shark 工具(附带 Apple 的开发人员工具)是我遇到过的最好的分析工具。 使用起来几乎很有趣!

至于分析,有两种方法。 首先,您应该了解该软件。 尤其是数据结构。 除非您先了解它,否则不要开始优化。

其次,您应该测量(您似乎即将这样做)。 我几乎总是被我的直觉所误导。 我认为次要的地方是花费时间的地方。 这也意味着当您进行优化时,您始终会针对运行的一组特定测试用例进行优化。 此类案例的选择很重要。

This won't help you much on C#, but the OS X Shark tools (comes with the developer tools from Apple) are the Best profiling tools I've come accross. Almost fun to use!

As to profiling, there's two ways of approach. First, you should understand the software. The data structures especially. Don't start optimizing unless you understand it first.

Second, you shall measure (which seems you're about to do). I've been mislead by my gut instinct almost always; places I would regard as secondary are the time takers. This also means when you're optimizing you're always optimizing for a certain set of test cases you run. The selection of such cases is important.

桜花祭 2024-07-21 02:19:40

您已经用 Profiler 切中要害了。 所有这些,至少是我使用过的,都遵循相同的基本方法。 您选择可执行文件,然后运行该应用程序。

您对输出所做的就是找到花费最多时间的方法。这还不是全部,但是您需要一种学习如何优化代码的好方法,因此长时间运行的例程是一个很好的起点。 您提到的 ANTS 将默认显示长时间运行的例程,大多数(如果不是全部)其他例程也是如此。

您可以排除容器方法,例如 Main(),除非其中有大量代码(不太可能)。

一般来说,我发现大部分浪费在三个方面:

  1. 循环
  2. 递归
  3. 网络延迟

对于数据库而言,如果您还会分析数据库,则第 3 区通常很容易发现,因为您将看到命中数。 减少网络延迟的最佳方法,无论是否是数据库(例如服务调用),都是通过消息而不是 CRUD 进行通信。 不要一次查询每个表。 不幸的是,该解决方案通常需要删除许多公共数据层的一部分。

递归和循环是非常相似的问题。 如果你想物有所值,请先打内循环。

在 .NET 中,您还可以通过学习基本 IL 并通过 Reflector 等工具检查应用程序的 IL 来了解很多有关优化的知识。 如果这不是你工作描述的主要部分,或者你可能想在未来的职业生涯中做的事情,那就有点浪费时间了。 作为一名消防员薪水很高,但作为一名仅进行维护的编码员可能会非常无聊。

关于优化和分析 .NET 应用程序的书籍只有几本。 标题中有优化的那个。 .NET 的调试书有一些关于 Profiling 的信息,但不是很深入。 然而,这是一本值得阅读的优化书籍,因为许多导致错误的问题也会出现在您的优化之旅中。

You have already hit the nail on the head with the Profiler. All of them, at least all that I have used, follow the same basic methodology. You select the executable and then run the application.

What you do with the output is find the methods that take the most time.l This is not all, but you asked for a good way to learn how to optimize code, so the long running routines are a good place to start. ANTS, which you mentioned, will default to showing long running routines, as will most, if not all, others.

You can exclude the container methods, like Main(), unless you have a lot of code in there (unlikely).

In general, I find most waste in three areas:

  1. Loops
  2. Recursion
  3. Network latency

Area #3, for the database, is generally easy to spot if you will also profile your database, as you will see the number of hits. The best way to reduce network latency, whether database or not (service calls, for example), is to communicate in messages rather than CRUD. Don't query each table, one at a time. Unfortunately, the solution often requires canning parts of many common data layers.

Recursion and loops are very similar problems. If you want bang for the buck, hit the inner loop first.

In .NET, you can also learn a lot about optimization by learning basic IL and examining the IL of your applications through tools like Reflector. A bit of a waste of time, if this is not the major portion of your job description, or something you are likely to want to spend your future career doing. Being a fireman pays well, but being a maintenance only coder can be very boring.

There are only a couple of books on optimizing and profiling .NET applications. The one that has optimzing in the title. The debugging book for .NET has some info on Profiling, but it is not very deep. It is a great book to read for optimization, however, as many issues that cause bugs will also show up in your optimization trips.

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