Return-Path: Delivered-To: apmail-jakarta-struts-user-archive@jakarta.apache.org Received: (qmail 8126 invoked by uid 500); 28 Aug 2001 13:45:39 -0000 Mailing-List: contact struts-user-help@jakarta.apache.org; run by ezmlm Precedence: bulk Reply-To: struts-user@jakarta.apache.org list-help: list-unsubscribe: list-post: Delivered-To: mailing list struts-user@jakarta.apache.org Received: (qmail 8115 invoked from network); 28 Aug 2001 13:45:39 -0000 Received: from mailout6-0.nyroc.rr.com (HELO mailout6.nyroc.rr.com) (24.92.226.125) by daedalus.apache.org with SMTP; 28 Aug 2001 13:45:39 -0000 Received: from apache.org (roc-24-24-50-8.rochester.rr.com [24.24.50.8]) by mailout6.nyroc.rr.com (8.11.5/Road Runner 1.12) with ESMTP id f7SDiXJ12742 for ; Tue, 28 Aug 2001 09:44:34 -0400 (EDT) Message-ID: <3B8BA07E.E7A9A707@apache.org> Date: Tue, 28 Aug 2001 09:45:34 -0400 From: Ted Husted Organization: Apache Software Foundation / Jakarta X-Mailer: Mozilla 4.75 [en] (WinNT; U) X-Accept-Language: en MIME-Version: 1.0 To: struts-user@jakarta.apache.org Subject: Re: Performance, Reflection, and Object Creation vs. Cacheing References: <3B8B17EA.20501@netmeme.org> Content-Type: text/plain; charset=us-ascii Content-Transfer-Encoding: 7bit X-Spam-Rating: daedalus.apache.org 1.6.2 0/1000/N People I trust have said that they have run benchmarks that say reflection can cost 5% to 10% more than direct method invocation. http://archives.java.sun.com/cgi-bin/wa?A2=ind0001&L=jsp-interest&P=R35735 Now this is enough for some maven to put it on an optimization punchlist, along with unrolling loops, and other time vs space trade-offs. But, personally, I don't find the need to unroll many loops in the applications I write ;-) So it's important to ask yourself whether 5% to 10% is a difference that makes a difference? Also remember that in a real application, we are looking at one utility method, like BeanUtils.populate(), being threaded with all the assignments. I would think this is much more efficient than loading several hundred "optimized" methods just to manage direct method invocations. BeanUtils.populate() also caches the descriptors so subsequent calls are even cheaper than the first. Real-life optimizations are differences that make a real difference. When the EJB platform was being designed, object creation ~did~ make a difference, and caching ~was~ vital. To an extent it still is, especially with deep hierarchies, like those many EJB applications find themselves using. But object creation and garbage collection in a late model JVM is not what it used to be ;-) Progress! Meanwhile, personally, I've started to build calls to BeanUtils.populate() into my own data transfer utilities. This lets me put a call deep inside the resource layer that neatly turns an arbitrary ResultSet into a collection of arbitrary beans. It just matches the rset columns with the jbean properties. // Transfer ResultSet to Collection of target beans ** if (resultSet!=null) { collection = ResultSetUtils.getCollection( target,resultSet); } Where ResultSetUtils does this public static void populate(Object bean, ResultSet resultSet) throws SQLException { // Build a list of relevant column properties from this resultSet HashMap properties = new HashMap(); // Acquire resultSet MetaData ResultSetMetaData metaData = resultSet.getMetaData(); int cols = metaData.getColumnCount(); // Scroll to next record and pump into hashmap if (resultSet.next()) for (int i=1; i<=cols ; i++) { // :TODO: Let native types through /* int type = metaData.getType(i); if ... properties.put(metaData.getColumnName(i), resultSet.getObject(i)); else */ properties.put(metaData.getColumnName(i), resultSet.getString(i)); } // Set the corresponding properties of our bean try { BeanUtils.populate(bean, properties); } catch (Exception e) { throw new SQLException("BeanUtils.populate threw " + e.toString()); } } This can save hundreds of lines of code that would have otherwise have been needed to write custom transfer utilities. (Been there, did that, not fun.) Of course, it works with more than just ResultSets. I wrote a similar set of utilities last week that turned a Lucene Hits list into a collection of beans. Sweet ;-) Here are some other links from this list: http://www.mail-archive.com/struts-user@jakarta.apache.org/msg12574.html http://www.mail-archive.com/struts-user@jakarta.apache.org/msg13847.html http://www.mail-archive.com/struts-user@jakarta.apache.org/msg13294.html http://www.mail-archive.com/struts-user@jakarta.apache.org/msg13149.html http://www.mail-archive.com/struts-user@jakarta.apache.org/msg11933.html http://www.mail-archive.com/struts-user@jakarta.apache.org/msg02683.html http://www.mail-archive.com/struts-user@jakarta.apache.org/msg00374.html Other background links: http://java.sun.com/j2se/1.4/docs/guide/reflection/ http://www-106.ibm.com/developerworks/library/introspect/index.html http://www.javaworld.com/javaworld/jw-11-1999/jw-11-servlet_p.html http://www.javaworld.com/javaworld/jw-11-1998/jw-11-batch_p.html http://www.ddj.com/articles/1998/9801/9801c/9801c.htm http://www.javaworld.com/javaworld/jw-09-1997/jw-09-indepth_p.html Today's quote: "We should forget about small efficiencies, say about 97% of the time: premature optimization is the root of all evil." - Donald Knuth -T. Bryan Field-Elliot wrote: > This is incredibly important stuff! I'm sick to death of making tons of > EJB entity beans, and then "Value Objects" (or data objects) which are > very similar, and with Struts, "Form Beans" which again are very > similar. Often I wish I could just use generic property sets (using > HashMap, or any other generic collection). But I have resisted on > principle, because I thought it would be a poor performer compared to > "straight Java" variables and getters and setters. But here you are > saying "reflection is no longer a point of concern". What information > have you got in this regard? > > Also, you go on to say 'ditto for objection creation", and that it's > "more expensive to cache an object than recreate it". Where are you > getting this information? It goes against the design considerations of > virtually every "highly optimized" Java system I've seen, including EJB > which goes to EXTREME lengths to reuse rather than recreate. You see the > same pattern with JSP custom tags (nowadays they are pooled), and you > even see the same thing in the Servlet spec design (which is to have one > multithreaded instance of the servlet class, rather than one per user > which would make more logical sense). > > So, my apologies if this is off-topic of Struts, but these seem like > very important and impactful design issues, relevent (even if > peripherally) to good Struts design and development. > > Thanks, > > Bryan