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

63 java memory arrays performance bitsets

什么在内存和CPU使用方面更有效 - 一个booleans或BitSet 数组?不使用特定的BitSet方法,只对数组进行get/set/clear(==,=,Arrays.fill).

Pet*_*rey 41

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

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

  • 请注意,BitSet中每个布尔值1位是渐近值.封面下使用了一个long [],因此它被颗粒化为64位块. (31认同)
  • 值得一提的是,通常每个值只需要4个字节的指针.因为它是缓存的.除非你明确使用new Boolean(); 但当然它不仅仅是布尔[] (3认同)
  • `Boolean[]` 每个值使用 4 或 8 个字节,但绝对不能超过 20 个字节。如果您假设应用程序为每个元素创建一个新的“Boolean”对象(尽管没有理由这样假设),那么大多数实现将需要 24 个字节用于该对象,这总共需要 4 或 8 个字节用于引用,所以总共最多可达 32 个字节。但实际上谁会这么做…… (2认同)

sta*_*lue 39

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

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

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

  • 你可以发表你的考试吗? (16认同)
  • 这是一个误导性的答案,没有测试代码和特定的上下文.我鼓励任何读这篇文章的人在这里阅读其他答案并自己思考一下他们​​的具体情况. (9认同)
  • 我怀疑一些BitSet样式操作(和,或者不是)比BitSet更快,而不是数组.值得注意哪些操作更好.标题会误导所有人再也不会使用BitSet (7认同)
  • @starblue你能解释一下为什么对于非常大的数据,“boolean[]”和“BitSet”在CPU效率上几乎相同吗?感觉“boolean[]”仍然应该更有效。 (2认同)
  • @Utku可能是缓存的一种效果,因此要访问主内存,您还需要在写入字节时执行read-update-write。请注意,“ boolean []”更快的最大字节数为100万字节,这大概是可以放入高速缓存的大小。 (2认同)

Ale*_*lds 5

您的问题有点偏左,但如果存储是一个问题,您可能需要研究Huffman compression。例如,00000001可以通过频率压缩到相当于{(7)0, (1)1}. 更“随机”的字符串00111010需要更复杂的表示,例如{(2)0, (3)1, (1)0, (1)1, (1)0},并占用更多空间。根据位数据的结构,除了BitSet.


Jas*_*n C 5

至于内存,a 的文档BitSet有非常明确的含义。尤其:

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

Java 库类的源代码是公开可用的,人们可以轻松地自行检查。尤其:

The internal field corresponding to the serialField "bits".
89 
90     private long[] words;
Run Code Online (Sandbox Code Playgroud)

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

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

  1. 这取决于应用程序,通常没有人响应该应用程序可以访问该应用程序。在使用它的上下文中分析和分析它。确保它是一个真正值得优化的瓶颈。
  2. 像这样询问速度的问题通常表明OP认为他们关心效率,但不愿意分析并且没有定义性能要求。在表面之下,这通常是一个危险信号,表明 OP 正走在错误的道路上。

我知道这是一个老问题,但最近才出现;我相信这一点值得补充。


小智 5

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

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

在此处输入图片说明

在此处输入图片说明

希望能有所帮助...

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

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";
    }
}
Run Code Online (Sandbox Code Playgroud)