performance - Git注意到性能和替代方案

标签 performance git powershell libgit2sharp

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

管理层想知道的统计数据之一是将提交实际推送到存储库的时间。他们并不真正在乎作者日期提交者日期,因为重要的是何时推送提交并因此被CI服务器接收。因此,我必须实现推送日期之类的东西。出于完整性考虑(不做自我宣传:))这是我的博客文章,描述了详细信息http://mnaoumov.wordpress.com/2013/01/31/git-get-push-date/

基本上,我将使用自定义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本身在commit和note之间没有映射,因此它需要一直在所有笔记中进行查找。
我刚刚检查了存储库中有188921个提交,因此最可能的情况甚至会更糟。因此,我的解决方案根本无法扩展。

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

例如使用魔术哈希 4b825dc642cb6eb9a060e54bf8d69288fbee4904 (Is git's semi-secret empty tree object reliable, and why is there not a symbolic name for it?)
git notes add 4b825dc642cb6eb9a060e54bf8d69288fbee4904 -m serialized-data
$serializedData = git notes show 4b825dc642cb6eb9a060e54bf8d69288fbee4904

这将仅一次检索数据,因此不会出现查找问题。但这会增加序列化-反序列化数据的额外开销,这在我看来并不正确。
请分享您的想法

最佳答案

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

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

    请注意:从内存的 Angular 来看,这会增加一些压力,但是应该更快。

    可以使用以下代码在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 };
    

  • 关于performance - Git注意到性能和替代方案,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/22468146/

    相关文章:

    performance - 分支预测对性能的影响?

    git - 什么是正确的 Git p4 工作流程?

    git - Git 如何忽略以数字开头的文件?

    git - 无法在 GitHub 上将我的第二封邮件提交为 "verified"

    c# - SQL Server 和动态搜索的性能

    php - 我应该在 PHP PERFORMANCE-WISE 中为 MySQL 使用准备好的语句吗?

    powershell - 尝试在 'BizTalk'提供程序上执行InitializeDefaultDrives操作失败

    Powershell - "The process cannot access the file because it is being used by another process"

    azure - Runbook 作为 azure 帐户运行 Powershell

    javascript - 如何总体优化 jQuery 性能