任何小型数据库处理都可以通过Python/Perl/...脚本轻松解决,该脚本使用库和/甚至语言本身中的实用程序。但是,在性能方面,人们倾向于使用C/C ++/低级语言。根据需求量身定制代码的可能性似乎是使这些语言如此吸引人BigData的原因 - 无论是关于内存管理,并行性,磁盘访问还是低级优化(通过C/C ++级别的组装构造)。

当然,这样的好处不会没有成本:编写代码,有时甚至是 重新发明轮子, ,可能非常昂贵/厌倦。尽管有很多可用的库,但人们倾向于在需要时自己编写代码 授予 表现。什么 禁用 处理大型数据库时使用库的性能断言?

例如,考虑不断爬网的企业,并解析收集的数据。对于每个滑动窗口,在提取的数据上运行不同的数据挖掘算法。为什么开发人员会使用可用的库/框架(无论是用于爬网,文本处理和数据挖掘)抛弃?使用已经实施的东西不仅会减轻编码整个过程的负担,而且还可以节省大量时间。

一枪:

  • 是什么使自己编写代码 保证 性能?
  • 为什么 有风险 在您必须依靠框架/库时 保证 高性能?
有帮助吗?

解决方案

在一遍又一遍地进行重写游戏(仍然这样做)之后,我的直接反应是 适应性.

尽管框架和库有一个巨大的武器库(可能是可互解的)标准任务例程,但它们的框架属性经常(总是?)都会放置快捷方式。实际上,大多数框架都有某种核心基础架构,围绕该基础层面实现了基本功能的核心层。更具体的功能可以利用基本层,并将其放置在核心周围的第二层中。

现在,通过快捷方式,我的意思是在不使用核心的情况下直接从第二层例程到另一层例程。典型的示例(来自我的域)将是时间戳:您有某种时间戳的数据源。到目前为止,工作只是将数据从电线上读取并将其传递到核心,以便您的其他代码可以在其上盛宴。

现在,您的行业更改了默认时间戳格式,这是一个充分的理由(就我而言,从UNIX时间到GPS时间)。除非您的框架是特定于行业的,否则他们不太可能愿意改变时间的核心表示,因此您最终会使用一个框架 几乎 做你想要的。每次您访问数据时,都必须先将其转换为行业时段,并且每次您要修改它时,都必须将其转换回核心认为适当的任何东西。没有双转换,您无法直接将数据从源到水槽直接移交。

这是您手工制作的框架将发光的地方,这只是一个小的变化,您正在为现实世界建模,而所有其他(非行业)框架现在将具有性能劣势。

随着时间的流逝,现实世界与模型之间的差异将加起来。有了现成的框架,您很快就会面临以下问题:我如何代表 thisthat 或如何制作常规 X 接受/生产 Y.

到目前为止,这与C/C ++无关。但是,如果由于某种原因无法更改框架,即您确实必须使用双重转换数据才能从一端转到另一端,那么您通常会采用最小化额外开销的东西。就我而言,最好将tai-> utc或utc-> tai转换器留给RAW C(或FPGA)。没有可能的优雅,也没有深刻的智能数据结构,这使问题变得琐碎。这只是一个无聊的开关语句,为什么不使用编译器擅长确切优化的语言呢?

其他提示

我认为当性能是问题时,每个人都不会触手可及。

编写低级代码的优点是使用更少的CPU周期,有时会减少内存。但是我会注意到,更高级别的语言可以呼唤到低级语言,并确实可以获得一些价值。 Python和JVM语言可以做到这一点。

数据科学家使用桌面上的Scikit-Learn使用,已经在呼吁大量优化的本机例程进行数字处理。编写新代码的速度没有意义。

在分布式的“大数据”上下文中,您通常会在数据移动上瓶颈:网络传输和I/O。本机代码无济于事。有帮助的不是编写相同的代码以更快地运行,而是编写更智能的代码。

