Skip to content

Conversation

My-Responsitories
Copy link

@My-Responsitories My-Responsitories commented Oct 3, 2025

缓存文件使用硬链接代替复制

以下是采用整合包 FO fabric 1.21.1 测试结果

hard-linked files: 3941
non-hard-linked files: 102
total size of hard-linked files: 833.5 MB
total size of non-hard-linked files: 71.58 MB
percentage of non-hard-linked bytes: 7.91%

可见, 能节省90%+的空间

Copy link
Member

@burningtnt burningtnt left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

有很大问题。

private static volatile boolean hardLink = true;

private static final Object obj = new Object();
private static final ConcurrentHashMap<Path, Object> pathMap = new ConcurrentHashMap<>();
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

我完全没有看懂你这里做 pathMap 的意义是什么。

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

确保线程安全. 这个函数是并发的, 且实际测试也确实遇见了多次同时多个文件写入一个文件的情况, 出现了前面Files.exists(destFile)判断文件不存在, 后面Files.createLink又报错FileAlreadyExistsException

Copy link
Author

@My-Responsitories My-Responsitories Oct 4, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

最好是在创建任务时就去重, 但是copyFile引用的地方太多了, 改动太大可能不稳定, 也没有线程安全的弱引用Map, 可以移除不再使用的路径, 只添加不删除, 下载一个整合包会留下近4000字符串的引用, 这算内存泄漏了. 只能用pathMap保证有复制到destFile任务正在运行时, 其他任务退出

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

确保线程安全. 这个函数是并发的, 且实际测试也确实遇见了多次同时多个文件写入一个文件的情况, 出现了前面Files.exists(destFile)判断文件不存在, 后面Files.createLink又报错FileAlreadyExistsException

这样实现依然阻止不了多进程处理时出现问题的情况,所以不应该使用这样的方式来解决。

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

确保线程安全. 这个函数是并发的, 且实际测试也确实遇见了多次同时多个文件写入一个文件的情况, 出现了前面Files.exists(destFile)判断文件不存在, 后面Files.createLink又报错FileAlreadyExistsException

这样实现依然阻止不了多进程处理时出现问题的情况,所以不应该使用这样的方式来解决。

多进程确实没什么办法, 只能靠try-catch丢掉错误了

                } catch (FileAlreadyExistsException e) {
                    LOG.warning(e.toString());
                    return;

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

  1. 不应该使用 Map 防止重复,请安全地处理 FileAlreadyExistsException
  2. 不应该使用类似 LOG.warning(e.toString()) 这样的代码记录异常,这样无法记录异常栈。请使用 LOG.warning("message", e) 记录异常。

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

  1. 不应该使用 Map 防止重复,请安全地处理 FileAlreadyExistsException

  2. 不应该使用类似 LOG.warning(e.toString()) 这样的代码记录异常,这样无法记录异常栈。请使用 LOG.warning("message", e) 记录异常。

最好能够尝试在创建线程时去重, 尤其是在assets链接到cache时. 去掉判断后, 一次下载就有4处FileAlreadyExistsException

@Glavo
Copy link
Member

Glavo commented Oct 4, 2025

使用硬链接会导致修改一处文件时所有文件跟着变化,所以不应该成为 FileDownloadTask 的默认行为,只有个别场合(比如 assets/objects 里这些用 hash 命名的文件,但仍然要考虑用户是否可能需要修改其中的文本资源)才可以考虑是否使用硬链接。

@My-Responsitories
Copy link
Author

My-Responsitories commented Oct 4, 2025

使用硬链接会导致修改一处文件时所有文件跟着变化,所以不应该成为 FileDownloadTask 的默认行为,只有个别场合(比如 assets/objects 里这些用 hash 命名的文件,但仍然要考虑用户是否可能需要修改其中的文本资源)才可以考虑是否使用硬链接。

下载的文件有assets的hash文件, libraries的.jar库, mods的.jar, 只有资源包, 光影可能会被修改, 给这两个加个只读, 或者这两个用复制?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants