Task WBS field retrieval significantly degrades performance

Hi,

I’ve recently downloaded an evaluation copy of Aspose Tasks and I’m presently running a set of performance and functionality tests in comparison to the Microsoft Project Object Model API. I’ll label these as the Aspose & MSP application versions for the sake of future brevity.

The code platform is C# (VS 2015) using the Aspose Tasks 2017 version 17.5.0.0. The application frameworks for the Aspose & MSP versions are identical with object property retrieval differences appropriate for the relevant Aspose or MSP API. In each case the application reads the same 83 projects of varying task count and writes the project & task data to a SQLite database, records are written transactionaly for optimum performance.

All Task values are retrieved using the Aspose API Task.Get(Tsk.) method and the following columns are written:

OutlineLevel
WBS
Summary
Milestone
Name
Start
Finish
ActualStart
ActualFinish
Estimated
PercentComplete
PercentWorkComplete

First strike performance test results in Mins: Seconds -

  • MSP: 3:12

  • Aspose: 2:39

This was a little surprising, I expected a larger performance gain using the Aspose library. Further investigation has identified the WBS value as a performance bottleneck, removing the WBS field from the test reduces the Aspose benchmark to 36 seconds, re-adding WBS increases the benchmark by 2 minutes.

Any idea why the WBS field incurs such significant performance degradation ?

@LeeBorgea,

Thank you for writing to Aspose Support team.

Could you please share the sample project files along with your test code for our reference investigation? We’ll look into these in light of your shared information and share our feedback with you.

H Kashif,

The task testing code is inline below with comments regarding the WBS field. I also have the same code framework using MPXJ which does not manifest this performance difference when reading the WBS field, nor for that matter does using MS Project Interop.

using System;

using Aspose.Tasks;
using Aspose.Tasks.Util;
using Aspose.Tasks.Saving;

namespace GFX.MPP.File.Loader
{
class clsTaskData
{
public string PortfolioControlGUID { get; private set; }
public string TaskControlGUID { get; private set; }

    public int OutlineLevel { get; private set; }
    public string WBS { get; private set; }
    public bool Summary { get; private set; }
    public bool Milestone { get; private set; }
    public string Name { get; private set; }
    public DateTime Start { get; private set; }
    public DateTime Finish { get; private set; }
    public DateTime? ActualStart { get; private set; }
    public DateTime? ActualFinish { get; private set; }
    public bool Estimated { get; private set; }
    public double PercentComplete { get; private set; }
    public double PercentWorkComplete { get; private set; }

    public void SetTaskData(Task activeTask, string portfolioControlGUID)
    {
        try
        {
            PortfolioControlGUID = portfolioControlGUID;
            TaskControlGUID = Guid.NewGuid().ToString();
			
            OutlineLevel = activeTask.Get(Tsk.OutlineLevel);
			
	// The following line incurs large delays for some reason.
	// For 83 projects & 8671 tasks the elapsed time increase from an average 37 seconds to 2 minutes 38 seconds. 
            // Commenting the WBS line reduces the elapsed time back to 37 seconds.
	WBS = activeTask.Get(Tsk.WBS);
            
	Summary = activeTask.Get(Tsk.IsSummary);
            Milestone = activeTask.Get(Tsk.IsMilestone);
            Name = activeTask.Get(Tsk.Name);
            Start = activeTask.Get(Tsk.Start);
            Finish = activeTask.Get(Tsk.Finish);
            ActualStart = GetDate(activeTask.Get(Tsk.ActualStart).ToString());
            ActualFinish = GetDate(activeTask.Get(Tsk.ActualFinish).ToString());
            Estimated=activeTask.Get(Tsk.IsEstimated);
            PercentComplete = activeTask.Get(Tsk.PercentComplete);
            PercentWorkComplete = activeTask.Get(Tsk.PercentWorkComplete);
        }
        catch (SystemException exception)
        {
            throw exception;
        }
    }

    private DateTime? GetDate(string dateValue)
    {
    // Return null for basedate or null dates
        DateTime baseDate = new DateTime(630822816000000000);

        try
        {
            DateTime? returnValue = Convert.ToDateTime(dateValue);

            if (returnValue==baseDate)
            {
                returnValue = null;
            }
            return returnValue;
        }
        catch
        {
            return null;
        }
    }
}

}

@LeeBorgea,

Could you also please share your set of sample files for analysis at our end? We need these for running the tests and comparing results at our end. We’ll update you here with our findings soon.