与C/C ++相比,高级语言将使您在给定数量的开发人员时间内实现更复杂的分布式算法。在大规模上,具有更好数据移动的智能算法将击败愚蠢的本地代码。

通常,开发人员时间和错误的成本负载比新硬件更大。高级开发人员的一年时间可能满是200万美元。一年多的时间也租了数百台价值计算时间的服务器。在大多数情况下,要优化更多的硬件可能是没有意义的。

我不明白有关“授予”和“禁用”和“断言”的后续行动吗?

众所周知,在数字世界中,有许多方法可以完成相同的工作 /获得预期的结果。

代码带来的责任 /风险是开发人员的肩膀。

这很小,但我猜是.NET World的一个非常有用的例子。

因此,许多.NET开发人员使用内置的二进制阅读器 - 二进制作者在其数据序列化上进行性能 /获得对流程的控制。

这是该框架内置的binarywriter类内置的csharp源代码'一个超载写入方法之一:

// Writes a boolean to this stream. A single byte is written to the stream
// with the value 0 representing false or the value 1 representing true.
// 
public virtual void Write(bool value) 
{
     //_buffer is a byte array which declared in ctor / init codes of the class
    _buffer = ((byte) (value? 1:0));

    //OutStream is the stream instance which BinaryWriter Writes the value(s) into it.
    OutStream.WriteByte(_buffer[0]);
}

如您所见,可以编写此方法,而无需将额外分配给_buffer变量:

public virtual void Write(bool value) 
{
    OutStream.WriteByte((byte) (value ? 1 : 0));
}

如果不分配我们可以获得很少的毫秒。这几毫秒可以接受为“几乎没有”,但是如果有数千篇写作(即服务器过程中)怎么办?

让我们假设“很少”是2(毫秒),而数千个实例仅为2.000。这意味着4秒的过程时间更长。

如果我们继续从.NET进行对象,并且您可以检查MSDN的BCL- .NET级库库的源代码 - 您可以看到开发人员决定的大量性能丢失。

BCL源的任何点是正常的,您会看到开发人员决定使用()或foreach()循环,该循环可以在其代码中更快地实现()循环。

这个小的收益为我们提供了总表现。

如果我们返回到binarywriter.write()方法。

实际上,将额外的分配给_Buffer实现不是开发人员的错误。.这完全决定“保持安全”!

假设我们决定不使用_ buffer并决定实现第二种方法。连接丢失..原因是我们尝试在没有任何检查和控制机制的情况下发送所有数据。当连接丢失时,服务器和客户端都不知道已完成的数据是否已完成。

如果开发人员决定“保持安全”,那么通常意味着性能成本取决于实施“保持安全”机制。

但是,如果开发人员决定“冒险,获得绩效”,这也不是错误。

并注意:商业图书馆开发人员总是试图保持安全,因为他们不知道代码将在哪里使用。

从程序员的角度来看,框架很少将目标作为最高优先级。如果您的图书馆将被广泛利用,那么人们可能重视的东西是易用性,灵活性和可靠性。

性能通常在次要竞争库中价值。 “ X库更好,因为它更快。”即使那样,这些图书馆也经常将最佳解决方案换成可以广泛利用的解决方案。

通过使用任何框架,您本质上冒险存在更快的解决方案。我可能会说,几乎总是存在一个更快的解决方案。

自己写东西并不是表现的保证,但是如果您知道自己在做什么并且有相当有限的要求,则可以提供帮助。

一个例子可能是JSON解析。有一百个库,用于多种语言,可以将JSON变成引用的对象,反之亦然。我知道一个在CPU寄存器中都可以完成的实现。它比所有其他解析器都要快,但是它也非常有限,并且限制会根据您正在使用的CPU而有所不同。

建立高性能环境特定的JSON解析器的任务是一个好主意吗?我将利用100分之99倍的受人尊敬的图书馆。在一个单独的实例中,一些额外的CPU周期乘以一百万个迭代,这将使开发时间值得。

许可以下: CC-BY-SA归因
scroll top