使用 QueryBuilds 从 TFS 查询构建的性能非常低

Posted

技术标签:

【中文标题】使用 QueryBuilds 从 TFS 查询构建的性能非常低【英文标题】:Querying builds from TFS with QueryBuilds has very low performance 【发布时间】:2021-04-11 09:07:57 【问题描述】:

我正在尝试访问具有“无限期保留”标志(BuildDetail.KeepForever 属性)的本地 TFS 2015 服务器中的每个构建,但 QueryBuilds() 函数需要太长时间才能获取所有构建。

TFS 2015 'Retain Indefinitely' Web GUI Menu Option

我真正需要的是KeepForeverDropLocation 属性。

我发现使用IBuildDetailSpec 接口可以提高效率,但我找不到可以获取KeepForever 属性的选项。

我当前的代码sn-p:

public void BackupOnlyRetainedBuilds(string TeamProjectName, string DestinationPath)

    defs[...]

    Uri configurationServerUri = new Uri("http://builder:8080/tfs");
    TfsTeamProjectCollection server = new TfsTeamProjectCollection(configurationServerUri);

    //get builds server
    buildServer = (IBuildServer)server.GetService(typeof(IBuildServer));

    //set up an array of all build definition from a spcific team project.
    IBuildDefinition[] bda = buildServer.QueryBuildDefinitions(TeamProjectName);

    //check each build definition.
    foreach (var buildDefinition in bda)
    
        //set an array of builds history.
        IBuildDetail[] bha = buildDefinition.QueryBuilds();

        //check each build from build history build details.
        foreach (var buildDetails in bha)
        
            //check if build is retained.
            if (buildDetails.KeepForever == true)
            
                string dropLocationPath = buildDetails.DropLocation;

                //check if drop folder exists.
                if (Directory.Exists(dropLocationPath))
                
                    //create all of the directories.
                    foreach (string dirPath in Directory.GetDirectories(dropLocationPath, "*",
                        SearchOption.AllDirectories))
                        Directory.CreateDirectory(dirPath.Replace(dropLocationPath, DestinationPath));

                    //copy all the files & Replaces any files with the same name.
                    foreach (string newPath in Directory.GetFiles(dropLocationPath, "*.*",
                        SearchOption.AllDirectories))
                        File.Copy(newPath, newPath.Replace(dropLocationPath, DestinationPath), true);
                
            
        
    

【问题讨论】:

【参考方案1】:

你可以告诉QueryBuilds不要从我的tfsbuild.exe的补丁版本中获取所有构建细节,而只获取你感兴趣的那些:

buildDetailSpec = this.BuildServer.CreateBuildDetailSpec(...)
buildDetailSpec.QueryDeletedOption = !forDestroy ? QueryDeletedOption.IncludeDeleted : QueryDeletedOption.OnlyDeleted;
buildDetailSpec.InformationTypes = null;
IBuildQueryResult buildQueryResult = this.BuildServer.QueryBuilds(buildDetailSpec);

或者也可以使用QueryBuildsUri 并通过(string[]) null, QueryOptions.None

IBuildDetail[] buildDetailArray = this.BuildServer.QueryBuildsByUri(list2.ToArray(), (string[]) null, QueryOptions.None, QueryDeletedOption.IncludeDeleted);

您可能需要将一组特定的InformationTypes 传递给它,具体取决于您作为备份工具的一部分所需的数据。

【讨论】:

谢谢! buildDetailSpec.InformationTypes = null; & IBuildQueryResult 成功了,但我找不到文档来告诉我不同​​ InformationTypes 之间的区别以及为什么 null 使其比正常速度快得多。 构建时间线中的每条记录和附件都是一条 BuildInfo 记录。每条记录都有一个类型。当您查询构建时,默认情况下,当您检索或查询构建时,所有记录都会反序列化。这可以是许多 MB 的数据来反序列化并放入内存,我已经看到在这些记录中构建了 50+ MB 的数据。通过传递一个空数组或 null 你告诉系统只返回根记录。最多只有几 KB。因此实现了巨大的加速。 测试结果和覆盖率以及构建中包含的任何工具的每一行输出,它们最终都作为 I BuildInfo 记录。 这里是可以存储在构建中的所有类型信息的列表:docs.microsoft.com/en-us/previous-versions/visualstudio/…

以上是关于使用 QueryBuilds 从 TFS 查询构建的性能非常低的主要内容,如果未能解决你的问题,请参考以下文章

从 2012 年升级 TFS 并处理 Xaml 构建服务器

如何从 TFS 获取构建定义?

使用 top - 参数从 TFS-API 获取构建

将构建定义从 TFS 迁移到 VSTS

从 TFS Build 构建 MSI

如何在 VSTS 仪表板小部件中使用 REST API 从 TFS 获取构建定义?