java 文件相对化方法性能
java file relativize method performance
我有一个代码可以迭代 100 000 个文件并获取它们到某个根目录的相对路径并且代码可以正常工作但与另一个丑陋的解决方案相比速度较慢(它是奇怪的代码但速度更快)。
原代码在这里:
File file, URI rootDirURI
for() {
blabla = rootDirURI.relativize(file.toURI()).getPath()
}
对
File file, URI rootDirURI
for() {
String rootDirPath = rootDirURI.getPath().substring(1); // cut the first slash
rootDirPath = rootDirPath.replaceAll("/", "\\"); // correct windows slashes
String finalPath = file.getAbsolutePath().replace(rootDirPath, ""); // clear the root path: relativize
blabla = finalPath.replace("\", "/"); // slashes
}
好吧,第一个 for 循环 运行 超过 2 分钟,第二个 运行 不到 2 秒...文件是通过 UNC 路径加载的,但是这个 for 循环是在 Files.walkFileTree 被执行。我在我的文件系统中创建了符号链接,它的目标是 UNC 路径,如 \\192.168.1.x\public\something 第一部分加载 ArrayList 中的所有内容,第二部分对 ArrayList 中的文件应用一些操作(上面的循环代码)。
relativize是性能差还是toURI方法的意思?
可能两者兼而有之。如果您查看这两种方法 (URI.relativize(URI), File.toURI()) 的源代码,您会看到正在进行的大量检查、转换和解析。由于这些方法需要在广泛的不同输入上工作并且仍然有些 fault-tolerant 他们需要做这些事情。
如果您确信文件路径已经过清理、规范化、正确等,您可以跳过所有这些检查和转换,从而完成一些字符串操作。
正如@Thomas 已经指出的那样,Path.relativize() 绝对不仅仅是简单的字符串替换。
但在这种特殊情况下,您遇到的瓶颈可能是 File.toURI()
,因为它涉及文件系统访问,当它试图确定您的文件是否为目录时。
例如以下测试代码:
ArrayList<File> files = ...;
URI rootURI = base.toURI();
for(File ff : files) {
String relative = rootURI.relativize(ff.toURI()).getPath();
}
当应用于包含 100000 个文件的数组时,在我的机器上花费了 68993 毫秒 到 运行。
根据 jvisualvm,它大部分时间都在
java.io.UnixFileSystem.getBooleanAttributes0()
本机方法。
可以追溯到File.toURI() -> File.isDirectory()
对 URI
个对象数组进行操作的等效代码
ArrayList<URI> files = ...;
URI rootURI = base.toURI();
for(URI ff : files) {
String relative = rootURI.relativize(ff).getPath();
}
只用了 3810 毫秒就完成了,也就是说几乎快了 ~20 倍。
我有一个代码可以迭代 100 000 个文件并获取它们到某个根目录的相对路径并且代码可以正常工作但与另一个丑陋的解决方案相比速度较慢(它是奇怪的代码但速度更快)。
原代码在这里:
File file, URI rootDirURI
for() {
blabla = rootDirURI.relativize(file.toURI()).getPath()
}
对
File file, URI rootDirURI
for() {
String rootDirPath = rootDirURI.getPath().substring(1); // cut the first slash
rootDirPath = rootDirPath.replaceAll("/", "\\"); // correct windows slashes
String finalPath = file.getAbsolutePath().replace(rootDirPath, ""); // clear the root path: relativize
blabla = finalPath.replace("\", "/"); // slashes
}
好吧,第一个 for 循环 运行 超过 2 分钟,第二个 运行 不到 2 秒...文件是通过 UNC 路径加载的,但是这个 for 循环是在 Files.walkFileTree 被执行。我在我的文件系统中创建了符号链接,它的目标是 UNC 路径,如 \\192.168.1.x\public\something 第一部分加载 ArrayList 中的所有内容,第二部分对 ArrayList 中的文件应用一些操作(上面的循环代码)。
relativize是性能差还是toURI方法的意思?
可能两者兼而有之。如果您查看这两种方法 (URI.relativize(URI), File.toURI()) 的源代码,您会看到正在进行的大量检查、转换和解析。由于这些方法需要在广泛的不同输入上工作并且仍然有些 fault-tolerant 他们需要做这些事情。
如果您确信文件路径已经过清理、规范化、正确等,您可以跳过所有这些检查和转换,从而完成一些字符串操作。
正如@Thomas 已经指出的那样,Path.relativize() 绝对不仅仅是简单的字符串替换。
但在这种特殊情况下,您遇到的瓶颈可能是 File.toURI()
,因为它涉及文件系统访问,当它试图确定您的文件是否为目录时。
例如以下测试代码:
ArrayList<File> files = ...;
URI rootURI = base.toURI();
for(File ff : files) {
String relative = rootURI.relativize(ff.toURI()).getPath();
}
当应用于包含 100000 个文件的数组时,在我的机器上花费了 68993 毫秒 到 运行。
根据 jvisualvm,它大部分时间都在
java.io.UnixFileSystem.getBooleanAttributes0()
本机方法。
可以追溯到File.toURI() -> File.isDirectory()
对 URI
个对象数组进行操作的等效代码
ArrayList<URI> files = ...;
URI rootURI = base.toURI();
for(URI ff : files) {
String relative = rootURI.relativize(ff).getPath();
}
只用了 3810 毫秒就完成了,也就是说几乎快了 ~20 倍。