boolean []与BitSet:哪个更有效?

时间:2009-03-03 05:40:43

标签: java arrays performance memory bitsets

在内存和CPU使用方面更有效 - 一组boolean s还是BitSet?不使用特定的BitSet方法,只对数组进行get / set / clear(==,=,Arrays.fill)。

8 个答案:

答案 0 :(得分:39)

  • Boolean[]每个布尔值使用大约4-20个字节。
  • boolean[]每个布尔值使用大约1个字节。
  • BitSet每个布尔值使用大约1位。

内存大小可能不是问题,在这种情况下boolean []可能更容易编码。

答案 1 :(得分:36)

从使用Sun JDK 1.6计算素数的一些基准测试(最好的10次迭代预热,为JIT编译器提供机会,并排除随机调度延迟,Core 2 Duo T5600 1.83GHz):

除了非常小的尺寸外,BitSet比boolean []更有效。数组中的每个布尔值都需要一个字节。来自runtime.freeMemory()的数字对于BitSet来说有点混乱,但更少。

boolean []的CPU效率更高,除了非常大的大小,它们大约是偶数。例如,对于大小为100万的布尔[]大约快四倍(例如6ms对27ms),十亿和一亿大约是偶数。

答案 2 :(得分:4)

问题的左侧字段,但如果存储是一个问题,您可能需要查看Huffman compression。例如,00000001可以按频率压缩到相当于{(7)0, (1)1}的值。更“随机化”的字符串00111010将需要更复杂的表示,例如{(2)0, (3)1, (1)0, (1)1, (1)0},占用更多空间。根据位数据的结构,除了BitSet之外,您可以从其使用中获得一些存储优势。

答案 3 :(得分:3)

一如既往地依赖。 是BitSet的内存效率更高,但只要你需要多线程访问,boolean []可能是更好的选择。例如,对于计算素数,您只需将布尔值设置为true,因此您实际上不需要同步。 Hans Boehm已经写了一些关于此的论文,同样的技术可用于标记图中的节点。

答案 4 :(得分:3)

至于内存,BitSet的文档具有非常明确的含义。特别是:

  

每个位集都有一个当前大小,即空间位数   目前由位集使用。请注意,大小与   实现一个位集,因此它可能会随着实现而改变。该   位集的长度与位集的逻辑长度有关,并且是   独立于实施而定义。

Java库类的源代码是公开可用的,可以轻松地check this for themselves。特别是:

The internal field corresponding to the serialField "bits".
89 
90     private long[] words;

至于速度;这取决于一个人在做什么。一般来说,不要提前考虑速度;使用任何工具在语义上最有意义,并导致最清晰的代码。仅在观察到性能要求未得到满足并确定瓶颈后才进行优化。

来到SO并询问A是否比B快,这有很多原因,包括但不限于:

  1. 这取决于应用程序,没有人通常可以访问。在它正在使用的上下文中分析和分析它。确保它是一个实际上值得优化的瓶颈。
  2. 关于速度问题的这类问题通常表明OP认为他们关心效率但不愿意描述并且没有定义性能要求。在表面下,这通常是一个红旗,OP正朝着错误的道路前进。
  3. 我知道这是一个老问题,但最近出现了;我相信这值得补充。

答案 5 :(得分:2)

在这里您可以看到将boolean [] []三角矩阵与BitSet []三角矩阵进行比较的内存/时间基准。

我创建,设置和读取(size *(size-1)/ 2)值并比较内存使用情况和时间...

enter image description here

enter image description here

希望获得帮助...

这是代码...(只是一个很脏的测试代码,对不起;)

import java.util.BitSet;
import java.util.Date;

public class BooleanBitSetProfiler {

    Runtime runtime;
    int sum = 0;
    public void doIt() {

        runtime = Runtime.getRuntime();
        long[][] bitsetMatrix = new long[30][2];
        long[][] booleanMatrix = new long[30][2];
        int size = 1000;
        for (int i = 0; i < booleanMatrix.length; i++) {
            booleanMatrix[i] = testBooleanMatrix(size);
            bitsetMatrix[i] = testBitSet(size);
            size += 2000;
        }
        int debug = 1;
        for (int j = 0; j < booleanMatrix.length; j++){
            System.out.print(booleanMatrix[j][0] + ";");
        }
        System.out.println();
        for (int j = 0; j < booleanMatrix.length; j++){
            System.out.print(booleanMatrix[j][1] + ";");
        }
        System.out.println();
        for (int j = 0; j < bitsetMatrix.length; j++){
            System.out.print(bitsetMatrix[j][0] + ";");
        }
        System.out.println();
        for (int j = 0; j < bitsetMatrix.length; j++){
            System.out.print(bitsetMatrix[j][1] + ";");
        }
        System.out.println();
    }

