Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/arrays/13.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
磁盘上的Java阵列大容量刷新_Java_Arrays - Fatal编程技术网

磁盘上的Java阵列大容量刷新

磁盘上的Java阵列大容量刷新,java,arrays,Java,Arrays,我有两个数组(int和long),其中包含数百万个条目。到目前为止,我一直在使用DataOutputStream并使用长缓冲区来实现这一点,因此磁盘I/O成本变得很低(nio也或多或少与我有巨大的缓冲区相同,所以I/O访问成本很低),具体来说,使用 DataOutputStream dos = new DataOutputStream(new BufferedOutputStream(new FileOutputStream("abc.txt"),1024*1024*100)); for(in

我有两个数组(int和long),其中包含数百万个条目。到目前为止,我一直在使用DataOutputStream并使用长缓冲区来实现这一点,因此磁盘I/O成本变得很低(nio也或多或少与我有巨大的缓冲区相同,所以I/O访问成本很低),具体来说,使用

DataOutputStream dos = new DataOutputStream(new BufferedOutputStream(new FileOutputStream("abc.txt"),1024*1024*100));

for(int i = 0 ; i < 220000000 ; i++){
    long l = longarray[i];
    dos.writeLong(l);
}
DataOutputStream dos=newdataoutputstream(newbufferedoutputstream(newfileoutputstream(“abc.txt”),1024*1024*100));
对于(int i=0;i<220000000;i++){
长l=长数组[i];
dos.writeLong(l);
}
但这需要几秒钟(超过5分钟)的时间。实际上,我想要的是大容量刷新(某种主内存到磁盘内存映射)。为此,我在和中找到了一个很好的方法。但是,我不明白如何在我的javac中使用它。有人能帮我做这件事吗,或者用其他方法做得更好吗

我正在使用16GB内存和2.13 GhZ[CPU]运行it服务器

我怀疑这个问题与您的Java代码有关

您的文件系统似乎非常慢(至少比本地磁盘慢十倍)

我会做两件事:

  • 仔细检查您是否确实在写入本地磁盘,而不是网络共享。请记住,在某些环境中,主目录是NFS挂载
  • 请您的系统管理员查看一下机器,找出磁盘速度如此之慢的原因。如果我处在他们的位置,我会首先检查日志并运行一些基准测试(例如使用)

  • 在我的机器上,带有SSD的3.8 GHz i7

    DataOutputStream dos = new DataOutputStream(new BufferedOutputStream(new FileOutputStream("abc.txt"), 32 * 1024));
    
    long start = System.nanoTime();
    final int count = 220000000;
    for (int i = 0; i < count; i++) {
        long l = i;
        dos.writeLong(l);
    }
    dos.close();
    long time = System.nanoTime() - start;
    System.out.printf("Took %.3f seconds to write %,d longs%n",
            time / 1e9, count);
    

    使用内存映射文件

    final int count = 220000000;
    
    final FileChannel channel = new RandomAccessFile("abc.txt", "rw").getChannel();
    MappedByteBuffer mbb = channel.map(FileChannel.MapMode.READ_WRITE, 0, count * 8);
    mbb.order(ByteOrder.nativeOrder());
    
    long start = System.nanoTime();
    for (int i = 0; i < count; i++) {
        long l = i;
        mbb.putLong(l);
    }
    channel.close();
    long time = System.nanoTime() - start;
    System.out.printf("Took %.3f seconds to write %,d longs%n",
            time / 1e9, count);
    
    // Only works on Sun/HotSpot/OpenJDK to deallocate buffer.
    ((DirectBuffer) mbb).cleaner().clean();
    
    final FileChannel channel2 = new RandomAccessFile("abc.txt", "r").getChannel();
    MappedByteBuffer mbb2 = channel2.map(FileChannel.MapMode.READ_ONLY, 0, channel2.size());
    mbb2.order(ByteOrder.nativeOrder());
    assert mbb2.remaining() == count * 8;
    long start2 = System.nanoTime();
    for (int i = 0; i < count; i++) {
        long l = mbb2.getLong();
        if (i != l)
            throw new AssertionError("Expected "+i+" but got "+l);
    }
    channel.close();
    long time2 = System.nanoTime() - start2;
    System.out.printf("Took %.3f seconds to read %,d longs%n",
            time2 / 1e9, count);
    
    // Only works on Sun/HotSpot/OpenJDK to deallocate buffer.
    ((DirectBuffer) mbb2).cleaner().clean();
    
    在较慢的机器上打印

    Took 1.180 seconds to write 220,000,000 longs
    Took 0.990 seconds to read 220,000,000 longs
    

    这里有没有其他方法可以避免这种情况?因为我的主内存中已经有了这个阵列,我不能分配超过500 MB的内存来完成这个任务

    这不会使用小于1KB的堆。如果你看看这个电话前后使用了多少内存,你通常不会看到任何增加

    另一件事,这是不是给有效的加载也意味着MappedByteBuffer

    根据我的经验,使用内存映射文件是迄今为止最快的,因为这样可以减少系统调用和复制到内存中的次数

    因为,在一些文章中,我发现read(buffer)可以提供更好的加载性能。(我检查了一下,真的快了2.2亿整数数组-浮点数组读取5秒)

    我想读那篇文章,因为我从来没有看过


    另一个问题:readLong在读取代码输出文件时出错

    性能验证的一部分是以本机字节顺序存储值。writeLong/readLong总是使用大端字节格式,这在本机采用小端字节格式的Intel/AMD系统上要慢得多


    您可以将字节顺序设置为big-endian,这会降低它的速度,也可以使用本机排序(DataInput/OutputStream仅支持big-endian)

    这确实不应该超过几秒钟。我会尝试将缓冲区大小减少到32KB。缓冲区大于此值实际上可能会更慢。根据硬件的不同,您应该能够以至少40到400 MB/s的速度写入数据。@PeterLawrey,我修改了代码。有什么问题吗?但是,这需要498秒。您是在向本地文件系统(而不是网络文件系统)写入文件吗?您所说的“然而,无法理解如何在我的javac中使用它”是什么意思只需下载归档文件,获取Java文件Ti/jni/BulkDataOutputStream.Java并将其添加到您正在编译的类中。@aix,我正在使用16GB内存和2.13GHz内存运行it服务器,Java代码将其写入本地内存。谢谢,我会检查。系统中似乎有些地方存在缺陷。我得问问。谢谢,再次非常感谢。问题是,我必须用这个命令分配另一个相同大小的数组(2.64 GB,我有另一个int数组,相同大小):map(FileChannel.MapMode.READ_WRITE,0,count*8)。这里有没有其他方法可以避免这种情况?因为我的主内存中已经有了这个阵列,我不能分配超过500 MB的内存来完成这个任务?另一件事,这是不是给有效的加载也意味着MappedByteBuffer?因为,在一些文章中,我发现read(buffer)可以提供更好的加载性能。(我检查了其中一个,真的快了2.2亿整数数组-浮点数组读取5秒)。另一个问题:readLong在读取代码输出文件时出错。我作为编辑回复了您的评论。顺便说一句:如果您只使用MappedByteBuffer而不是int[]或long[]或double[],那么它不会使用太多堆(并且您不必做任何事情来将数据写入磁盘),谢谢。我发现read(buf)从中提供了很好的性能。另一件事,你能展示一下,如何使用MappedByteBuffer以一种有效的方式阅读吗?增加了一个如何阅读顺序的例子。注意:您还可以随机访问数据,以便您可以在任何地方开始/结束。
    Took 0.568 seconds to write 220,000,000 longs
    
    Took 1.180 seconds to write 220,000,000 longs
    Took 0.990 seconds to read 220,000,000 longs