Skip to content
  • Categories
  • Recent
  • Tags
  • Popular
  • World
  • Users
  • Groups
Skins
  • Light
  • Cerulean
  • Cosmo
  • Flatly
  • Journal
  • Litera
  • Lumen
  • Lux
  • Materia
  • Minty
  • Morph
  • Pulse
  • Sandstone
  • Simplex
  • Sketchy
  • Spacelab
  • United
  • Yeti
  • Zephyr
  • Dark
  • Cyborg
  • Darkly
  • Quartz
  • Slate
  • Solar
  • Superhero
  • Vapor

  • Default (No Skin)
  • No Skin
Collapse
Code Project
  1. Home
  2. General Programming
  3. C#
  4. multithread performance problem for web service call

multithread performance problem for web service call

Scheduled Pinned Locked Moved C#
databasesysadminperformancequestionwcf
35 Posts 5 Posters 0 Views 1 Watching
  • Oldest to Newest
  • Newest to Oldest
  • Most Votes
Reply
  • Reply as topic
Log in to reply
This topic has been deleted. Only users with topic management privileges can see it.
  • L Lost User

    Threads do not run concurrently (which means at the same time) unless you have hyperthreading technology (which I'm not even sure about that). So the more threads you have, the more checks it has to do, starting and stopping. I am not that great with threading, you'll probably get a much more detailed better response from someone else around here, but that's my understanding of it.

    G Offline
    G Offline
    George_George
    wrote on last edited by
    #7

    Thanks EliottA, I have tried to use thread pool to reduce thread context switch time, here is my code. But the performance never improves, and both the server side and client side CPU/Memory/Network are only used a little from performance tab of task manager. So, I think there are much rooms to optimize? I am using Windows Server 2003 x64 on both client side and server side. Any ideas about how to improve performance?

    class Program
    {
    static Service1[] clients = null;
    static Thread[] threads = null;
    static ManualResetEvent[] doneEvents = null;

    static void ThreadJob (object index)
    {
    // query 100 times
    for (int i = 0; i < 100; i++)
    {
    clients[(int)index].HelloWorld();
    }

    doneEvents[(int)index].Set();
    }

    static void Main(string[] args)
    {
    Console.WriteLine("Specify number of threads: ");
    int number = Int32.Parse(Console.ReadLine());

    clients = new Service1[number];
    threads = new Thread[number];
    doneEvents = new ManualResetEvent[number];

    for (int i = 0; i < number; i++)
    {
    doneEvents[i] = new ManualResetEvent(false);
    clients [i] = new Service1();
    clients[i].EnableDecompression = true;
    ThreadPool.QueueUserWorkItem(ThreadJob, i);
    // ParameterizedThreadStart starter = new ParameterizedThreadStart(ThreadJob);
    // threads[i] = new Thread(starter);
    }

    DateTime begin = DateTime.Now;

    /*
    for (int i = 0; i < number; i++)
    {
    threads[i].Start(i);
    }

    for (int i = 0; i < number; i++)
    {
    threads[i].Join();
    }
    */

    WaitHandle.WaitAll(doneEvents);

    Console.WriteLine("Total elapsed time (s): " + (DateTime.Now - begin).TotalSeconds);

    Console.ReadLine();

    return;
    }
    }

    regards, George

    1 Reply Last reply
    0
    • Y Yasithl

      as i know thread.join means calling thread waits in indefinitely till the other thread terminated.so it might be the bottle neck. the other thing is usually we use threads for concurrent processing so if we don't ask the threads to wait till other thread comes they will work independently

      yasith

      G Offline
      G Offline
      George_George
      wrote on last edited by
      #8

      Thanks yasith, "so if we don't ask the threads to wait till other thread comes they will work independently" -- I am interested, could you show me your code please? regards, George

      1 Reply Last reply
      0
      • L Lost User

        Maybe a single task is not taking enough time to be worth creating a thread for? If that's the case, try to use the ThreadPool and see if that works better. You don't have to use it "explicitly", creating a delegate and calling BeginInvoke on it should be fine. If you want to wait for all tasks to finish, you could store the IAsyncResults in an array and later call EndInvoke on all of them. edit: lol @ my stupid typo :laugh:


        Last modified: 42mins after originally posted --

        G Offline
        G Offline
        George_George
        wrote on last edited by
        #9

        Thanks harold! I have tried to use thread pool but performance never improves. Here is my code. Any ideas to improve performance? http://www.codeproject.com/script/Forums/View.aspx?fid=1649&msg=2911818[^] regards, George

        L 1 Reply Last reply
        0
        • P PIEBALDconsult

          My understanding is that a web service has only one process at a time, so all requests have to queue up anyway.

          G Offline
          G Offline
          George_George
          wrote on last edited by
          #10

          Thanks PIEBALDconsult! 1. "web service has only one process at a time" -- at client side or server side, do you mean? 2. "web service has only one process at a time" -- any documents to prove your points? I am very interested to learn from it. regards, George

          P 1 Reply Last reply
          0
          • E Ennis Ray Lynch Jr

            Add another NIC. Only one request can go through one network card at a time. Also, in looking at your code you are locking up each thread with your call to hello world. If you had a stack of methods to call say:

            Stack<Service1> clients ...;

            You can then use thread safe code inside of your ThreadJob method to pop a service, call its method and then return. Because each thread is now no longer depended on a given service a slow running server will not tie up the entire operation.

            Need software developed? Offering C# development all over the United States, ERL GLOBAL, Inc is the only call you will have to make.
            If you don't ask questions the answers won't stand in your way.
            Most of this sig is for Google, not ego.

            G Offline
            G Offline
            George_George
            wrote on last edited by
            #11

            Thanks Ennis, Looks like you are an expert of this topic. Cool! I read your reply 3 times but still confused. :-( "You can then use thread safe code inside of your ThreadJob method to pop a service, call its method and then return. " -- it is appreciated if you could show me your code please? Honestly, I never wrote such code before. regards, George

            E 1 Reply Last reply
            0
            • G George_George

              Thanks harold! I have tried to use thread pool but performance never improves. Here is my code. Any ideas to improve performance? http://www.codeproject.com/script/Forums/View.aspx?fid=1649&msg=2911818[^] regards, George

              L Offline
              L Offline
              Lost User
              wrote on last edited by
              #12

              Ok, this may not make much of a difference (if any), but you could use some elements like: (this is not code - just some 'useful' elements) delegate void ThreadJobDelegate(int index); IAsyncResult[] results = new IAsyncResult[number]; ThreadJobDelegate th = new ThreadJobDelegate(ThreadJob); results[index] = th.BeginInvoke(index, null, null); foreach(IAsyncResult res) th.EndInvoke(res); I would also time each call to ThreadJob, it doesn't have to be fancy, just to get an idea of how long each call is taking - and time the total (from before the first BeginInvoke till after the last EndInvoke), to see whether threading improved it at all (and if so, by how much).

              G 1 Reply Last reply
              0
              • L Lost User

                Ok, this may not make much of a difference (if any), but you could use some elements like: (this is not code - just some 'useful' elements) delegate void ThreadJobDelegate(int index); IAsyncResult[] results = new IAsyncResult[number]; ThreadJobDelegate th = new ThreadJobDelegate(ThreadJob); results[index] = th.BeginInvoke(index, null, null); foreach(IAsyncResult res) th.EndInvoke(res); I would also time each call to ThreadJob, it doesn't have to be fancy, just to get an idea of how long each call is taking - and time the total (from before the first BeginInvoke till after the last EndInvoke), to see whether threading improved it at all (and if so, by how much).

                G Offline
                G Offline
                George_George
                wrote on last edited by
                #13

                Thanks harold! I have applied your ideas but performance never improves. Here is my code modified according to your idea. Any ideas? Or anything wrong with my code?

                class Program
                {
                    static Service1\[\] clients = null;
                    static IAsyncResult\[\] results = null;
                    static AsyncMethodCaller\[\] callers = null;
                
                    public delegate void AsyncMethodCaller(object index);
                
                    static void ThreadJob (object index)
                    {
                        // query 100 times
                        for (int i = 0; i < 100; i++)
                        {
                            clients\[(int)index\].HelloWorld();
                        }
                    }
                    
                    static void Main(string\[\] args)
                    {
                        Console.WriteLine("Specify number of threads: ");
                        int number = Int32.Parse(Console.ReadLine());
                        
                        clients = new Service1\[number\];
                        results = new IAsyncResult\[number\];
                        callers = new AsyncMethodCaller\[number\];
                
                        for (int i = 0; i < number; i++)
                        {
                            clients\[i\] = new Service1();
                            clients\[i\].EnableDecompression = true;
                            callers\[i\] = new AsyncMethodCaller(ThreadJob);
                            results\[i\] = callers\[i\].BeginInvoke(i, null, null);
                        }
                
                        DateTime begin = DateTime.Now;
                
                        int j = 0;
                        foreach (IAsyncResult res in results)
                        {
                            callers\[j\].EndInvoke(res);
                            j++;
                        }
                
                        Console.WriteLine("Total elapsed time (s): " + (DateTime.Now - begin).TotalSeconds);
                
                        Console.ReadLine();
                
                        return;
                    }
                }
                

                regards, George

                L 1 Reply Last reply
                0
                • G George_George

                  Thanks harold! I have applied your ideas but performance never improves. Here is my code modified according to your idea. Any ideas? Or anything wrong with my code?

                  class Program
                  {
                      static Service1\[\] clients = null;
                      static IAsyncResult\[\] results = null;
                      static AsyncMethodCaller\[\] callers = null;
                  
                      public delegate void AsyncMethodCaller(object index);
                  
                      static void ThreadJob (object index)
                      {
                          // query 100 times
                          for (int i = 0; i < 100; i++)
                          {
                              clients\[(int)index\].HelloWorld();
                          }
                      }
                      
                      static void Main(string\[\] args)
                      {
                          Console.WriteLine("Specify number of threads: ");
                          int number = Int32.Parse(Console.ReadLine());
                          
                          clients = new Service1\[number\];
                          results = new IAsyncResult\[number\];
                          callers = new AsyncMethodCaller\[number\];
                  
                          for (int i = 0; i < number; i++)
                          {
                              clients\[i\] = new Service1();
                              clients\[i\].EnableDecompression = true;
                              callers\[i\] = new AsyncMethodCaller(ThreadJob);
                              results\[i\] = callers\[i\].BeginInvoke(i, null, null);
                          }
                  
                          DateTime begin = DateTime.Now;
                  
                          int j = 0;
                          foreach (IAsyncResult res in results)
                          {
                              callers\[j\].EndInvoke(res);
                              j++;
                          }
                  
                          Console.WriteLine("Total elapsed time (s): " + (DateTime.Now - begin).TotalSeconds);
                  
                          Console.ReadLine();
                  
                          return;
                      }
                  }
                  

                  regards, George

                  L Offline
                  L Offline
                  Lost User
                  wrote on last edited by
                  #14

                  Ok that would explain it then I suppose.. It should be possible to use on 1 new AsyncMethodCaller - but I seriously doubt it would have a impact on the performance. If performance can not be improved with threading, then it will just have to be improved in some other way..

                  G 1 Reply Last reply
                  0
                  • L Lost User

                    Ok that would explain it then I suppose.. It should be possible to use on 1 new AsyncMethodCaller - but I seriously doubt it would have a impact on the performance. If performance can not be improved with threading, then it will just have to be improved in some other way..

                    G Offline
                    G Offline
                    George_George
                    wrote on last edited by
                    #15

                    Thanks harold! "It should be possible to use on 1 new AsyncMethodCaller - but I seriously doubt it would have a impact on the performance." -- how could we use only one AsyncMethodCaller instance? Could you show me some simple pseudo code based on my code please? regards, George

                    L 1 Reply Last reply
                    0
                    • G George_George

                      Thanks Ennis, Looks like you are an expert of this topic. Cool! I read your reply 3 times but still confused. :-( "You can then use thread safe code inside of your ThreadJob method to pop a service, call its method and then return. " -- it is appreciated if you could show me your code please? Honestly, I never wrote such code before. regards, George

                      E Offline
                      E Offline
                      Ennis Ray Lynch Jr
                      wrote on last edited by
                      #16

                      Stack<Items> stack ...;

                      public void MyThread(object whocares){
                      while(go){
                      Item item = null;
                      lock(stack){
                      item = stack.Pop();
                      }
                      if(item != null){
                      //Process Item
                      }
                      }
                      }

                      Then you need somewhere to run start the loop

                      System.Threading.ThreadPool.QueueUserWorkItem(new System.Threading.WaitCallback(MyThread));

                      Now just push items on the stack when they need to be called in another thread. There are many modifications to this basic theme.

                      Need software developed? Offering C# development all over the United States, ERL GLOBAL, Inc is the only call you will have to make.
                      If you don't ask questions the answers won't stand in your way.
                      Most of this sig is for Google, not ego.

                      G 1 Reply Last reply
                      0
                      • G George_George

                        Thanks harold! "It should be possible to use on 1 new AsyncMethodCaller - but I seriously doubt it would have a impact on the performance." -- how could we use only one AsyncMethodCaller instance? Could you show me some simple pseudo code based on my code please? regards, George

                        L Offline
                        L Offline
                        Lost User
                        wrote on last edited by
                        #17

                        Like so:

                        class Program
                        {
                            static Service1\[\] clients = null;
                        
                            public delegate void AsyncMethodCaller(int index);
                        
                            static void ThreadJob (int index)
                            {
                                // query 100 times
                                for (int i = 0; i < 100; i++)
                                {
                                    clients\[index\].HelloWorld();
                                }
                            }
                            
                            static void Main(string\[\] args)
                            {
                                Console.WriteLine("Specify number of threads: ");
                                int number = Int32.Parse(Console.ReadLine());
                                //note: this doesn't actually specify the number of threads
                                //the number of threads will be something like "at most 15 time the number of available cores"
                                //which means that it will only specify the number of threads that are used if
                                //the number if small. And any number of threads may exists - but they wouldn't be used.
                        
                                clients = new Service1\[number\];
                                IAsyncResult\[\] results = new IAsyncResult\[number\];
                        
                                AsyncMethodCaller TJ = new AsyncMethodCaller(ThreadJob)
                                for (int i = 0; i < number; i++)
                                {
                                    clients\[i\] = new Service1();
                                    clients\[i\].EnableDecompression = true;
                                    results\[i\] = TJ.BeginInvoke(i, null, null);
                                }
                        
                                DateTime begin = DateTime.Now;
                        
                                foreach (IAsyncResult res in results)
                                    TJ.EndInvoke(res);
                        
                                Console.WriteLine("Total elapsed time (s): " + (DateTime.Now - begin).TotalSeconds);
                        
                                Console.ReadLine();
                        
                                return;
                            }
                        }
                        
                        G 1 Reply Last reply
                        0
                        • G George_George

                          Thanks PIEBALDconsult! 1. "web service has only one process at a time" -- at client side or server side, do you mean? 2. "web service has only one process at a time" -- any documents to prove your points? I am very interested to learn from it. regards, George

                          P Offline
                          P Offline
                          PIEBALDconsult
                          wrote on last edited by
                          #18

                          1. Server side, the service doesn't run on the client. 2. If I did, I would have given a more authoritative answer.

                          G 1 Reply Last reply
                          0
                          • E Ennis Ray Lynch Jr

                            Stack<Items> stack ...;

                            public void MyThread(object whocares){
                            while(go){
                            Item item = null;
                            lock(stack){
                            item = stack.Pop();
                            }
                            if(item != null){
                            //Process Item
                            }
                            }
                            }

                            Then you need somewhere to run start the loop

                            System.Threading.ThreadPool.QueueUserWorkItem(new System.Threading.WaitCallback(MyThread));

                            Now just push items on the stack when they need to be called in another thread. There are many modifications to this basic theme.

                            Need software developed? Offering C# development all over the United States, ERL GLOBAL, Inc is the only call you will have to make.
                            If you don't ask questions the answers won't stand in your way.
                            Most of this sig is for Google, not ego.

                            G Offline
                            G Offline
                            George_George
                            wrote on last edited by
                            #19

                            Thanks Ennis, I have some confusion about your soluton. I think the reason of why you use stack is because there are some shared object instances between the threads, correct? But in my situation, there is no shared items between my thread jobs. You can read my code again for my thread job in method "ThreadJob". Any comments? Please feel free to correct me if I am wrong. :-) regards, George

                            1 Reply Last reply
                            0
                            • P PIEBALDconsult

                              1. Server side, the service doesn't run on the client. 2. If I did, I would have given a more authoritative answer.

                              G Offline
                              G Offline
                              George_George
                              wrote on last edited by
                              #20

                              Thanks PIEBALDconsult! If the bottleneck is "web service has only one process at a time", how do you prove it or show some related documents? regards, George

                              P 1 Reply Last reply
                              0
                              • L Lost User

                                Like so:

                                class Program
                                {
                                    static Service1\[\] clients = null;
                                
                                    public delegate void AsyncMethodCaller(int index);
                                
                                    static void ThreadJob (int index)
                                    {
                                        // query 100 times
                                        for (int i = 0; i < 100; i++)
                                        {
                                            clients\[index\].HelloWorld();
                                        }
                                    }
                                    
                                    static void Main(string\[\] args)
                                    {
                                        Console.WriteLine("Specify number of threads: ");
                                        int number = Int32.Parse(Console.ReadLine());
                                        //note: this doesn't actually specify the number of threads
                                        //the number of threads will be something like "at most 15 time the number of available cores"
                                        //which means that it will only specify the number of threads that are used if
                                        //the number if small. And any number of threads may exists - but they wouldn't be used.
                                
                                        clients = new Service1\[number\];
                                        IAsyncResult\[\] results = new IAsyncResult\[number\];
                                
                                        AsyncMethodCaller TJ = new AsyncMethodCaller(ThreadJob)
                                        for (int i = 0; i < number; i++)
                                        {
                                            clients\[i\] = new Service1();
                                            clients\[i\].EnableDecompression = true;
                                            results\[i\] = TJ.BeginInvoke(i, null, null);
                                        }
                                
                                        DateTime begin = DateTime.Now;
                                
                                        foreach (IAsyncResult res in results)
                                            TJ.EndInvoke(res);
                                
                                        Console.WriteLine("Total elapsed time (s): " + (DateTime.Now - begin).TotalSeconds);
                                
                                        Console.ReadLine();
                                
                                        return;
                                    }
                                }
                                
                                G Offline
                                G Offline
                                George_George
                                wrote on last edited by
                                #21

                                Thanks harold, I have tried but no performance improvements. Do you have any other ideas to improve performance? I find CPU/memory/network are used a little part, so I think there is room to improve performance. regards, George

                                L 1 Reply Last reply
                                0
                                • G George_George

                                  Thanks harold, I have tried but no performance improvements. Do you have any other ideas to improve performance? I find CPU/memory/network are used a little part, so I think there is room to improve performance. regards, George

                                  L Offline
                                  L Offline
                                  Lost User
                                  wrote on last edited by
                                  #22

                                  Very strange.. I'm really out of ideas now.. :( There is just 1 explanation I can think of - the web server is handling all requests sequentially and non-pipelined.

                                  G 1 Reply Last reply
                                  0
                                  • L Lost User

                                    Very strange.. I'm really out of ideas now.. :( There is just 1 explanation I can think of - the web server is handling all requests sequentially and non-pipelined.

                                    G Offline
                                    G Offline
                                    George_George
                                    wrote on last edited by
                                    #23

                                    Thanks harold, Two more questions, 1. My code is posted and simple. Could you reproduce my issue? I am not suspecting it is my environment issue. :-) 2. "the web server is handling all requests sequentially and non-pipelined" -- do you have any ways or documents to prove it? regards, George

                                    L 1 Reply Last reply
                                    0
                                    • G George_George

                                      Thanks PIEBALDconsult! If the bottleneck is "web service has only one process at a time", how do you prove it or show some related documents? regards, George

                                      P Offline
                                      P Offline
                                      PIEBALDconsult
                                      wrote on last edited by
                                      #24

                                      I don't know, I'm not a Web expert, I'm hoping someone with more knowledge will step in and answer that for both of us. You could possibly create a Web Service with two methods, one that sleeps for a minute and one that doesn't. Make a request to the one that sleeps, and while it's sleeping make a request to the other and see whether or not it waits for the sleeping one to complete.

                                      G 1 Reply Last reply
                                      0
                                      • G George_George

                                        Thanks harold, Two more questions, 1. My code is posted and simple. Could you reproduce my issue? I am not suspecting it is my environment issue. :-) 2. "the web server is handling all requests sequentially and non-pipelined" -- do you have any ways or documents to prove it? regards, George

                                        L Offline
                                        L Offline
                                        Lost User
                                        wrote on last edited by
                                        #25

                                        1. no, I would have to know what HelloWorld() does, and how it does it, and probably a lot more 2. well, if it weren't, threading would cause a speed-up. And it didn't.

                                        G 1 Reply Last reply
                                        0
                                        • P PIEBALDconsult

                                          I don't know, I'm not a Web expert, I'm hoping someone with more knowledge will step in and answer that for both of us. You could possibly create a Web Service with two methods, one that sleeps for a minute and one that doesn't. Make a request to the one that sleeps, and while it's sleeping make a request to the other and see whether or not it waits for the sleeping one to complete.

                                          G Offline
                                          G Offline
                                          George_George
                                          wrote on last edited by
                                          #26

                                          Thanks PIEBALDconsult, I am not sure what you are going to prove. In your scenario, you have web service (say sleep) and another web service (say sleepless). If we call on a thread from client side, first call sleep web service, then call sleepless web service, since it is synchronous call in one thread from client, the client will definitely wait for the sleep web service to complete the return results until call the second sleepless web service. Please correct me if I am wrong in understanding your points. I am confused what you are going to prove -- so obvious results. :-) regards, George

                                          P 1 Reply Last reply
                                          0
                                          Reply
                                          • Reply as topic
                                          Log in to reply
                                          • Oldest to Newest
                                          • Newest to Oldest
                                          • Most Votes


                                          • Login

                                          • Don't have an account? Register

                                          • Login or register to search.
                                          • First post
                                            Last post
                                          0
                                          • Categories
                                          • Recent
                                          • Tags
                                          • Popular
                                          • World
                                          • Users
                                          • Groups