P4 FusionPerforce 到 Git 转换工具
P4 Fusion 是一个使用 Perforce Helix Core C++ API 和 Libgit2 用 C++ 编写的快速 Perforce 到 Git 的转换工具,试图缓解git-p4.py的性能瓶颈。
这个项目是作为一个内部项目的概念验证开始的,它需要将P4仓库转换为Git仓库。Git内部也有一个类似的解决方案,叫做git-p4.py。然而,它在处理任何超过1GB大小的仓库时有性能问题,而且它使用Python2在单线程中运行,这给git-p4.py在更大的使用场景中的使用增加了一系列限制。
该工具通过以下方式解决了 git-p4.py 中一些最有影响的扩展和性能限制:
- 使用Helix Core C++ API来处理下载 CL,从而更好地控制内存以及如何将其提交到 Git 存储库,而无需进行不必要的内存复制和文件 I/O。
- 使用libgit2将从 Perforce 服务器接收到的文件内容按原样转发到 Git 存储库,同时尽可能避免内存复制。该库允许从内存中简单存在的文件内容创建提交。
- 使用在 C++11 中实现的自定义基于唤醒的线程池,该线程池运行 Helix Core C++ API 的线程本地库上下文,以对变更列表下载过程进行大量多线程处理。
值得注意的是,P4 Fusion 的速度快到足以在你的Perforce服务器上瞬间产生巨大的负载(如果以中等数量的线程运行,在几分钟内超过15万个请求)。因此,它需要仔细监测以确保Perforce服务器不受影响。这个工具将继续产生负载,没有任何速率限制(除了这个工具提供的运行时选项外),直到转换过程完成。然而,没有速率限制,用几百个网络线程(如果可能的话,甚至更多)来运行这个工具,是在转换过程中实现最大速度的理想情况。
网络线程的数量应设置为一般多于逻辑CPU的数量,因为最耗时的步骤是下载CL数据,这主要是网络I/O的限制。
官方研究表明,这个工具的运行速度比 git-p4.py 快 100 倍以上。在一个包含约3393个中等规模变更列表的仓库路径内,使用 200 个并行连接进行历史转换的平均时间为 26 秒,而 git-p4.py 转换同一仓库路径需要接近 42 分钟。如果Perforce服务器有完整的文件缓存,那么这些转换时间可能是可重复的,否则如果文件缓存是空的,那么前几次运行预计会花费更多时间。
对于更大的仓库(数百万个 CL 或更多),这些执行时间预计会按预期扩展。该工具提供了在转换过程中控制内存利用率的选项,因此这些选项将有助于更大的用例。
❯ ./build/p4-fusion/p4-fusion [ PRINT @ Main:24 ] Running p4-fusion from: ./build/p4-fusion/p4-fusion [ PRINT @ Main:43 ] Usage: [Required] --port Specify which P4PORT to use. [Required] --path P4 depot path to convert to a Git repo [Required] --lookAhead How many CLs in the future, at most, shall we keep downloaded by the time it is to commit them? [Required] --src Local relative source path with P4 code. Git repo will be created at this path. This path should be empty before running p4-fusion. [Required] --client Name/path of the client workspace specification. [Required] --user Specify which P4USER to use. Please ensure that the user is logged in. [Optional, Default is false] --includeBinaries Do not discard binary files while downloading changelists. [Optional, Default is false] --fsyncEnable Enable fsync() while writing objects to disk to ensure they get written to permanent storage immediately instead of being cached. This is to mitigate data loss in events of hardware failure. [Optional, Default is 10] --retries Specify how many times a command should be retried before the process exits in a failure. [Optional, Default is 16] --networkThreads Specify the number of threads in the threadpool for running network calls. Defaults to the number of logical CPUs. [Optional, Default is -1] --maxChanges Specify the max number of changelists which should be processed in a single run. -1 signifies unlimited range. [Optional, Default is 1] --printBatch Specify the p4 print batch size. [Optional, Default is 100] --refresh Specify how many times a connection should be reused before it is refreshed.