In one of my application, we wanted to achieve 8000 TPS (Transactions per second) where every second, 8000 session objects will be created and destroyed.
To achieve this performance number, I wanted to optimize memory allocation and deallocation so started looking for existing memory pool class particularly in boost libraries (assuming it would be faster) and I am already using few classes from boost.
I found boost::object_pool. It is a header only file so no need to include link library and I included into my application. At the same time, I used boost::multi_index_container to store session object with multiple indexes. The performance was degrading as number of object increases in the container. I thought that is due to boost multi-index-container.
So I created two separate test applications to measure performance of boost object pool and boost multi-index-container and found that boost object_pool was the bottleneck.
Here is the performance number of destroying 10K, 20K and 30K object from object_pool and using standard c++ delete.
./object_pool_test 10000
Total time to destroy 10000 using delete: 0.3158860
Total time to destroy 10000 from object_pool: 1.447002736 sec
./object_pool_test 20000
Total time to destroy 20000 using delete: 0.6340170
Total time to destroy 20000 from object_pool: 9.624879974 sec
./object_pool_test 30000
Total time to destroy 30000 using delete: 0.10413087
Total time to destroy 30000 from object_pool: 32.150515048 sec
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// File: test_object_pool.cpp
// Description: Test performance of deleting object from boost::object_pool versus standard delete operator.
// Author: Rohit Joshi
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
#include <iostream>
#include <vector>
#include <time.h>
#include <boost/pool/object_pool.hpp>
class Test
{
char buffer[1024];
unsigned long id;
};
int main(int argc, char** argv) {
if(argc < 2) {
std::cout << "Usage: "<< argv[0] << " NumObjects\n";
return 0;
}
int num_objs = atoi(argv[1]);
/////////////////////////////////////////////////////////////////////////////////////////////////
//test1: using standard delete to delete objects
////////////////////////////////////////////////////////////////////////////////////////////////
std::vector<Test*> vDelTest;
vDelTest.reserve(num_objs);
for(int i = 0; i < num_objs; ++i) {
Test *pTest = new Test();
vDelTest.push_back(pTest);
}
timespec tv;
tv.tv_sec = 0;
tv.tv_nsec = 0;
clock_settime(CLOCK_PROCESS_CPUTIME_ID, &tv);
for(int i = 0; i < num_objs; ++i) {
delete vDelTest[i];
}
clock_gettime(CLOCK_PROCESS_CPUTIME_ID, &tv);
std::cout << "Total time to destroy "<< num_objs << " using delete: " << tv.tv_sec << "." << tv.tv
_nsec << "\n";
//////////////////////////////////////////////////////////////////////////////////////////////////
//delete using object_pool
/////////////////////////////////////////////////////////////////////////////////////////////////
boost::object_pool<Test> m_oPool;
std::vector<Test*> vTest;
vTest.reserve(num_objs);
for(int i = 0; i < num_objs; ++i) {
Test *pTest = m_oPool.construct();
vTest.push_back(pTest);
}
clock_gettime(CLOCK_PROCESS_CPUTIME_ID, &tv);
std::cout << "Total time to destroy "<< num_objs << " from object_pool: " << tv.tv_sec << "." << tv.tv_nsec << "\n";
return 0;
}
To compile, copy this source into test_object_pool.cpp
g++ -c test_object_pool.cpp
g++ -o test_object_pool test_object_pool.o -lrt
Expose stop working after connecting to external monitor
When ever I unplug my MacBook from an external monitor, Expose stops working. The solution to this problem is to kill "Dock" application. To make it easier, I have created a script which allows you to do the same.
set app_name to "/System/Library/CoreServices/Dock.app/Contents/MacOS/Dock"
set the_pid to (do shell script "ps ax | grep " & (quoted form of app_name) & " | grep -v grep | awk '{print $1}'")
display dialog "Killingn the application Dock with PID:" & the_pid
if the_pid is not "" then do shell script ("kill -9 " & the_pid)
Copy following lines of code into text editor and copy under $HOME/Library/Scripts/killdock.scpt. Now you can see the script listed under scripts as an shortcut. You can see "kill dock" listed at the end.
set app_name to "/System/Library/CoreServices/Dock.app/Contents/MacOS/Dock"
set the_pid to (do shell script "ps ax | grep " & (quoted form of app_name) & " | grep -v grep | awk '{print $1}'")
display dialog "Killingn the application Dock with PID:" & the_pid
if the_pid is not "" then do shell script ("kill -9 " & the_pid)
Copy following lines of code into text editor and copy under $HOME/Library/Scripts/killdock.scpt. Now you can see the script listed under scripts as an shortcut. You can see "kill dock" listed at the end.
Does Internet Speed check varies based on the browser
I wanted to see whether browser makes different while checking the speed of the internet. I did speed check test using speedtest.net and four different browser and surprisingly all of them gave different results.
1: Safari Version 4.0.3 (5531.9)
Download Speed: 17.16 Mb/s
Upload speed: 4.08 Mb/s
2. Firefox Version 3.6 (rv:1.9.2 Gecko 20100105)
Download Speed:15.84 Mb/s
Upload Speed:4.25 Mb/s
3. Chrome Version 4.0.246.0 (31780)
Download Speed:15.47 Mb/s
Upload Speed:2.17 Mb/s
4. Chrome Version 4.0.249.43:
Download speed: 17.65 Mb/s
Upload speed: 3.98 Mb/s
1: Safari Version 4.0.3 (5531.9)
Download Speed: 17.16 Mb/s
Upload speed: 4.08 Mb/s
2. Firefox Version 3.6 (rv:1.9.2 Gecko 20100105)
Download Speed:15.84 Mb/s
Upload Speed:4.25 Mb/s
3. Chrome Version 4.0.246.0 (31780)
Download Speed:15.47 Mb/s
Upload Speed:2.17 Mb/s
4. Chrome Version 4.0.249.43:
Download speed: 17.65 Mb/s
Upload speed: 3.98 Mb/s
Why google search engine is better than bing for technical information?
When Microsoft launched bing search engine, I started using it. I really liked the picture on main page and results are good when I am searching non-technical information. So I changed my default search engine to Bing and set home page as http://www.bing.com.
But when it comes to technical information, bing couldn't provide me information I wanted. It seems it doesn't display the latest information.
E.g I was working on dbxml (Berkeley DB XML) and posted a question to the "dbxml forum". When I searched "dbxml forum" (without quotes), bing fetches following first five search results.
But when it comes to technical information, bing couldn't provide me information I wanted. It seems it doesn't display the latest information.
E.g I was working on dbxml (Berkeley DB XML) and posted a question to the "dbxml forum". When I searched "dbxml forum" (without quotes), bing fetches following first five search results.
- sourceforge.net/projects/dbxml-core
- rubyforge.org/forum/?group_id=1643
- sourceforge.net/projects/dbxml
- dbxml-core.wiki.sourceforge.net/space/stats
- eiffel-dbxml.wiki.sourceforge.net
- forums.oracle.com/forums/forum.jspa?forumID=274
- www.nabble.com/Berkeley-DB-Xml-f730.html
- www.nabble.com/Berkeley-DB-XML-mailing-list-transition-td5475353.html
- www.mombu.com/.../t-getting-started-with-berkeley-db-xml-806334.html
- www.eosdirectory.com/project/196/Berkeley+DB+XML.html
Glassfish Application Server Performance tunings
If you want to improve performance of your application running on Glassfish application server, you can try out following JVM options. We got significant performance improvement by using them.
<jvm-options>-server</jvm-options>
<jvm-options>-Xms3000m</jvm-options>
<jvm-options>-Xmx3000m</jvm-options>
<jvm-options>-XX:MaxPermSize=192m</jvm-options>
<jvm-options>-XX:NewRation=2</jvm-options>
<jvm-options>-XX:+AggressiveHeap</jvm-options>
<jvm-options>-XX:+AggressiveOpts</jvm-options>
<jvm-options>-XX:+UseParallelGC</jvm-options>
<jvm-options>-XX:+UseParallelOldGC</jvm-options>
<jvm-options>-XX:ParallelGCThreads=5</jvm-options>
By using these performance tunings, we are able to get almost 30% more TPS (Transactions per Seconds).If I can be helpful, please do let me know. I have spent enough time on Glassfish and OpenESB performance tunings.
<jvm-options>-Xmx3000m</jvm-options>
<jvm-options>-XX:MaxPermSize=192m</jvm-options>
<jvm-options>-XX:NewRation=2</jvm-options>
<jvm-options>-XX:+AggressiveHeap</jvm-options>
<jvm-options>-XX:+AggressiveOpts</jvm-options>
<jvm-options>-XX:+UseParallelGC</jvm-options>
<jvm-options>-XX:+UseParallelOldGC</jvm-options>
<jvm-options>-XX:ParallelGCThreads=5</jvm-options>
By using these performance tunings, we are able to get almost 30% more TPS (Transactions per Seconds).If I can be helpful, please do let me know. I have spent enough time on Glassfish and OpenESB performance tunings.
Labels:
garbage collection,
glassfish,
jvm options,
performance,
tunings
Absolute Singleton. Not Really...
Singleton are not true singleton and there are many reasons: One of them is multiple class loaders can have their own copy of singleton. See How single can your singleton instance be?. I started googling for true singleton and came across Absolute Singleton.
When I use this approach in my product, it didn't work instead it was throwing exception java.lang.ClassNotFoundException on the Singleton class.
java.lang.ClassNotFoundException: com.example.common.utils.JCSCache at com.sun.enterprise.util.ConnectorClassLoader.loadClass(ConnectorClassLoader.java:222)
at java.lang.ClassLoader.loadClass(ClassLoader.java:252)
at com.example.common.utils.JCSCache.getInstance(JCSCache.java:131)
After looking at the exception and class initialization, I found that what happens if the first instance is initiated by custom class loader and not the default one?
It will not find an existing instance because while creating the instance, due to custom class loader, it will go into "if (! myClassLoader.toString().startsWith("sun.")) {" (see the Absolute Singleton) condition and try to find existing instance instead of creating new which doesn't exits yet so it throws the java.lang.ClassNotFoundException.
The work around I found is to catch the exception and create the instance of AbsoluteSingleton class.
But next time, custom class loader try to get the instance, again it's not going to find it and create it's own instance.
See the below log.
First instance of JCSCache ( com.example.common.utils.JCSCache@124adaf) created by class loader: org.glassfish.openesb.pojose.jbi.su.SUClassLoader@1b78d60
and
2nd instance (com.example.common.utils.JCSCache@1a859dc) is created by EJBClassLoader.
So Absolute singleton is not really absolute singleton.
[2009-09-27 21:56:04,713 | Thread-79 | common.utils.JCSCache | ENTRY] -->getInstance()
[2009-09-27 21:56:04,713 | Thread-79 | common.utils.JCSCache | DEBUG] Class Loader:org.glassfish.openesb.pojose.jbi.su.SUClassLoader@1b78d60
[2009-09-27 21:56:04,713 | Thread-79 | common.utils.JCSCache | ERROR] Exception:com.example.common.utils.JCSCache
[2009-09-27 21:56:04,713 | Thread-79 | common.utils.JCSCache | ENTRY] -->JCSCache()
[2009-09-27 21:56:04,713 | Thread-79 | common.utils.JCSCache | DEBUG] JCSCache constructor called.
[2009-09-27 21:56:04,713 | Thread-79 | common.utils.JCSCache | EXIT] <--JCSCache() [2009-09-27 21:56:04,713 | Thread-79 | common.utils.JCSCache | ENTRY] -->init()
[2009-09-27 21:56:04,713 | Thread-79 | common.utils.JCSCache | DEBUG] Setting the cache configuratio name:/cache.ccf
[2009-09-27 21:56:04,721 | Thread-79 | common.utils.JCSCache | DEBUG] Initializing region base cache objects.
[2009-09-27 21:56:04,786 | Thread-79 | common.utils.JCSCache | EXIT] <--init() true [2009-09-27 21:56:04,786 | Thread-79 | common.utils.JCSCache | EXIT] <--getInstance() com.example.common.utils.JCSCache@124adaf
2nd instance:
2009-09-27 21:56:06,812 | httpSSLWorkerThread-8080-0 | common.utils.JCSCache | ENTRY] -->getInstance()
[2009-09-27 21:56:06,813 | httpSSLWorkerThread-8080-0 | common.utils.JCSCache | DEBUG] Class Loader:EJBClassLoader :
[2009-09-27 21:56:06,813 | httpSSLWorkerThread-8080-0 | common.utils.JCSCache | ERROR] Exception:com.example.common.utils.JCSCache
[2009-09-27 21:56:06,813 | httpSSLWorkerThread-8080-0 | common.utils.JCSCache | ENTRY] -->JCSCache()
[2009-09-27 21:56:06,813 | httpSSLWorkerThread-8080-0 | common.utils.JCSCache | DEBUG] JCSCache constructor called.
[2009-09-27 21:56:06,813 | httpSSLWorkerThread-8080-0 | common.utils.JCSCache | EXIT] <--JCSCache() [2009-09-27 21:56:06,813 | httpSSLWorkerThread-8080-0 | common.utils.JCSCache | ENTRY] -->init()
[2009-09-27 21:56:06,813 | httpSSLWorkerThread-8080-0 | common.utils.JCSCache | DEBUG] Setting the cache configuratio name:/cache.ccf
[2009-09-27 21:56:06,818 | httpSSLWorkerThread-8080-0 | common.utils.JCSCache | DEBUG] Initializing region base cache objects.
[2009-09-27 21:56:06,926 | httpSSLWorkerThread-8080-0 | common.utils.JCSCache | EXIT] <--init() true [2009-09-27 21:56:06,926 | httpSSLWorkerThread-8080-0 | common.utils.JCSCache | EXIT] <--getInstance() com.example.common.utils.JCSCache@1a859dc
When I use this approach in my product, it didn't work instead it was throwing exception java.lang.ClassNotFoundException on the Singleton class.
java.lang.ClassNotFoundException: com.example.common.utils.JCSCache at com.sun.enterprise.util.ConnectorClassLoader.loadClass(ConnectorClassLoader.java:222)
at java.lang.ClassLoader.loadClass(ClassLoader.java:252)
at com.example.common.utils.JCSCache.getInstance(JCSCache.java:131)
After looking at the exception and class initialization, I found that what happens if the first instance is initiated by custom class loader and not the default one?
It will not find an existing instance because while creating the instance, due to custom class loader, it will go into "if (! myClassLoader.toString().startsWith("sun.")) {" (see the Absolute Singleton) condition and try to find existing instance instead of creating new which doesn't exits yet so it throws the java.lang.ClassNotFoundException.
The work around I found is to catch the exception and create the instance of AbsoluteSingleton class.
But next time, custom class loader try to get the instance, again it's not going to find it and create it's own instance.
See the below log.
First instance of JCSCache ( com.example.common.utils.JCSCache@124adaf) created by class loader: org.glassfish.openesb.pojose.jbi.su.SUClassLoader@1b78d60
and
2nd instance (com.example.common.utils.JCSCache@1a859dc) is created by EJBClassLoader.
So Absolute singleton is not really absolute singleton.
[2009-09-27 21:56:04,713 | Thread-79 | common.utils.JCSCache | ENTRY] -->getInstance()
[2009-09-27 21:56:04,713 | Thread-79 | common.utils.JCSCache | DEBUG] Class Loader:org.glassfish.openesb.pojose.jbi.su.SUClassLoader@1b78d60
[2009-09-27 21:56:04,713 | Thread-79 | common.utils.JCSCache | ERROR] Exception:com.example.common.utils.JCSCache
[2009-09-27 21:56:04,713 | Thread-79 | common.utils.JCSCache | ENTRY] -->JCSCache()
[2009-09-27 21:56:04,713 | Thread-79 | common.utils.JCSCache | DEBUG] JCSCache constructor called.
[2009-09-27 21:56:04,713 | Thread-79 | common.utils.JCSCache | EXIT] <--JCSCache() [2009-09-27 21:56:04,713 | Thread-79 | common.utils.JCSCache | ENTRY] -->init()
[2009-09-27 21:56:04,713 | Thread-79 | common.utils.JCSCache | DEBUG] Setting the cache configuratio name:/cache.ccf
[2009-09-27 21:56:04,721 | Thread-79 | common.utils.JCSCache | DEBUG] Initializing region base cache objects.
[2009-09-27 21:56:04,786 | Thread-79 | common.utils.JCSCache | EXIT] <--init() true [2009-09-27 21:56:04,786 | Thread-79 | common.utils.JCSCache | EXIT] <--getInstance() com.example.common.utils.JCSCache@124adaf
2nd instance:
2009-09-27 21:56:06,812 | httpSSLWorkerThread-8080-0 | common.utils.JCSCache | ENTRY] -->getInstance()
[2009-09-27 21:56:06,813 | httpSSLWorkerThread-8080-0 | common.utils.JCSCache | DEBUG] Class Loader:EJBClassLoader :
[2009-09-27 21:56:06,813 | httpSSLWorkerThread-8080-0 | common.utils.JCSCache | ERROR] Exception:com.example.common.utils.JCSCache
[2009-09-27 21:56:06,813 | httpSSLWorkerThread-8080-0 | common.utils.JCSCache | ENTRY] -->JCSCache()
[2009-09-27 21:56:06,813 | httpSSLWorkerThread-8080-0 | common.utils.JCSCache | DEBUG] JCSCache constructor called.
[2009-09-27 21:56:06,813 | httpSSLWorkerThread-8080-0 | common.utils.JCSCache | EXIT] <--JCSCache() [2009-09-27 21:56:06,813 | httpSSLWorkerThread-8080-0 | common.utils.JCSCache | ENTRY] -->init()
[2009-09-27 21:56:06,813 | httpSSLWorkerThread-8080-0 | common.utils.JCSCache | DEBUG] Setting the cache configuratio name:/cache.ccf
[2009-09-27 21:56:06,818 | httpSSLWorkerThread-8080-0 | common.utils.JCSCache | DEBUG] Initializing region base cache objects.
[2009-09-27 21:56:06,926 | httpSSLWorkerThread-8080-0 | common.utils.JCSCache | EXIT] <--init() true [2009-09-27 21:56:06,926 | httpSSLWorkerThread-8080-0 | common.utils.JCSCache | EXIT] <--getInstance() com.example.common.utils.JCSCache@1a859dc
Labels:
absolute singleton,
singleton,
true singleton
How to Enabled logging in OpenLdap
I am working on performance improvement task for our new product where I wanted avoid duplicate Ldap seaches. To view the ldap searches in sldap log file, we have to enable the logging. This is how you do it.
To enabled logging:
ldapmodify -x -H ldap://ldaphost -D cn=directory\ manager,cn=config -w password
dn: cn=Config
replace: olcLogLevel
olcLogLevel: Stats Stats2 None
Ctrl+d
Now you can view the log file at /var/log/slapd.log. You will need a root/sudo access to view this log file.
To disabled logging:
ldapmodify -x -H ldap://ldaphost -D cn=directory\ manager,cn=config -w password
dn: cn=Config
replace: olcLogLevel
olcLogLevel: None
Ctrl+d
NOTE: Here is None is used for reporting errors so don't forget to specify None when you enable or disable logging.
If you want to modify existing subscriber data in ldap, you can use this command
ldapmodify -x -H ldap://host -D cn=directory\ manager,o=example.com -w password123 -f modifieddata.ldif
where modifieddata.ldif would contain
dn: uniqueIdentifier=0209091514-1015999999,ou=subscribers,ou=OU,o=example.com
changetype: modify
replace:
:
dn: uniqueIdentifier=0209091514-1016000000,ou=subscribers,ou=OU,o=example.com
changetype: modify
replace:
:
To enabled logging:
ldapmodify -x -H ldap://ldaphost -D cn=directory\ manager,cn=config -w password
dn: cn=Config
replace: olcLogLevel
olcLogLevel: Stats Stats2 None
Ctrl+d
Now you can view the log file at /var/log/slapd.log. You will need a root/sudo access to view this log file.
To disabled logging:
ldapmodify -x -H ldap://ldaphost -D cn=directory\ manager,cn=config -w password
dn: cn=Config
replace: olcLogLevel
olcLogLevel: None
Ctrl+d
NOTE: Here is None is used for reporting errors so don't forget to specify None when you enable or disable logging.
If you want to modify existing subscriber data in ldap, you can use this command
ldapmodify -x -H ldap://host -D cn=directory\ manager,o=example.com -w password123 -f modifieddata.ldif
where modifieddata.ldif would contain
dn: uniqueIdentifier=0209091514-1015999999,ou=subscribers,ou=OU,o=example.com
changetype: modify
replace:
dn: uniqueIdentifier=0209091514-1016000000,ou=subscribers,ou=OU,o=example.com
changetype: modify
replace:
Labels:
enabled logging,
ldap,
olcLogLevel




