繁体   English   中英

在Java中用文件写一个非常小的字符串的最快方法是什么?

[英]What's the fastest way to write a very small string to a file in Java?

我的代码需要采用0到255之间的整数值,并将其作为字符串写入文件。 它需要很快,因为它可以非常快速地重复调用,因此任何优化在重负载时都会变得明显。 此处还有其他问题涉及将大量数据写入文件的有效方法,但少量数据如何?

这是我目前的做法:

public static void writeInt(final String filename, final int value)
{
    try
    {
        // Convert the int to a string representation in a byte array
        final String string = Integer.toString(value);
        final byte[] bytes = new byte[string.length()];
        for (int i = 0; i < string.length(); i++)
        {
            bytes[i] = (byte)string.charAt(i);
        }

        // Now write the byte array to file
        final FileOutputStream fileOutputStream = new FileOutputStream(filename);
        fileOutputStream.write(bytes, 0, bytes.length);
        fileOutputStream.close();
    }
    catch (IOException exception)
    {
        // Error handling here
    }
}

我不认为BufferedOutputStream会在这里提供帮助:构建刷新缓冲区的开销可能适用于3字符写入,不是吗? 我可以做出任何其他改进吗?

我认为这与0-255范围要求的要求一样有效。 使用缓冲的写入器效率较低,因为它会创建一些临时结构,您不需要创建这么多的字节。

static byte[][] cache = new byte[256][];
public static void writeInt(final String filename, final int value)
{
    // time will be spent on integer to string conversion, so cache that
    byte[] bytesToWrite = cache[value];
    if (bytesToWrite == null) {
        bytesToWrite = cache[value] = String.valueOf(value).getBytes();
    }

    FileOutputStream fileOutputStream = null;
    try {
        // Now write the byte array to file
        fileOutputStream = new FileOutputStream(filename);
        fileOutputStream.write(bytesToWrite);
        fileOutputStream.close();
    } catch (IOException exception) {
        // Error handling here
    } finally {
        if (fileOutputStream != null) {
            fileOutputStream.close()
        }
    }
}

您无法使其更快IMO。 如果不是这样,BufferedOutputStream在这里没有任何帮助。 如果我们查看src,我们将看到FileOutputStream.write(byte b [],int off,int len)将字节数组直接发送到本机方法,而BufferedOutputStream.write(byte b [],int off,int len)是同步并首先将数组复制到其缓冲区,然后在关闭时将字节从缓冲区刷新到实际流。

除了这种情况下最慢的部分是打开/关闭文件。

我认为,这里的瓶颈是IO,这两项改进可能会有所帮助:

  • 考虑更新的粒度。 也就是说,如果您的应用程序每秒需要不超过20个更新,那么您可以优化您的应用程序,以使每1/20秒不超过1个更新。 根据环境的不同,这可能非常有益。
  • Java NIO已被证明对于大尺寸而言要快得多,因此尝试小尺寸也很有意义,例如,写入Channel而不是InputStream

对不起来这么晚来参加聚会:)

我认为尝试优化代码可能不是正确的方法。 如果您要重复写入相同的小文件,并且每次都必须写入它而不是在应用程序中进行缓冲,那么到目前为止,最大的考虑因素是文件系统和存储硬件。

关键在于,如果你每次真正击中硬件,那么你会严重打扰它。 但是,如果您的系统正在缓存写入,那么您可能根本不会经常访问硬件:数据在到达之前就已被覆盖,并且只会写入新数据。

但这取决于两件事。 首先,你的文件系统在写入旧写入之前获得新写入时会做什么? 某些文件系统可能最终仍会在日记中写入额外的条目,甚至将旧文件放在一个位置,然后将新文件放在另一个物理位置。 那将是一个杀手。

另外,当您要求覆盖某些内容时,您的硬件会做什么? 如果它是传统的硬盘驱动器,它可能只会覆盖旧数据。 如果它是闪存(这可能是Android系统),则损耗平衡将开始,并且它将继续写入驱动器的不同位。

在磁盘缓存和文件系统方面,您确实需要尽一切可能,以确保在将缓存推送到磁盘之前发送1000次更新时,只会写入最后一次更新。

由于这是Android,你可能正在看ext2 / 3/4。 仔细查看日记选项,并研究ext4中延迟分配的影响。 也许最好的选择是使用ext4,但关闭日记。

谷歌的快速搜索为不同大小的文件提供了不同写/读操作的基准:

http://designingefficientsoftware.wordpress.com/2011/03/03/efficient-file-io-from-csharp/

作者得出结论, WinFileIO.WriteBlocks在将数据写入文件WinFileIO.WriteBlocks执行速度最快,尽管I / O操作严重依赖于多种因素,例如操作系统文件缓存,文件索引,磁盘碎片,文件系统缓存等。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM