为什么BytesWritable.setSize(size)使字节空间为1.5 *大小?

时间:2013-04-11 20:04:49

标签: hadoop

我正在使用hadoop编写程序。我的问题代码如下(代码在mapper中):

byte[] tmp = new byte[2];
tmp[0] = 0x01;
tmp[1] = 0x02;
BytesWritable outputKey = new BytesWritable();
outputKey.set(tmp, 0, 2);

然而,当我在mapper中操作减速器中的键时,它让我感到惊讶:

byte[] reducerKey = key.getBytes();

reducerKey如下:

reducerKey[0] -> 0x01;
reducerKey[1] -> 0x02;
reducerKey[2] -> 0x00;

为什么我输入的tmp是2个字节的长度,但是当我得到它时,它变成3个字节的长度。

然后我读了BytesWritable.setSize(size)的源代码, 我发现了这个:

public void setSize(int size) {
 if (size > getCapacity()) {
  setCapacity(size * 3 / 2);
 }
this.size = size;}

那么当字节进入BytesWritable时,为什么数据结构为byte []创建1.5 *大小的空间?我认为这是浪费空间,因为0.5 *大小的空间是无用的。

1 个答案:

答案 0 :(得分:1)

这是一种常见的编程实践,用于分摊dynamic array调整大小的成本。

现在为什么它不是Hadoop可写的问题和良好的默认行为?

  1. 可写对象通常是单例,因为它们可以被重用。您通常希望调整它们的大小以适合最大的缓冲区。每次创建一个新的Writable,浪费时间并可以对GC施加压力。使它们比最大的已使用的缓冲区大一点是有意义的。
  2. 如果您想避免额外的空间,可以使用BytesWritable(byte[] bytes)构造函数或setCapacity。请注意,构造函数比set()更有效,因为它不必复制数据。只需要设置两个引用。