From 4ec8e779d1ca5721ad5b4066956db958e872c17b Mon Sep 17 00:00:00 2001 From: doxlik Date: Wed, 13 Aug 2025 20:52:22 +0400 Subject: [PATCH 1/3] Avoiding extra byte copy inside readFileInternal Signed-off-by: doxlik --- .../vertx/core/file/impl/FileSystemImpl.java | 44 +++++-------------- 1 file changed, 11 insertions(+), 33 deletions(-) diff --git a/vertx-core/src/main/java/io/vertx/core/file/impl/FileSystemImpl.java b/vertx-core/src/main/java/io/vertx/core/file/impl/FileSystemImpl.java index 3b26f87cceb..fb560159d08 100644 --- a/vertx-core/src/main/java/io/vertx/core/file/impl/FileSystemImpl.java +++ b/vertx-core/src/main/java/io/vertx/core/file/impl/FileSystemImpl.java @@ -11,16 +11,15 @@ package io.vertx.core.file.impl; +import io.netty.buffer.ByteBuf; +import io.netty.buffer.Unpooled; import io.vertx.codegen.annotations.Nullable; import io.vertx.core.Future; import io.vertx.core.buffer.Buffer; -import io.vertx.core.file.AsyncFile; -import io.vertx.core.file.CopyOptions; -import io.vertx.core.file.FileProps; +import io.vertx.core.buffer.impl.BufferImpl; +import io.vertx.core.file.*; import io.vertx.core.file.FileSystem; import io.vertx.core.file.FileSystemException; -import io.vertx.core.file.FileSystemProps; -import io.vertx.core.file.OpenOptions; import io.vertx.core.internal.ContextInternal; import io.vertx.core.internal.VertxInternal; @@ -28,36 +27,13 @@ import java.io.FilenameFilter; import java.io.IOException; import java.io.RandomAccessFile; -import java.nio.file.CopyOption; -import java.nio.file.FileAlreadyExistsException; -import java.nio.file.FileStore; -import java.nio.file.FileVisitOption; -import java.nio.file.FileVisitResult; -import java.nio.file.Files; -import java.nio.file.LinkOption; -import java.nio.file.Path; -import java.nio.file.Paths; -import java.nio.file.SimpleFileVisitor; -import java.nio.file.StandardCopyOption; -import java.nio.file.attribute.BasicFileAttributes; -import java.nio.file.attribute.FileAttribute; -import java.nio.file.attribute.GroupPrincipal; -import java.nio.file.attribute.PosixFileAttributeView; -import java.nio.file.attribute.PosixFilePermission; -import java.nio.file.attribute.PosixFilePermissions; -import java.nio.file.attribute.UserPrincipal; -import java.nio.file.attribute.UserPrincipalLookupService; -import java.util.ArrayList; -import java.util.EnumSet; -import java.util.HashSet; -import java.util.List; -import java.util.Objects; -import java.util.Set; +import java.nio.file.*; +import java.nio.file.attribute.*; +import java.util.*; import java.util.concurrent.Callable; import java.util.regex.Pattern; /** - * * This class is thread-safe * * @author Tim Fox @@ -531,7 +507,7 @@ public Void perform() { raf.setLength(len); } } catch (IOException e) { - throw new FileSystemException(getFileAccessErrorMessage("truncate", p) ,e); + throw new FileSystemException(getFileAccessErrorMessage("truncate", p), e); } return null; } @@ -711,6 +687,7 @@ public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) throws IO Files.delete(file); return FileVisitResult.CONTINUE; } + public FileVisitResult postVisitDirectory(Path dir, IOException e) throws IOException { if (e == null) { Files.delete(dir); @@ -876,7 +853,8 @@ public Buffer perform() { try { Path target = resolveFile(path).toPath(); byte[] bytes = Files.readAllBytes(target); - return Buffer.buffer(bytes); + ByteBuf bb = Unpooled.wrappedBuffer(bytes); + return new BufferImpl(bb); } catch (IOException e) { throw new FileSystemException(getFileAccessErrorMessage("read", path), e); } From fabebae2fa5f54df65a425bf813d3441503bb69d Mon Sep 17 00:00:00 2001 From: doxlik Date: Thu, 14 Aug 2025 12:01:03 +0400 Subject: [PATCH 2/3] removed unrelated changes --- .../vertx/core/file/impl/FileSystemImpl.java | 38 ++++++++++++++++--- 1 file changed, 32 insertions(+), 6 deletions(-) diff --git a/vertx-core/src/main/java/io/vertx/core/file/impl/FileSystemImpl.java b/vertx-core/src/main/java/io/vertx/core/file/impl/FileSystemImpl.java index fb560159d08..0f040ca983c 100644 --- a/vertx-core/src/main/java/io/vertx/core/file/impl/FileSystemImpl.java +++ b/vertx-core/src/main/java/io/vertx/core/file/impl/FileSystemImpl.java @@ -17,9 +17,13 @@ import io.vertx.core.Future; import io.vertx.core.buffer.Buffer; import io.vertx.core.buffer.impl.BufferImpl; -import io.vertx.core.file.*; +import io.vertx.core.file.AsyncFile; +import io.vertx.core.file.CopyOptions; +import io.vertx.core.file.FileProps; import io.vertx.core.file.FileSystem; import io.vertx.core.file.FileSystemException; +import io.vertx.core.file.FileSystemProps; +import io.vertx.core.file.OpenOptions; import io.vertx.core.internal.ContextInternal; import io.vertx.core.internal.VertxInternal; @@ -27,13 +31,36 @@ import java.io.FilenameFilter; import java.io.IOException; import java.io.RandomAccessFile; -import java.nio.file.*; -import java.nio.file.attribute.*; -import java.util.*; +import java.nio.file.CopyOption; +import java.nio.file.FileAlreadyExistsException; +import java.nio.file.FileStore; +import java.nio.file.FileVisitOption; +import java.nio.file.FileVisitResult; +import java.nio.file.Files; +import java.nio.file.LinkOption; +import java.nio.file.Path; +import java.nio.file.Paths; +import java.nio.file.SimpleFileVisitor; +import java.nio.file.StandardCopyOption; +import java.nio.file.attribute.BasicFileAttributes; +import java.nio.file.attribute.FileAttribute; +import java.nio.file.attribute.GroupPrincipal; +import java.nio.file.attribute.PosixFileAttributeView; +import java.nio.file.attribute.PosixFilePermission; +import java.nio.file.attribute.PosixFilePermissions; +import java.nio.file.attribute.UserPrincipal; +import java.nio.file.attribute.UserPrincipalLookupService; +import java.util.ArrayList; +import java.util.EnumSet; +import java.util.HashSet; +import java.util.List; +import java.util.Objects; +import java.util.Set; import java.util.concurrent.Callable; import java.util.regex.Pattern; /** + * * This class is thread-safe * * @author Tim Fox @@ -507,7 +534,7 @@ public Void perform() { raf.setLength(len); } } catch (IOException e) { - throw new FileSystemException(getFileAccessErrorMessage("truncate", p), e); + throw new FileSystemException(getFileAccessErrorMessage("truncate", p) ,e); } return null; } @@ -687,7 +714,6 @@ public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) throws IO Files.delete(file); return FileVisitResult.CONTINUE; } - public FileVisitResult postVisitDirectory(Path dir, IOException e) throws IOException { if (e == null) { Files.delete(dir); From 3eab03c9daad0c7ea4bd8eb7a1958b6d17003f8a Mon Sep 17 00:00:00 2001 From: doxlik Date: Tue, 23 Sep 2025 12:59:51 +0400 Subject: [PATCH 3/3] modified method to use channel approach --- .../vertx/core/file/impl/FileSystemImpl.java | 44 ++++++++++++++++--- 1 file changed, 39 insertions(+), 5 deletions(-) diff --git a/vertx-core/src/main/java/io/vertx/core/file/impl/FileSystemImpl.java b/vertx-core/src/main/java/io/vertx/core/file/impl/FileSystemImpl.java index 0f040ca983c..e8e04f2f216 100644 --- a/vertx-core/src/main/java/io/vertx/core/file/impl/FileSystemImpl.java +++ b/vertx-core/src/main/java/io/vertx/core/file/impl/FileSystemImpl.java @@ -12,11 +12,9 @@ package io.vertx.core.file.impl; import io.netty.buffer.ByteBuf; -import io.netty.buffer.Unpooled; import io.vertx.codegen.annotations.Nullable; import io.vertx.core.Future; import io.vertx.core.buffer.Buffer; -import io.vertx.core.buffer.impl.BufferImpl; import io.vertx.core.file.AsyncFile; import io.vertx.core.file.CopyOptions; import io.vertx.core.file.FileProps; @@ -26,6 +24,7 @@ import io.vertx.core.file.OpenOptions; import io.vertx.core.internal.ContextInternal; import io.vertx.core.internal.VertxInternal; +import io.vertx.core.internal.buffer.BufferInternal; import java.io.File; import java.io.FilenameFilter; @@ -40,8 +39,10 @@ import java.nio.file.LinkOption; import java.nio.file.Path; import java.nio.file.Paths; +import java.nio.channels.FileChannel; import java.nio.file.SimpleFileVisitor; import java.nio.file.StandardCopyOption; +import java.nio.file.StandardOpenOption; import java.nio.file.attribute.BasicFileAttributes; import java.nio.file.attribute.FileAttribute; import java.nio.file.attribute.GroupPrincipal; @@ -878,9 +879,41 @@ private BlockingAction readFileInternal(String path) { public Buffer perform() { try { Path target = resolveFile(path).toPath(); - byte[] bytes = Files.readAllBytes(target); - ByteBuf bb = Unpooled.wrappedBuffer(bytes); - return new BufferImpl(bb); + try (FileChannel fc = FileChannel.open(target, StandardOpenOption.READ)) { + long initialSize = fc.size(); + final long MAX = (long) Integer.MAX_VALUE - 8; + if (initialSize > MAX) { + throw new OutOfMemoryError("Required array size too large"); + } + + BufferInternal res = BufferInternal.buffer(initialSize > 0 ? (int) initialSize : 0); + final ByteBuf bb = res.getByteBuf(); + if (initialSize > 0) { + bb.ensureWritable((int) initialSize); + } + + long position = 0L; + for (;;) { + int writable = bb.writableBytes(); + if (writable == 0) { + long soFar = bb.readableBytes(); + long remaining = MAX - soFar; + if (remaining <= 0) { + throw new OutOfMemoryError("Required array size too large"); + } + int ensure = (int) Math.min(remaining, 1 << 20); + bb.ensureWritable(ensure); + writable = bb.writableBytes(); + } + int read = bb.writeBytes(fc, position, writable); + if (read <= 0) { + break; + } + position += read; + } + + return res; + } } catch (IOException e) { throw new FileSystemException(getFileAccessErrorMessage("read", path), e); } @@ -888,6 +921,7 @@ public Buffer perform() { }; } + private BlockingAction writeFileInternal(String path, Buffer data) { Objects.requireNonNull(path); Objects.requireNonNull(data);