    private long memory () {
        return runtime.totalMemory() - runtime.freeMemory();
    }
    private long[] testBooleanMatrix(int size) {
        runtime.gc();
        long startTime = new Date().getTime();
        long startMemory = memory();
        boolean[][] matrix = new boolean[size][];
        for (int i = 0; i < size; i++) {
            matrix[i] = new boolean[size - i - 1];
        }
        long creationMemory = memory();
        long creationTime = new Date().getTime();
        for (int i = 0; i < size; i++)  {
            for (int j = 0; j < matrix[i].length; j++) {
                matrix[i][j] = i % 2 == 0;
            }
        }
        long setMemory = memory();
        long setTime = new Date().getTime();
        for (int i = 0; i < size; i++)  {
            for (int j = 0; j < matrix[i].length; j++) {
                if (matrix[i][j]) sum++;
            }
        }
        long readTime = new Date().getTime();
        System.out.println("Boolean[][] (size " + size + ")");
        System.out.println("Creation memory " + printMem(creationMemory-startMemory) + ", set memory " + printMem(setMemory-startMemory));
        System.out.println("Creation time " + printTime(creationTime-startTime) + ", set time " + printTime(setTime - creationTime) + " read time " + printTime(readTime - setTime) + "\n");
        runtime.gc();
        return new long[]{(setMemory-startMemory)/(1024*1024), (readTime-startTime)};
    }
    private long[] testBitSet(int size) {
        runtime.gc();
        long startTime = new Date().getTime();
        long startMemory = memory();
        BitSet[] matrix = new BitSet[size];
        for (int i = 0; i < size; i++) {
            matrix[i] = new BitSet(size - i - 1);
        }
        long creationMemory = memory();
        long creationTime = new Date().getTime();
        for (int i = 0; i < size; i++)  {
            for (int j = 0; j < matrix[i].size(); j++) {
                matrix[i].set(j, (i % 2 == 0));
            }
        }
        long setMemory = memory();
        long setTime = new Date().getTime();
        for (int i = 0; i < size; i++)  {
            for (int j = 0; j < matrix[i].size(); j++) {
                if (matrix[i].get(j)) sum++;
            }
        }
        long readTime = new Date().getTime();
        System.out.println("BitSet[] (size " + size + ")");
        System.out.println("Creation memory " + printMem(creationMemory-startMemory) + ", set memory " + printMem(setMemory-startMemory));
        System.out.println("Creation time " + printTime(creationTime-startTime) + ", set time " + printTime(setTime - creationTime) + " read time " + printTime(readTime - setTime) + "\n");
        runtime.gc();
        return new long[]{(setMemory-startMemory)/(1024*1024), (readTime-startTime)};
    }

    private String printMem(long mem) {
        mem = mem / (1024*1024);
        return mem + "MB";
    }
    private String printTime(long milis) {
        int seconds = (int) (milis / 1000);
        milis = milis % 1000;
        return seconds > 0 ? seconds + "s " + milis + "ms" : milis + "ms";
    }
}

答案 6 :(得分:1)

从Java到CPU完全是特定于VM的。例如,它曾经是一个布尔值实际上是作为32位值实现的(很可能今天也是如此)。

除非你知道它最重要,否则你最好把代码写清楚,对它进行分析,然后修复那些速度慢或消耗大量内存的部分。

你可以随时去做。例如,我曾经决定不在字符串上调用.intern(),因为当我在分析器中运行代码时,它减慢了太多(尽管使用更少的内存)。

答案 7 :(得分:-1)

我相信BitSet具有更高的内存和CPU效率,它可以在内部将这些位打包成int,long或本机数据类型,而boolean []则需要每个数据位一个字节。另外,如果你要使用其他方法(和,或等),你会发现BitSet效率更高,因为不需要遍历数组的每个元素;改为使用按位数学。