什么是“开销”?


149

我是计算机科学专业的学生,​​在程序和排序方面,我经常听到“开销”一词。这到底是什么意思?


27
您需要做多少“额外的东西”才能得到一些东西。例如,如果为了打印“ Hello World”而不得不加载一个37类的项目,我会认为这会产生很多开销。
scunliffe

1
@ doug65536其实是另一回事。=)
福泽由纪夫(Yukio Fukuzawa

Answers:


177

这是设置操作所需的资源。它看起来似乎无关,但有必要。

就像当您需要去某个地方时,您可能需要汽车。但是,要开车沿着街道行驶,将会有很多开销,因此您可能要走路。但是,如果您要在全国范围内旅行,这笔开销是值得的。

在计算机科学中,有时我们会因为没有更好的方法而开车上街,或者“学习如何走路”不值得我们花时间。


84
类似的比喻会飞起来。飞机比汽车快得多,但是机场值机,安全等方面的开销使汽车成为距离较短的更好的选择。
FogleBird 2010年

s / drive / go /((如果您需要开车去某个地方,通常不会决定走路...
RCIX 2010年

1
@ inf3rno具有讽刺意味?我们怎么去我们的车?我们走。而且我们可以完全步行到我们的汽车。即使距离我们的车近,我们也无法步行。
corsiKa 2014年

如果我要说我编写了开销较低的Java代码,那么您将如何用“设置操作所需的资源”的定义来解释这一点。我的代码不需要太多设置吗?
committedandroider

好吧,您必须打开计算机或服务器,必须加载操作系统和所有驱动程序,必须启动Java进程,必须打开JVM,必须加载所有类,必须将IO缓冲区同步到控制台,以便您可以进行“ hello world”操作。但请告诉我更多有关低开销编码的信息。
corsiKa

40

这个词的含义可能因上下文而有很大差异。通常,使用的是资源(通常是内存和CPU时间),它们不会直接对预期结果产生影响,但是所使用的技术或方法需要这些资源。例子:

  • 协议开销:以太网帧,IP数据包和TCP段都具有标头,TCP连接需要握手数据包。因此,您不能使用硬件能够用于实际数据的全部带宽。您可以通过使用更大的数据包大小来减少开销,并且UDP具有较小的标头且没有握手。
  • 数据结构的内存开销:链表的每个元素至少需要一个指针。如果元素的大小与指针的大小相同,则意味着内存开销为50%,而数组的开销可能为0%。
  • 方法调用的开销:一个精心设计的程序被分解为许多简短的方法。但是每个方法调用都需要设置一个堆栈框架,复制参数和一个返回地址。与在单个整体功能中执行所有操作的程序相比,这表示CPU开销。当然,增加的可维护性使其非常值得,但是在某些情况下,过多的方法调用可能会对性能产生重大影响。

在所有这些示例中,听起来这个词都具有相同的含义(需要执行任务,但并不总是与直接执行任务有关)
RCIX 2010年

有关数据结构的内存开销:对于大多数内存分配器,情况甚至更糟。malloc由于分配器(假定为经典的32位计算机)由块的大小加上保护值组成,因此返回的每个值都有8个字节的内置开销。而这甚至还没有考虑分配粒度。因此,单链接的简单4字节整数列表将产生75%的开销。数组要好得多(除非您需要在中间快速插入),因为它们可以有一次开销(如果数组不是动态分配的,则开销更少)。
多纳研究员2010年

19

您很累,无法做更多的工作。你吃东西 花在寻找食物,获取食物和实际食用食物上的能量消耗着能量,而且是开销!

开销是为了完成任务而浪费的东西。目标是使开销非常小。

在计算机科学中,您可以说要打印一个数字,这就是您的任务。但是存储数字,设置显示器以打印它以及调用例程以打印它,然后从变量访问数字都是开销。


17

维基百科覆盖了我们

在计算机科学中,开销通常被认为是达到特定目标所需的多余或间接的计算时间,内存,带宽或其他资源的任意组合。这是工程间接费用的特例。


4
但是,如果没有,您将修复WikiPedia,然后在此处发布相同的帖子。
SamGoody 2011年

11

开销通常涉及不同编程算法占用的额外资源(内存,处理器,时间等)数量。

例如,插入到平衡二叉树中的开销可能比同一插入简单链表中的开销大得多(插入将花费更长的时间,使用更多的处理能力来平衡树,这导致更长的操作时间用户)。


5

对于程序员而言,开销是指代码在给定平台上的给定输入数据集上运行时,代码所消耗的那些系统资源。通常,该术语用于比较不同的实现或可能的实现的上下文中。

例如,我们可能会说,一种特定的方法可能会导致相当大的CPU开销,而另一种可能会导致更多的内存开销,而另一种可能会加权网络开销(例如,需要外部依赖)。

让我们举一个具体的例子:计算一组数字的平均值(算术平均值)。

显而易见的方法是循环输入,保持运行总计和计数。当遇到最后一个数字时(通过“文件末尾” EOF发出信号,或者通过某些哨兵值,或者通过某种GUI界面,等等),我们只需将总数除以输入数即可。

这种方法几乎不占用CPU,内存或其他资源的开销。(这是一项琐碎的任务)。

另一种可能的方法是将输入“混入”列表。遍历列表以计算总和,然后将其除以列表中有效项目的数量。

相比之下,这种方法可能会导致任意数量的内存开销。

在一个特别糟糕的实现中,我们可能使用递归执行求和运算,但没有尾消除。现在,除了清单中的内存开销外,我们还引入了堆栈开销(这是一种不同的内存,通常比其他形式的内存更有限的资源)。

另一种(可能更荒谬的)方法是将所有输入发布到RDBMS中的某些SQL表中。然后只需在该表的该列上调用SQL SUM函数。这会将我们的本地内存开销转移到其他服务器上,并导致网络开销和对我们执行的外部依赖性。(请注意,远程服务器可能有也可能没有与此任务相关的任何特定内存开销,例如,它可能会将所有值立即推送到存储中)。

假设地考虑在某种集群上实施(可能使数万亿值的平均值可行)。在这种情况下,值的任何必要编码和分配(将它们映射到节点)以及结果的收集/整理(归约)将被算作开销。

我们还可以讨论程序员自身代码以外的因素所引起的开销。例如,为32或64位处理器编译某些代码可能会比在旧的8位或16位体系结构上看到的开销更大。这可能涉及较大的内存开销(对齐问题)或CPU开销(其中CPU被迫调整位顺序或使用了未对齐的指令等)或两者兼而有之。

请注意,您的代码及其库等占用的磁盘空间通常不称为“开销”,而称为“占用空间”。同样,程序消耗的基本内存(不考虑其正在处理的任何数据集)也称为“内存”。


3

开销仅仅是程序执行中更多的时间消耗。例子; 当我们调用一个函数并将其控件传递到定义它的位置,然后执行它的主体时,这意味着我们使我们的CPU运行了一个很长的过程(首先将控件传递到内存中的其他位置,然后在其中执行,然后再执行将控件传递回原来的位置),因此需要花费大量的执行时间,因此会产生开销。我们的目标是通过在函数定义和调用期间使用内联来减少此开销,该内联将在函数调用时复制函数的内容,因此我们不将控件传递到其他位置,而是在一行中继续执行程序,因此是内联。


2

您可以使用字典。定义是相同的。但是为节省您的时间,开销是完成生产性工作所需的工作。例如,一种算法可以运行并完成有用的工作,但是需要内存来完成其工作。这种内存分配需要时间,并且与完成的工作没有直接关系,因此会产生开销。


1

您可以检查Wikipedia。但主要是在使用更多操作或资源时。就像您熟悉.NET一样,您可以拥有值类型和引用类型。引用类型具有内存开销,因为它们比值类型需要更多的内存。


1

开销的一个具体示例是“本地”过程调用和“远程”过程调用之间的区别。

例如,对于经典的RPC(以及许多其他远程框架,例如EJB),无论是本地调用,内存调用还是分布式网络调用,函数或方法调用对编码员而言都是相同的。

例如:

service.function(param1, param2);

这是普通方法还是远程方法?从这里所见,您无法分辨。

但是您可以想象两个调用之间执行时间的差异是巨大的。

因此,虽然核心实现将“花费相同”,但所涉及的“开销”却大不相同。


1

将开销视为管理线程并在其中进行协调所需的时间。如果线程没有足够的任务要做,那将是一个负担。在这种情况下,开销开销可以通过使用线程来节省时间,并且代码比顺序代码花费更多的时间。


By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.