From: thhal at mailblocks.com (Thomas Hallgren) Date: Wed, 16 Feb 2005 17:53:46 +0100 Subject: [Pljava-dev] advice needed In-Reply-To: <309710-220052316154320451@M2W052.mail2web.com> References: <309710-220052316154320451@M2W052.mail2web.com> <42137A9A.3010602@mailblocks.com> Message-ID: info at wyse-systems.ltd.uk wrote: >1. I assume the main class is created (and the class constructor is called) >upon a direct call to the function and then instance is left to be >destroyed by the gc. >If that is the case this wouldn't be the most wise thing to do because of >(at least) 2 reasons: 1. Class cleanup (in my example I have to perform >connection shutdown as well as Resultset and Statement close upon >'completion' or exception event of each task), and 2: there is no way on >Earth you can manage multiple instances and synchorization (unless you >synchronise all methods - way too slow). > > Keep in mind that the PostgreSQL backend is inherently single threaded. You have one JVM per session. This means two things. 1) you hardly ever need to worry about synchronization. The only time you'll need it is when you expect finalizers to do something that might conflict with the main thread. 2) Since you hardly ever will encounter a contended synchronization locks, the overhead of using synchronizers will be almost none at all. A modern JVM is extremely fast when it comes to uncontendend synchronizations. Don't rely on finalizers to do cleanup. Do that just prior to returning false in the assignRowValues. >Wouldn't it be better for pljava to create a pool of instances and present >them to the caller each time a call to the function is made. If you adopt >this approach and extend the ResultSetProvider class to include at least >two more methods for managing class 'activate' and 'deactivate' events >while keeping/recycle the class instance that would bring a performance >boost (not to mention the memory management improvements). You can then add >a few more set of options in postgresql.conf file to configure the object >pool. I am using a similar pool here on our system (it deals with between >30 and 120 different class instances existing in the pool at any point in >time, each of which has an independent network connection to a client) and >by using a pool of objects (as oppose to class instances >creation/destruction upon every call) this brings a performance boost >between 17 and 28% of the entire system. > > Yes, using a pool is an excellent idea. Stay tuned for next release ;-) Meanwhile, try something like this (replace PooledProvider with a name of choice): public class PooledProvider implements ResultSetProvider { private static PooledProvider s_pool; private PooledProvider m_next; public boolean assignRowValues(ResultSet receiver, int currentRow) throws SQLException { // Code that returns true omitted. This happens just before you return false. this.deactivate(); m_next = s_pool; s_pool = this; return false; } public static ResultSetProvider getPooledProvider() throws SQLException { PooledProvider ret = s_pool; if(ret != null) s_pool = ret.m_next; else ret = new PooledProvider(); ret.activate(); return ret; } void activate() {} void deactivate() {} } >2. I am no expert in PostgreSQL internals (in fact I don't know anything >about that at all), but with the above class (DetailsView) wouldn't be >wiser to call 'a method' once and get the result in one go, instead of >calling assignRowValues for each individual row. I think I know the answer >to that one, but it is worth asking and give it a go anyway (; > > The reason is a combination of factors: 1. The PostgreSQL backend function interface stipulates that you implement a function that returns one row at a time. 2. Returning all in one go implies that you either build everything up in memory (not an option for you), or that you create some kind of implementation that in turn can return one row at a time. Then you've gained nothing since that's exactly what the ResultSetProvider does. 3. A lot of implementations will return data that doesn't origin from an SQL query. Having said that, perhaps PLJava should provide a variant that allowes you to return a ResultSet and thereby bypass the transfer between ResultSet's that has to take place today. We are currently adding DatabaseMetaData support to PLJava and in that addition a new SyntheticResultSet is included that would make such an approach even more valuable. >Once I clarify the above questions I am willing to contribute. > > Super! Regards, Thomas Hallgren