简体   繁体   English

算法优化-C#

[英]Algorithm optimization - c#

I have this algorithm which I have been working on for some time, but my problem is that it is kinda slow. 我已经使用了一段时间了,但是我的问题是它有点慢。 I will have to optimize it somehow but I find it a little hard. 我将不得不以某种方式对其进行优化,但是我发现有些困难。 The current speed is O(n^4) with some extra execution in for loops. 当前速度为O(n ^ 4),在for循环中有一些额外的执行。

What am I trying to accomplish? 我想完成什么?

I have a lot of testcases stored in a "run section" and some testcases stored in a "suite section". 我在“运行部分”中存储了很多测试用例,在“套件部分”中存储了一些测试用例。 I would like to compare the testcases to be able to see which testcases has failed in the "suite section". 我想比较一下测试用例,以便能够在“套件部分”中查看哪些测试用例失败了。 But to get all the failen testcases I first have to loop through the build to get to the test runs then loop through the testruns to get to the testcases and then I compare the "run section testcases" with the "suite section testcases" in the 4'th loop. 但是,要获取所有失败的测试用例,我首先必须遍历构建以进行测试运行,然后循环遍历测试运行以获取测试用例,然后将“运行部分测试用例”与“套件部分测试用例”进行比较。第4个循环。

Is there any way or methods i could use to simplify this job? 有什么方法或方法可以用来简化这项工作?

The algorithm is listed below. 该算法在下面列出。

/// <summary>
/// Check if the sortet masterList matches any other testcases. If it does then return them.
/// </summary>
/// <algorithm>
/// The following soring algorithm is running O(n^4) which we have to optimize somehow. 
/// </algorithm>
/// <param name="builds"></param>
/// <returns></returns>
/// <summary>
public IEnumerable<Entities.TestResult> RetrieveTestcasesFromSuite(string project, string buildNumber, int suiteId)
{
    SuiteSorting aps = new SuiteSorting();

    IBuilds build = TSBuilds.GetBuildByBuildNumber(project, buildNumber);

    List<Entities.TestResult> failedTestcases = new List<Entities.TestResult>();

    //Gets us a list of the testcase names from the suite number
    List<string> dataen = new List<string>();
    var testcaseSortingID = aps.GetTestcasesFromSuite(suiteId);
    foreach (var element in testcaseSortingID)
    {
        dataen.Add(GetTitleFromTestcaseID(element));
    }

    //For the build we select, we want to see...
    for (int i = 0; i < build.Count; i++)
    {
        ITestRuns testRuns = TS.Runs.TSRuns.GetTestRunByBuildUri(project, build.Value[i].Uri);
        // Show only test runs that have completed
        IEnumerable<TestRun> sortTestRuns = testRuns.Value.Where(p => p.State == TestState.Completed.ToString());

        //Foreach testrun in the build we want to see..
        foreach (ITestRun testRun in sortTestRuns)
        {
            ITestResults testResults = TS.Results.TSResults.GetListOfTestResultsByID(project, testRun.Id);
            // Show only test results that have not passed 
            IEnumerable<TestResult> sortedTestResults = testResults.Value.Where(p => p.Outcome != TestOutcome.Passed.ToString());

            //Foreach test result in each testrun we would like to...
            foreach (ITestResult testResult in sortedTestResults)
            {
                //Foreach testcase found within suites, compare it with all testcases looped from above..
                foreach (var element in dataen)
                {
                    //Foreach testcase in suite, compare with testcases from run.
                    if (element.Equals(testResult.TestCaseTitle))
                    {
                        failedTestcases.Add(new Entities.TestResult()
                        {
                            RunId = testResult.TestRun.Id,                      // The test Run ID
                            RunTitle = testResult.TestRun.Name,                 // The test run Title
                            TestResultId = testResult.Id,
                            Area = testResult.Project.Name,
                            ComputerName = testResult.ComputerName,
                            FailureType = testResult.FailureType,
                            ErrorMessage = testResult.ErrorMessage,
                            TestCaseId = testResult.TestCase.Id,
                            TestCaseTitle = testResult.TestCaseTitle,
                            TestRunId = testResult.TestRun.Id,
                            Reason = ReasonHandler.GiveReasonFromErrorMessage(testResult.ErrorMessage), //Reason
                            Match = ReasonHandler.CompareReasonWithErrorMessageOne(testResult.ErrorMessage),
                            ReasonCategorie = GiveCategorieFromReason(testResult.ErrorMessage, ReasonHandler.GiveReasonFromErrorMessage(testResult.ErrorMessage)), //Retrurns Categorie of reason                                                                                                                                                     // numberInRow = dataToReturn.Count, do we use it?
                            JiraIssueUrl = JiraCommunication.CreatejiraUrlFromReason(ReasonHandler.GiveReasonFromErrorMessage(testResult.ErrorMessage)),           //Creates the JiraIssueUrl
                            JiraKey = JiraCommunication.GetJiraKeyFromReason(ReasonHandler.GiveReasonFromErrorMessage(testResult.ErrorMessage)),
                            TestcaseTfsUrl = TfsHandler.GetTestcaseUrl(testResult.TestRun.Id.ToString(), testResult.Id.ToString()),
                            ResolutionStateId = testResult.ResolutionStateId
                        });
                    }
                }
            }
        }
    }
    return failedTestcases;
}

I think you can do something like below for the inner most two loops and get rid of them, I have not tested anything as you haven't provided complete code: 我认为您可以对最里面的两个循环执行以下操作并摆脱它们,因为您没有提供完整的代码,所以我没有进行任何测试:

var failedTestCases = sortedTestResults.Where(x => dataen.Contains(x.TestCaseTitle)).Select(testResult => new Entities.TestResult
{
                RunId = testResult.TestRun.Id,                      // The test Run ID
                RunTitle = testResult.TestRun.Name,
                TestResultId = testResult.Id,
                Area = testResult.Project.Name,
                // all other columns here ...
}).ToList();

As we discussed in private @KristoferMarEinarsson(We are colleagues) your performance hit comes from external calls and is not a performance problem of your algorithm/CPU as such. 正如我们在私人@KristoferMarEinarsson(我们是同事)中讨论的那样,您的性能下降来自外部调用,而不是算法/ CPU的性能问题。

GetBuildByBuildNumber

GetTestRunByBuildUri

GetListOfTestResultsByID

Are all performing rest queries synchronously and are therefore slowing down your algorithm a lot. 所有同步执行剩余查询,因此大大降低了算法速度。

As each iteration on the loops does not depend on the one prior all your logic in your loops could be made to run asynchronously. 由于循环中的每次迭代都不依赖于先前的迭代,因此可以使循环中的所有逻辑异步运行。 In theory that would bring the execution time down to the worst case of GetBuildByBuildNumber + GetTestRunByBuildUri + GetListOfTestResultsByID . 从理论上讲,这将使执行时间缩短到GetBuildByBuildNumber + GetTestRunByBuildUri + GetListOfTestResultsByID的最坏情况。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM