2

私の C# プログラムに任意の数のスレッドがあるとします。各スレッドは、その履歴を調べて、特定のパスの変更セット ID を調べる必要があります。メソッドは次のようになります。

public List<int> GetIdsFromHistory(string path, VersionControlServer tfsClient)
{ 
   IEnumerable submissions = tfsClient.QueryHistory(
      path,
      VersionSpec.Latest,
      0,
      RecursionType.None, // Assume that the path is to a file, not a directory
      null,
      null,
      null,
      Int32.MaxValue,
      false,
      false);

   List<int> ids = new List<int>();
   foreach(Changeset cs in submissions)
   {
      ids.Add(cs.ChangesetId);
   }
   return ids;
}

私の質問は、各スレッドに独自のVersionControlServerインスタンスが必要ですか、それとも 1 つあれば十分でしょうか? 私の直感では、TFS SDK は Web サービスを使用するため、各スレッドには独自のインスタンスが必要であり、実際に並列動作を実現するには、おそらく複数の接続を開く必要があることがわかります。接続を 1 つだけ使用すると、直感的に、複数のスレッドがあってもシリアル動作になることがわかります。

スレッドと同じ数のインスタンスが必要な場合は、Object-Pool パターンを使用することを考えていますが、使用されていない場合、接続はタイムアウトして長時間閉じられますか? この点で、ドキュメントはまばらに見えます。

4

1 に答える 1

1

SAME クライアントを使用するスレッドが最速のオプションのようです。

以下は、4 つのテストをそれぞれ 5 回実行し、ミリ秒単位で平均結果を返すテスト プログラムからの出力です。複数のスレッドで同じクライアントを使用するのが明らかに最速の実行です。

Parallel Pre-Alloc: Execution Time Average (ms): 1921.26044
Parallel AllocOnDemand: Execution Time Average (ms): 1391.665
Parallel-SameClient: Execution Time Average (ms): 400.5484
Serial: Execution Time Average (ms): 1472.76138

参考までに、テスト プログラム自体を次に示します (これもGitHubにあります)。

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.TeamFoundation;
using Microsoft.TeamFoundation.Client;
using Microsoft.TeamFoundation.VersionControl.Client;
using System.Collections;
using System.Threading.Tasks;
using System.Diagnostics;

namespace QueryHistoryPerformanceTesting
{
    class Program
    {
        static string TFS_COLLECTION = /* TFS COLLECTION URL */
        static VersionControlServer GetTfsClient()
        {
            var projectCollectionUri = new Uri(TFS_COLLECTION);
            var projectCollection = TfsTeamProjectCollectionFactory.GetTeamProjectCollection(projectCollectionUri, new UICredentialsProvider());
            projectCollection.EnsureAuthenticated();
            return projectCollection.GetService<VersionControlServer>();
        }

        struct ThrArg
        {
            public VersionControlServer tfc { get; set; }
            public string path { get; set; }
        }

        static List<string> PATHS = new List<string> {
            // ASSUME 21 FILE PATHS
        };

        static int NUM_RUNS = 5;
        static void Main(string[] args)
        {
            var results = new List<TimeSpan>();

            for (int i = NUM_RUNS; i > 0; i--)
            {
                results.Add(RunTestParallelPreAlloc());
            }
            Console.WriteLine("Parallel Pre-Alloc: Execution Time Average (ms): " + results.Select(t => t.TotalMilliseconds).Average());

            results.Clear();
            for (int i = NUM_RUNS; i > 0; i--)
            {
                results.Add(RunTestParallelAllocOnDemand());
            }
            Console.WriteLine("Parallel AllocOnDemand: Execution Time Average (ms): " + results.Select(t => t.TotalMilliseconds).Average());

            results.Clear();
            for (int i = NUM_RUNS; i > 0; i--)
            {
                results.Add(RunTestParallelSameClient());
            }
            Console.WriteLine("Parallel-SameClient: Execution Time Average (ms): " + results.Select(t => t.TotalMilliseconds).Average());

            results.Clear();
            for (int i = NUM_RUNS; i > 0; i--)
            {
                results.Add(RunTestSerial());
            }
            Console.WriteLine("Serial: Execution Time Average (ms): " + results.Select(t => t.TotalMilliseconds).Average());
        }

        static TimeSpan RunTestParallelPreAlloc()
        {
            var paths = new List<ThrArg>();
            paths.AddRange( PATHS.Select( x => new ThrArg { path = x, tfc = GetTfsClient() } ) );
            return RunTestParallel(paths);
        }

        static TimeSpan RunTestParallelAllocOnDemand()
        {
            var paths = new List<ThrArg>();
            paths.AddRange(PATHS.Select(x => new ThrArg { path = x, tfc = null }));
            return RunTestParallel(paths);
        }

        static TimeSpan RunTestParallelSameClient()
        {
            var paths = new List<ThrArg>();
            var _tfc = GetTfsClient();
            paths.AddRange(PATHS.Select(x => new ThrArg { path = x, tfc = _tfc }));
            return RunTestParallel(paths);
        }

        static TimeSpan RunTestParallel(List<ThrArg> args)
        {
            var allIds = new List<int>();

            var stopWatch = new Stopwatch();
            stopWatch.Start();
            Parallel.ForEach(args, s =>
            {
                allIds.AddRange(GetIdsFromHistory(s.path, s.tfc));
            }
            );
            stopWatch.Stop();

            return stopWatch.Elapsed;
        }

        static TimeSpan RunTestSerial()
        {
            var allIds = new List<int>();
            VersionControlServer tfsc = GetTfsClient();

            var stopWatch = new Stopwatch();
            stopWatch.Start();
            foreach (string s in PATHS)
            {
                allIds.AddRange(GetIdsFromHistory(s, tfsc));
            }
            stopWatch.Stop();

            return stopWatch.Elapsed;
        }

        static List<int> GetIdsFromHistory(string path, VersionControlServer tfsClient)
        {
            if (tfsClient == null)
            {
                tfsClient = GetTfsClient();
            }

            IEnumerable submissions = tfsClient.QueryHistory(
                path,
                VersionSpec.Latest,
                0,
                RecursionType.None, // Assume that the path is to a file, not a directory
                null,
                null,
                null,
                Int32.MaxValue,
                false,
                false);

            List<int> ids = new List<int>();
            foreach(Changeset cs in submissions)
            {
                ids.Add(cs.ChangesetId);
            }
            return ids;
        }
于 2013-01-24T17:36:46.057 に答える