传输原始数据,如 int、float-tuple:更有效地解析字符串或转换为字节数组?

Transmitting primitive data such as an int,float-tuple: More efficient to parse strings or convert to byte array?

当做大量的MapReduce操作时,我希望传输的数据有尽可能少的开销。我目前需要传输的很多东西之一是 (int,float) 元组,等等。我目前正在尝试在两种传输方式之间进行选择:

  1. 序列化为字符串,例如“4,3.4”。如果我使用 ASCII-US,我猜测传输对象的大小将因此只是字符串形式所需的字符数量,即如果我的整数很长或者我的浮点数很精确,那么对象可能会变得很大。

  2. 序列化为字节数组:int使用4个字节,float使用4个字节。这样我就会一直使用 8 个字节。在特殊情况下我可以少用字符串,但我猜测字符串方式平均来说会更贵。

因此我目前倾向于第二种选择,虽然转换比仅仅序列化为字符串稍微复杂一点,但它应该更有效率,对吧?

您可以使用ASCII或UTF-8格式将数据转换为字节。

只需将字符串转换为字节数组并将格式传递为 ASCII/UTF-8 我会推荐 UTF-8,因为它比 ASCII 支持更多的特殊字符。

String s = "some text here";
byte[] b = s.getBytes("UTF-8");

通过反序列化,您可以轻松地将字节数组转换为字符串。

这是一个比较复杂的问题。

  • 一方面,将数字从二进制格式转换为文本格式……并返回的计算量(相对)很大。转换为十进制特别昂贵,因为转换涉及重复除法/乘以 10。

  • 另一方面,如果数据值(平均)较小,则文本表示在编码时可能(平均)占用更少的字节。根据网络的端到端速度和延迟(包括 NIC、虚拟化等),较小的在线表示可能会导致更大的吞吐量。

  • 另一方面,如果通信成本在整个计算中只占微不足道的一部分,那么这将毫无意义。

我的建议是:

  1. 提防过早优化!
  2. 在您的环境中对编码+传输+解码的两种备选方案(二进制和文本)进行基准测试。确保您使用的测试数据是您实际数据的典型数据。
  3. 对整个应用程序进行基准测试。 (这假设您注意了第一点!)
  4. 确定二进制表示与文本表示的差异是否会对完整应用程序在真实数据上的整体性能产生显着差异。
  5. 重写代码...如果您的测量等告诉您这是值得的。

注意:如果测量告诉您二进制与文本之间的差异对于您的应用程序来说实际上很重要,那么可能表明您的计算花费了太多时间进行通信与计算。看看您是否可以减少 数量 的通信,这将是值得的;例如通过更改计算的粒度或正在移动的数据量。


终于...

When doing a lot of MapReduce operations, I'd like the data that is transmitted to have as little overhead as possible.

这不应该是你的目标。目标应该是:

  • 使应用程序作为一个整体足够快以满足性能要求。
  • 优化开发人员时间,不要试图达到超出实际要求的性能。

像 "as fast as possible" 或 "as efficiently as possible" 或 "as small as possible" 这样的目标可能是危险的努力消耗。你应该尽量避免它们。