java - Java中连续将小文件读入对象的最有效方法

标签 java performance kotlin nio

tl/dr:我需要让我的应用程序中的某些值与大约 10 个小文件中的值保持同步,但我担心一遍又一遍地读取这些值会产生大量 GC 开销。我是创建一堆无缓冲的文件读取器并轮询它们,还是有任何方法可以将文件中的值“映射”到 java Double 中,我可以稍后在值(可能)更改时重新运行?

长版:我有一些物理传感器(陀螺仪、转速计)ev3dev有助于将它们的当前值公开为虚拟文件系统中的小文件。就像一个名为“/sys/bus/lego/drivers/ev3-analog-sensor/angle”的文件,其中包含 56.26712

或者下一刻它包含58.9834

而且我希望我的应用程序中的值尽可能与该文件保持同步。我可以让你的标准循环包含 MappedByteBuffer buffer = inChannel.map(FileChannel.MapMode.READ_ONLY, 0, inChannel.size()); (来自 here )但这似乎有很多分配如果将其置于快速循环中,则会产生开销。

也许有扫描仪的东西,或者 FileChannel inChannel = aFile.getChannel(); ByteBuffer buffer = ByteBuffer.allocate(1024); while(inChannel.read(buffer) > 0)...

我还没有找到KeepInSyncWithFile(myFloatArray, File("./angle", MODE.FILE_TO_VALUE, 10, TimeUnits.MS)的神奇功能

Java 8+

最佳答案

Singe 你说的是 /sys 虚拟文件系统上的伪文件,标准 WatchService 不太可能将为他们工作。为了获得更新的值,您需要阅读这些文件。

好消息是您可以以无垃圾的方式继续阅读,即根本没有分配。打开文件并只分配一次缓冲区,每次要读取一个值时,查找文件的开头并读取到现有的预分配缓冲区。

代码如下:

public class DeviceReader implements Closeable {
    private final RandomAccessFile file;
    private final byte[] buf = new byte[512];

    public DeviceReader(String fileName) throws IOException {
        this.file = new RandomAccessFile(fileName, "r");
    }

    @Override
    public void close() throws IOException {
        file.close();
    }

    public synchronized double readDouble() throws IOException {
        file.seek(0);
        int length = file.read(buf);
        if (length <= 0) {
            throw new EOFException();
        }

        int sign = 1;
        long exp = 0;
        long value = 0;

        for (int i = 0; i < length; i++) {
            byte ch = buf[i];
            if (ch == '-') {
                sign = -1;
            } else if (ch == '.') {
                exp = 1;
            } else if (ch >= '0' && ch <= '9') {
                value = (value * 10) + (ch - '0');
                exp *= 10;
            } else if (ch < ' ') {
                break;
            }
        }

        return (double) (sign * value) / Math.max(1, exp);
    }
}

请注意,我手动从 byte[] 缓冲区解析 float 。调用 Double.parseDouble 会容易得多,但在这种情况下,您必须将 byte[] 转换为 String,该算法将不再是免费分配的。

关于java - Java中连续将小文件读入对象的最有效方法,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/56201037/

相关文章:

bashrc 中的 JAVA_HOME

java - 每周在应用程序中创建一个 DynamoDB 表

java内存管理-java类加载器

Ruby-on-rails 4 性能低下

java - 如何避免创建新的 ObjectMapper 实例,每个来自外部系统的类型响应都被 Jackson 接收和解析?

android - 为什么 ViewModel 和 Fragment 中的相同变量不同?

java - 我们可以从软件的安装文件中揭示其源代码吗?

SQL - 提高 NOT EXISTS 查询性能

java - 使用接口(interface)和反射 API 在运行时创建实例是 coSTLy 选项

android - 为什么来自 Kotlin May 更新的新 LiveData 构建器在我的项目中不起作用