一般来说程序无法打开文件的原因包括:权限不够,文件损坏,格式不支持,系统资源不足等.而这里要讨论的是一种我个人认为较为特殊的情况,主要特征就是文件在外部程序打开完全没问题,可以排除权限,文件损坏之类的通常问题,但是在 julia 中总是报错. 由于这里是 SQLite 的数据文件, macOS 中的出错信息是 ERROR: LoadError: SQLite.SQLiteException("unable to open database file"), 而在 Linux 中则是程序直接退出,终端显示 LoadError: SystemError: unable to read directory, Too many open files.

具体的执行情况是需要将多个文件中某列数据全部提取,并存入一个汇总的文件中.由于这个汇总可能会执行多次(单独的文件可能由于新数据产生而更新),所以需要判断具体的数据是否已在汇总文件中,如果在则跳过.这里的判断需要打开每个数据文件,并得到所需数据列的时间戳.一般在第一次运行时是没有问题的,而在更新时则会偶尔出现上述问题.

实际上在最初由 python 迁移到 julia 时就遇到过这个问题,还在 julia 的 Issues 中询问过.当时在 Linux 下,一般在800个文件前后时直接报错退出,在搜索之后,发现是 julia 进程打开的db文件没有关闭.于是在读取函数最后加上了 SQLite_close(db) 的语句.这样之后,确实有所缓解:不会在800个文件时报错,而是在1800个文件时报错.查看打开文件后,发现还是打开的 db 文件在函数退出后没有关闭.于是猜测是 julia 的 gc() 没有运行.在手动添加 GC.gc() 后,基本没有什么问题了.

最近在macOS上运行,发现又出现问题了.这里同样查看打开的文件 lsof -s julia 发现应该是同一问题.而且是这次是每到240左右退出,于是调整 GC.gc() 的频率,让其每过160个文件运行一次.再次执行时,发现又退出了,而且是在160个文件时.这就让我感到困惑了.在 vscode 中调试运行,发现又没有退出.

之后搜索一番之后,感觉是打开文件数目限制的原因.并且发现如下几个页面: superuser.com, gist.github.com.

按上述页面运行命令后发现系统中 iTerm 下程序的打开文件限制是256个.于是尝试增大这个限制.由于上述页面的评论都说不同版本的macOS方法不同,同时考虑到我能遇到也就iTerm下运行数据处理程序,决定还是在 ~/.zshrc 中添加 limit -n 10240.关于 ulimit 命令可以参阅 ss64.com.再次运行发现没有出现这个中途退出的问题.

之后觉得应该可以把手动运行 gc() 去掉.于是在运行时不断查看 julia 打开文件数目,发现如果函数仅仅打开db文件,打开的文件的最大数目在3000个左右.应该是 julia 本身的 gc() 运行间隔.考虑到已经设置打开文件数目限制为 10240,删除 gc() 应该不会出现问题,于是删除.截止目前还没有出现问题.

发表评论

电子邮件地址不会被公开。 必填项已用*标注