Git 注释性能和替代方案

问题描述 投票:0回答:2

我们在一个大型团队(>100 名开发人员)的工作中使用 git,我正在编写不同的脚本来向管理层提供 git 统计信息。

管理层想知道的统计数据之一是提交实际推送到存储库的时间。他们并不真正关心作者日期提交者日期,因为重要的是提交何时被推送并被 CI 服务器拾取。所以我必须实现像“推送日期”这样的东西。只是为了完整性(不是为了给自己做广告:))这是我的博文描述了细节。 基本上,当提交实际推送到远程存储库时,我使用自定义 git 注释来存储详细信息。

让我们考虑一个简单的任务:提供 A(不包括)和 B(包括)之间的所有提交的列表,并输出提交哈希、提交消息和推送日期

我可以做这样的事情:

git log A..B --notes=push-date --format=<begin>%H<separator>%s<separator>%N<end>

然后相应地解析事物。无论如何,这确实很慢。而且我也不喜欢进行字符串解析,我更喜欢强类型方法。

因此,为了解决性能问题并摆脱解析,我决定使用 LibGit2Sharp 库。

好吧,如果我们不碰笔记,它的工作速度会非常快,但一旦我尝试检索笔记,它就会变得非常非常慢:

# PowerShell script $pushDateNote = $commit.Notes | Where-Object -FilterScript { $_.Namespace -eq "push-date" } $pushDate = [DateTime]::Parse($pushDateNote.Message)

为了进行比较,如果我不包含注释,大约 2 秒内返回 200 次提交的结果。如果我添加笔记,时间会增加到 2 分钟。

我已经检查过这里的瓶颈是提交的搜索注释。看来git本身没有提交和注释之间的映射,所以它需要一直查找所有注释。 我刚刚检查了存储库中有 188921 个提交,因此最有可能的情况会变得更糟。所以我的解决方案根本不可扩展。

所以我的问题是:我做错了吗?也许 git 不是有效存储自己的元数据的正确工具?我现在正在考虑将所有元数据移动到外部数据库(例如 MSSQL)中。但我宁愿把所有东西都放在一处。或者,我想将提交和推送日期之间的整个映射序列化为一次提交中的注释

例如使用魔法哈希

4b825dc642cb6eb9a060e54bf8d69288fbee4904

git的半秘密空树对象可靠吗?为什么没有符号名? git notes add 4b825dc642cb6eb9a060e54bf8d69288fbee4904 -m serialized-data $serializedData = git notes show 4b825dc642cb6eb9a060e54bf8d69288fbee4904

这将有助于仅检索一次数据,因此不会出现查找问题。但它会增加序列化-反序列化数据的额外开销,这对我来说看起来不太合适。

请分享您的想法。

git performance libgit2sharp git-notes
2个回答
3
投票
Commit

对象访问注释使得 libgit2 在循环的每次迭代中访问注释树。更有效的方法是:


首先,加载您感兴趣的提交列表(显然您已经在这样做了)
  • 然后加载与
  • push-date
  • 命名空间关联的所有笔记
    仅一次
    并最终在这两个列表之间执行连接
注意

:从内存角度来看,这会增加一些更多的压力,但应该会更快。

这可以在 C# 中使用以下代码完成:

using (var repo = new Repository("your_repo_path")) { var notes = repo.Notes["push-date"]; var commits = repo.Commits.QueryBy( new CommitFilter {Since = "1234567", Until = "89abcde"}); var pairs = from commit in commits from note in notes where note.TargetObjectId == commit.Id select new {Commit = commit, Note = note}; foreach (var pair in pairs) { Debug.Write(pair.Commit.Sha + " : " + pair.Note); } }

这将输出在 
push-date

命名空间中具有关联注释的提交。

注意

:如果您使用 QueryBy 语法来检索提交列表,请注意指定为

Until
的提交将从列表中排除(例如:如 git log A...B 中所示)


为了还显示在
push-date

命名空间中没有关联注释的提交,您可以使用以下 linq 查询:

var pairs2 = from commit in commits
             join note in notes on commit.Id equals note.TargetObjectId into gj
             from subnote in gj.DefaultIfEmpty()
             select new { Commit = commit, Note = subnote };



0
投票
https://git-scm.com/docs/git-notes

最新问题
© www.soinside.com 2019 - 2025. All rights reserved.