| A couple of days ago, I had sent in an email with the following observation: |
| |
| >Memory consumption: |
| >=================== |
| > |
| >In case of stress test involving lots of clients doing enumeration at |
| >the same time, the memory consumption starts growing at an alarming |
| >rate. This is understandable, since Openwsman has to cache the |
| >enumeration results till the client actually pulls them or they expire. |
| >This might not be a problem under normal systems where the memory is not |
| >at a premium but on embedded systems, this will definitely cause problems. |
| > |
| >Actually, let me take that back. It will cause problems on normal |
| >systems as well. Somewhere between 1.5.0 and 2.0.0 we got rid of the |
| >max_thread parameter. Currently, I believe each listener thread is setup |
| >to handle 20 clients. In case there is a 21st simultaneous client, |
| >another listener thread is spawned. |
| > |
| >Now if one were to look at compat_unix.h, we see this: |
| > |
| > |
| >#define InitializeCriticalSection(x) /* FIXME UNIX version is not MT |
| >safe */ |
| >#define EnterCriticalSection(x) |
| >#define LeaveCriticalSection(x) |
| > |
| > |
| >Seems like mutex locking code is def'ed to nothing on unix systems. If |
| >that is the case then the moment the system spawns another listener |
| >thread, there will be problems and since you cannot contain the number |
| >of threads spawned, you have no control over another thread being spawned. |
| > |
| >I tried to fix compat_unix.h but that just leads to deadlocks that |
| >Helgrind can't seem to identify. |
| > |
| >This seems like a limitation of the spec and the way Openwsman is |
| >engineered. I have a working fix for this albeit in the Openwsman 2.1.0 |
| >codebase. Let me try and port it over to 2.2.0 and I shall send the fix |
| >along. Might take me a day or two to get to this. |
| > |
| >The fix is not conventional but it is config file driven so it can be |
| >turned on or off on the fly. |
| |
| I'm sending in the patch to fix this problem. |
| |
| The patch reintroduces the max_thread config file parameter and introduces |
| two new parameters: |
| |
| * max_connections_per_thread |
| * thread_stack_size |
| |
| Explanation for the patch: |
| ================ |
| |
| 1. wsmand-daemon.c & wsmand-daemon.h: |
| |
| The changes here are to read in the config file parameters. |
| |
| 2. wsmand-listener.c: |
| |
| As I had mentioned earlier, the multithreading capabilities in Openwsman seem |
| to be busted, since compat_unix.c defines all the locking/unlocking primitives to |
| blanks. Since we got rid of the max_thread parameter this makes it quite dangerous |
| since if we have a thread serving 20 clients and a 21st client sends in a request |
| another thread is spawned which is dangerous without the concurrency primitives |
| in place. |
| |
| The change in this file first of all reintroduces the max_thread parameter. I usually |
| keep this to 1, since I don't want more than 1 listener thread running if there is no |
| concurrency support. It also uses the max_connections_per_thread parameter to |
| optimize how many clients you wish to serve by that thread. If more than max_thread |
| * max_connections_per_thread client comes in it is blocked till one of the threads is |
| free. I also modified find_not_busy thread to count how many threads are active. |
| |
| After some profiling it was also a pleasant surprise that Openwsman does not |
| utilize a lot of stack space. Since each thread by default is given about 2Mb if I |
| am not wrong, which seems wasteful, so I introduced the thread_stack_size to |
| optimize the thread stack space. This parameter takes in stack size in bytes and |
| is used as the input to pthread_attr_setstacksize(). I've tested with as low as |
| 256k(262144 bytes) and Openwsman works just fine even under stress. Your |
| mileage may vary depending on the OS. |
| |
| When max_thread is set to 0, Openwsman behaves as it used to. The only |
| caveat is when max_thread is non-zero, max_connections_per_thread cannot |
| be zero, since that would effectively mean that the threads cannot serve any |
| clients. |
| |
| In the case of thread_stack_size set to 0, Openwsman again behaves like it used |
| to. So set both these parameters to zero to turn off these optimizations. |
| |
| 3. wsman-soap.c: |
| |
| This is to tackle the problem of Openwsman using lots of memory when there |
| are too many clients doing Enumerations. Enumerations require Openwsman |
| to keep the results in memory till they expire or till they are pulled by the client. |
| On an embedded system, where the memory constraints are stringent, this |
| could cause problems. |
| |
| To get around this problem, if there are already max_threads*max_connections_ |
| per_thread number of enumeration results in memory and another enumeration |
| request is encountered, I return an error saying "Insufficient Resource.......", till |
| one of the enumerations is pulled or one of them expires. |
| max_threads*max_connections_per_thread means that all the available |
| listeners have been utilized to do enumerations, therefore there could be that |
| many clients making pull requests. I do not block the pull operations or any other |
| operations since those do not require Openwsman to cache the results. |
| |
| This optimization can again be turned off by setting max_threads to 0 which is |
| the default. |
| |
| Testing: |
| ===== |
| |
| Before these changes, the idle Openwsman memory usage was about 8MB and with |
| 10 clients doing simultaneous enumearations would climb up to about 50-60MB. With |
| the following parameters in place: |
| |
| max_threads=1 |
| max_connections_per_thread=8 |
| thread_stack_size=262144 |
| |
| the idle memory usage was about 4MB and with 10 clients doing enumearation, it went |
| up to about 19MB. |
| |
| NOTE: |
| ------- |
| I could get the idle usage down a lot more with setting the main stack even lower than |
| the thread stack using `ulimit -s` in the wsman init file. I could set it down to about 64K |
| and Openwsman worked just fine. |
| |
| Your mileage may again vary but feel free to play around with that if you are on a memory |
| starved system. |
| |
| -- |
| Suresh |