performance issue with multiple threads?

I'm making 3 threads that each instantiate a WF that only has one activity (prints "Hello World" to the console) and I run alll of this in a loop about 3 times. It's taking roughly 2 seconds for each loop. Any idea what could be taking so long

My code looks something like this

Thread[] t = new Thread[iterationCount];
for (int i = 0; i < iterationCount; i++)
{
tIdea = new Thread(new ThreadStart(new ThreadClass().RunWorkflow));
}

DateTime startTime = DateTime.Now;

for (int i = 0; i < iterationCount; i++)
{
tIdea.Start();
}

Program.mEvent.WaitOne();

TimeSpan timeElapsed = DateTime.Now - startTime;







RunWorkflow()....
iCount++;
using (WorkflowRuntime workflowRuntime = new WorkflowRuntime())
{
AutoResetEvent waitHandle = new AutoResetEvent(false);
workflowRuntime.WorkflowCompleted += delegate(object sender, WorkflowCompletedEventArgs e) { waitHandle.Set(); };
workflowRuntime.WorkflowTerminated += delegate(object sender, WorkflowTerminatedEventArgs e)
{
Console.WriteLine(e.Exception.Message);
waitHandle.Set();
};
WorkflowInstance instance = workflowRuntime.CreateWorkflow(typeof(CompositeActivitySample.HelloWorldWorkflow));
instance.Start();
if (iCount == iMax)
{
waitHandle.WaitOne();
Program.mEvent.Set();
}
}


Answer this question

performance issue with multiple threads?

  • George Waters

    In that case I would advise to use the ManualWorkflowSchedulerService as is required in a webservice as a minimum. But to get any decent timings you really should be using a webservice.

    Another thing to keep in mind is that workflow is not intended to replace a short tight loop in code. There is far more overhead involved because of cloning context, persitence etc. This will give you some overhead but a lot of benefit in the long run. However with a very short loop you will only see the overhead :-(


  • ykessler

    If you want to simulate a client application, I'd create a host that instantiates the WF runtime once and then has a mechanism for receiving requests to start workflows. Keep the runtime up until you want it to shut down.

    What you have now may work with simple .NET communication, but if it were me, I'd want a web service client making the calls so I could configure all of the factors.

    The other thing to keep in mind when doing these tests is you are starting and running a very simple workflow. In reality, you will probably have a more complex workflow that has points where it will be waiting for input and persisting. I wouldn't use your configuration from this simple test in that environment without doing some performance testing there too. You will likely not need nearly as many threads in the workflow scheduler.

    Matt



  • Kamii47

    This does raise a more interesting pattern needed for high user count servers that use workflow - the async pattern and thread pools.

    There should be something like this:

    while(running)
    {
    Client client = AcceptClientConnection();
    WorkFlow.BeginWorkflow(typeof(wf1),
    delegate(IAsyncResult ar)
    {
    object result = WorkFlow.EndWorkflow(ar);
    // Process result
    }, client); // Start a workflow and pass our state object to the wf instance.
    }

    The workflow runtime handles the thread pool and frees any blocked thread in the workpool to be used again and pick up again when needed.


  • Trainwreck

    the code looks something like this now...

    workflowRuntime = new WorkflowRuntime()
    DefaultWorkflowSchedulerService mySchedSvc = new DefaultWorkflowSchedulerService(100);
    workflowRuntime.AddService(mySchedSvc);


    for (int i = 0; i < iterationCount; i++)
    {
    ...
    Thread[] t = new Thread[10];
    for (int i = 0; i < iterationCount; i++)
    {
    tIdea = new Thread(new ThreadStart(new ThreadClass().RunHelloWorldWorkFlow));
    }

    DateTime startTime = DateTime.Now;

    for (int i = 0; i < iterationCount; i++)
    {
    tIdea.Start();
    }

    mEvent.WaitOne();

    TimeSpan timeElapsed = DateTime.Now - startTime;
    }


    RunHelloWorldWF....

    {
    AutoResetEvent waitHandle = new AutoResetEvent(false);
    workflowRuntime.WorkflowCompleted += delegate(object sender, WorkflowCompletedEventArgs e) { waitHandle.Set(); };
    workflowRuntime.WorkflowTerminated += delegate(object sender, WorkflowTerminatedEventArgs e)
    {
    Console.WriteLine(e.Exception.Message);
    waitHandle.Set();
    };
    WorkflowInstance instance = workflowRuntime.CreateWorkflow(typeof(CompositeActivitySample.HelloWorldWorkflow));
    instance.Start();
    waitHandle.WaitOne();
    iCount++;
    if (iCount == Program.iterationCount)
    {
    Program.mEvent.Set();
    }
    }

  • TJ2007

    Hi,

    I am surprised that your code actually runs :-) There is only supposed to be a single WorkflowRuntime in an AppDomain.

    Just out of curiosity but why are you creating new threads to start new workflows This is what the DefaultWorkflowSchedulerService is supposed to do. So all you are doing is adding threads and complicating things. By default the DefaultWorkflowSchedulerService will run 4 workflow at the same time on different threads.

    Maurice

  • karthik.sr

    ic...I wanted to spawn 100 threads to simulate a webservice environment where the App Server would get 100 requests. In that case it would be multiple threads.

    I think spawning multiple WorkflowRunTime was what killed the performance. I actually fixed that just right now. Thanks!

  • voila jacques

    I understand that Workflow instance will be handled in another thread, but I am trying to simulate a WebService that can be called from multiple users. That is why I have the thread code there. Am I not understanding something here or is my logic behidn this correct



  • dinzana

    Try this, without all of your threading code:

    for(int i = 0; i<3; i++)

    {

    workflowRuntime.CreateWorkflow(typeof(CompositeActivitySample.HelloWorldWorkflow)).Start();

    }

    You'll need to update your workflow runtime completed event handler to wait for the 3rd workflow to complete before setting the wait handle. But other than that, this should give you what you want.

    Matt



  • performance issue with multiple threads?