multithread performance problem for web service call
-
My understanding is that a web service has only one process at a time, so all requests have to queue up anyway.
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
-
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.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
-
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
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).
-
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).
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
-
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
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..
-
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..
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
-
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
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. -
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
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; } }
-
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
1. Server side, the service doesn't run on the client. 2. If I did, I would have given a more authoritative answer.
-
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.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. Server side, the service doesn't run on the client. 2. If I did, I would have given a more authoritative answer.
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
-
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; } }
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
-
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
-
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.
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
-
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
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.
-
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
-
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.
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
-
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.
Thanks harold, For 1, Here is my code at server side. Could you reproduce my problem?
/// <summary> /// Summary description for Service1 /// </summary> \[WebService(Namespace = "http://tempuri.org/")\] \[WebServiceBinding(ConformsTo = WsiProfiles.BasicProfile1\_1)\] \[System.ComponentModel.ToolboxItem(false)\] public class Service1 : System.Web.Services.WebService { \[WebMethod\] public double HelloWorld() { return new Random().NextDouble(); } }
For 2, I could understand your points. But do you have any documents to prove? I think if web service could only serve requests sequentially other than simualtenaously, it is so bad and degrade performance design. I can not believe it is designed in this way. :-) regards, George
-
Thanks harold, For 1, Here is my code at server side. Could you reproduce my problem?
/// <summary> /// Summary description for Service1 /// </summary> \[WebService(Namespace = "http://tempuri.org/")\] \[WebServiceBinding(ConformsTo = WsiProfiles.BasicProfile1\_1)\] \[System.ComponentModel.ToolboxItem(false)\] public class Service1 : System.Web.Services.WebService { \[WebMethod\] public double HelloWorld() { return new Random().NextDouble(); } }
For 2, I could understand your points. But do you have any documents to prove? I think if web service could only serve requests sequentially other than simualtenaously, it is so bad and degrade performance design. I can not believe it is designed in this way. :-) regards, George
- Alright it looks like it should be doing it sequentially, otherwise Random.NextDouble could fail, no method in System.Random is threadsafe. But it should barely take any time at all. 2) Documents... well. Take Amdahl's_law for example, in which P is the proportion of the program that has been made parallel. P would be zero, so you'd get the limit 1 / (1 - 0 + 0/n) where n goes to infinity. So as you can see, the answer is 1, independent of n, meaning: no benefit at all. But of course we knew that that already, since we made no improvement. 3?) I see no good reason for this to be slow, it should be blazingly fast - it's only generating a bunch of random numbers and sending them over right?
-
- Alright it looks like it should be doing it sequentially, otherwise Random.NextDouble could fail, no method in System.Random is threadsafe. But it should barely take any time at all. 2) Documents... well. Take Amdahl's_law for example, in which P is the proportion of the program that has been made parallel. P would be zero, so you'd get the limit 1 / (1 - 0 + 0/n) where n goes to infinity. So as you can see, the answer is 1, independent of n, meaning: no benefit at all. But of course we knew that that already, since we made no improvement. 3?) I see no good reason for this to be slow, it should be blazingly fast - it's only generating a bunch of random numbers and sending them over right?
Thanks harold, 1. "otherwise Random.NextDouble could fail, no method in System.Random is threadsafe." -- I agree it is not thread safe, but I disagree since it is not thread safe, web service will do sequentially. Since each time I creat a new instance of Random object. You can check my code. Any comments? 2. "Alright it looks like it should be doing it sequentially" -- how do you prove it? My current confusion is, web service has to do sequentially or could do in parallel? regards, George