You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@turbine.apache.org by John McNally <jm...@collab.net> on 2001/03/13 02:25:48 UTC

pool service and recyclable

Is there any object to the addition of the following that can allow the
pooling of objects which can be recycled without reflection?

John McNally

? org/apache/turbine/util/pool/SimpleRecyclable.java


/**
 * An interface for objects that can be pooled and
 * recycled several times by different clients.  This interface
 * presents a recycle method that does not require
introspection/reflection.
 *
 * @author <a href="mailto:jmcnally@collab.net">John McNally</a>
 * @version $Id: $
 */
public interface SimpleRecyclable extends Recyclable
{
    /**
     * Recycles the object for a new client. Objects implementing
     * this interface must also provide a matching constructor.
     * The recycle methods must call their super.
     */
    public void recycle(Object[] params);
}




Index: org/apache/turbine/services/pool/TurbinePoolService.java
===================================================================
RCS file:
/home/cvs/jakarta-turbine/src/java/org/apache/turbine/services/pool/TurbinePoolService.java,v
retrieving revision 1.3
diff -u -r1.3 TurbinePoolService.java
--- org/apache/turbine/services/pool/TurbinePoolService.java	2001/03/06
06:12:35	1.3
+++ org/apache/turbine/services/pool/TurbinePoolService.java	2001/03/13
01:15:31
@@ -98,6 +98,11 @@
         private BoundedBuffer pool;
 
         /**
+         * A flag to determine if a more efficient recycler is
implemented.
+         */
+        private boolean simpleRecyclable;
+
+        /**
          * A cache for recycling methods.
          */
         private HashMap recyclers;
@@ -113,6 +118,17 @@
         }
 
         /**
+         * Tells pool that it contains objects which can be
+         * initialized using an Object array.
+         *
+         * @param isSimple a <code>boolean</code> value
+         */
+        public void setSimpleRecyclable(boolean isSimple)
+        {
+            simpleRecyclable = isSimple;
+        }
+
+        /**
          * Polls for an instance from the pool.
          *
          * @return an instance or null.
@@ -122,8 +138,13 @@
                            throws TurbineException
         {
             Object instance = pool.poll();
-            if ((instance != null) &&
-                (instance instanceof Recyclable))
+          if (instance != null)
+          {    
+            if (simpleRecyclable)
+            {
+                ((SimpleRecyclable) instance).recycle(params);
+            }
+            else if (instance instanceof Recyclable)
             {
                 try
                 {
@@ -163,6 +184,7 @@
                         "Recycling failed for " +
instance.getClass().getName(),x);
                 }
             }
+          }
             return instance;
         }
 
@@ -400,6 +422,11 @@
                 repository = (HashMap) repository.clone();
                 repository.put(className,pool);
                 poolRepository = repository;
+                
+                if (instance instanceof SimpleRecyclable) 
+                {
+                    pool.setSimpleRecyclable(true);
+                }
             }
             return pool.offer(instance);
         }

---------------------------------------------------------------------
To unsubscribe, e-mail: turbine-dev-unsubscribe@jakarta.apache.org
For additional commands, e-mail: turbine-dev-help@jakarta.apache.org


Re: pool service and recyclable

Posted by John McNally <jm...@collab.net>.
That should be objection
			
John McNally wrote:
> 
> Is there any s/object/objection/ to the addition of the following that can allow the
> pooling of objects which can be recycled without reflection?
> 
> John McNally
> 
> ? org/apache/turbine/util/pool/SimpleRecyclable.java
> 
> /**
>  * An interface for objects that can be pooled and
>  * recycled several times by different clients.  This interface
>  * presents a recycle method that does not require
> introspection/reflection.
>  *
>  * @author <a href="mailto:jmcnally@collab.net">John McNally</a>
>  * @version $Id: $
>  */
> public interface SimpleRecyclable extends Recyclable
> {
>     /**
>      * Recycles the object for a new client. Objects implementing
>      * this interface must also provide a matching constructor.
>      * The recycle methods must call their super.
>      */
>     public void recycle(Object[] params);
> }
> 
> Index: org/apache/turbine/services/pool/TurbinePoolService.java
> ===================================================================
> RCS file:
> /home/cvs/jakarta-turbine/src/java/org/apache/turbine/services/pool/TurbinePoolService.java,v
> retrieving revision 1.3
> diff -u -r1.3 TurbinePoolService.java
> --- org/apache/turbine/services/pool/TurbinePoolService.java    2001/03/06
> 06:12:35        1.3
> +++ org/apache/turbine/services/pool/TurbinePoolService.java    2001/03/13
> 01:15:31
> @@ -98,6 +98,11 @@
>          private BoundedBuffer pool;
> 
>          /**
> +         * A flag to determine if a more efficient recycler is
> implemented.
> +         */
> +        private boolean simpleRecyclable;
> +
> +        /**
>           * A cache for recycling methods.
>           */
>          private HashMap recyclers;
> @@ -113,6 +118,17 @@
>          }
> 
>          /**
> +         * Tells pool that it contains objects which can be
> +         * initialized using an Object array.
> +         *
> +         * @param isSimple a <code>boolean</code> value
> +         */
> +        public void setSimpleRecyclable(boolean isSimple)
> +        {
> +            simpleRecyclable = isSimple;
> +        }
> +
> +        /**
>           * Polls for an instance from the pool.
>           *
>           * @return an instance or null.
> @@ -122,8 +138,13 @@
>                             throws TurbineException
>          {
>              Object instance = pool.poll();
> -            if ((instance != null) &&
> -                (instance instanceof Recyclable))
> +          if (instance != null)
> +          {
> +            if (simpleRecyclable)
> +            {
> +                ((SimpleRecyclable) instance).recycle(params);
> +            }
> +            else if (instance instanceof Recyclable)
>              {
>                  try
>                  {
> @@ -163,6 +184,7 @@
>                          "Recycling failed for " +
> instance.getClass().getName(),x);
>                  }
>              }
> +          }
>              return instance;
>          }
> 
> @@ -400,6 +422,11 @@
>                  repository = (HashMap) repository.clone();
>                  repository.put(className,pool);
>                  poolRepository = repository;
> +
> +                if (instance instanceof SimpleRecyclable)
> +                {
> +                    pool.setSimpleRecyclable(true);
> +                }
>              }
>              return pool.offer(instance);
>          }

---------------------------------------------------------------------
To unsubscribe, e-mail: turbine-dev-unsubscribe@jakarta.apache.org
For additional commands, e-mail: turbine-dev-help@jakarta.apache.org


Re: pool service and recyclable

Posted by Sean Legassick <se...@informage.net>.
In message <ND...@nokia.com>, 
Ilkka Priha <ex...@nokia.com> writes
>Excuse me, but did you you miss my last posting on this topic? I realized a
>little late the same thing that John explains below, a standardized (through
>an interface) recycle() method is at least as good as an object specific
>init method.

Sure, I can see that. The discussion is slightly muddied by the 
reference to the init(Object) method in ApplicationTool, which is also a 
standardized interface method - but ApplicationTool-implementing classes 
are just one example of a more general class of recyclable objects, so 
perhaps the generalization does indeed belong in a Recyclable interface 
instead.

I guess I was just querying John's specific justification for rejecting 
the use of an init() method which seemed a bit tenuous to me (related to 
wanting to do expensive work once only)...

-- 
Sean Legassick
sean@informage.net
         Czlowiekiem jestem i nic co ludzkie nie jest mi obce

---------------------------------------------------------------------
To unsubscribe, e-mail: turbine-dev-unsubscribe@jakarta.apache.org
For additional commands, e-mail: turbine-dev-help@jakarta.apache.org


RE: pool service and recyclable

Posted by Ilkka Priha <ex...@nokia.com>.
Excuse me, but did you you miss my last posting on this topic? I realized a
little late the same thing that John explains below, a standardized (through
an interface) recycle() method is at least as good as an object specific
init method.

-- Ilkka

[mailto:ext-ilkka.priha@nokia.com]


>You are right about the performance, I got almost 20x slower results, which
>was a surprise for me. You are also right, that the interface fits well to
>the service itself, only not so well to the objects to be pooled. But on
the
>second thought, the difference between an object based init() method and a
>standardized recycle(Objects[]) method is not remarkable, we're already
>using the same kind of approach with services, i.e. init(Object). Maybe I
>was too hurried with my opinions, sorry about that.
>
>So +1 for the SimpleRecyclable interface :-)


> -----Original Message-----
> From: jmcnally [mailto:jmcnally]On Behalf Of John McNally
> Sent: Thursday, March 15, 2001 03:36
> To: turbine-dev@jakarta.apache.org
> Subject: Re: pool service and recyclable
>
>
> Sean Legassick wrote:
> >
> > In message <3A...@collab.net>, John McNally
> > <jm...@collab.net> writes
> > >It is easy in some cases to get around the reflection by defining no
> > >argument constructor/recycle methods and then using an init(...) method
> > >to initialize the object which I have done and it looks like Jason has
> > >done in the pull service.
> >
> > (that was me actually - all the pooling done by the pull service is part
> > of my recent changes)
> >
> > > But sometimes you would like to have a
> > >constructor that caches some expensive operations and takes some
> > >arguments, and has a corresponding recycle method.
> >
> > Couldn't you use init and some internal state that indicates whether the
> > expensive operations have been done yet though? (Like booleans or
> > references which start null?)
>
>
> yes you could, I guess I was exaggerating the problem by stating
> sometimes you might have two init methods because I was not satisfied
> with Ilkka's reason's for rejection.  I started off doing the same sort
> of thing using an init method to get around the reflection.  I felt like
> I was not doing things properly and breaking the constructor/recycle
> interface which seemed to me very elegant.  So I was attempting to
> provide a method around the reflection that kept this interface.  Since
> Ilkka said he thinks the init method is considered good or at least okay
> form and now you are joining him I am fine with it.
>
> >
> > >  I am just trying to
> > >standardize the way a class might be built if it is planned to
> be pooled
> > >during design.  There is no reason to suffer the inefficiency  of
> > >reflection if you have complete freedom in the pooled object design.
> > >
> > >The secondary issue was whether to cache the instanceof results.  I
> > >would say my tests show that a simple boolean check is faster than an
> > >instanceof check (big surprise).  I would say the results are not so
> > >dramatic as to bring me to avoid the use of instanceof, but
> why make the
> > >check every time an object is requested when the result will always be
> > >the same for the same pool?
> >
> > Performance freakdom here we come! But seriously its great to see this
> > level of detail applied to optimising Turbine's core performance, as
> > we'll all benefit. I'm curious though to know whether anyone's done any
> > overall profiling on the framework to see what the major bottleneck's
> > are?
> >
>
> No, it would certainly be worthwile.
>
> John McNally
>
> ---------------------------------------------------------------------
> To unsubscribe, e-mail: turbine-dev-unsubscribe@jakarta.apache.org
> For additional commands, e-mail: turbine-dev-help@jakarta.apache.org
>


---------------------------------------------------------------------
To unsubscribe, e-mail: turbine-dev-unsubscribe@jakarta.apache.org
For additional commands, e-mail: turbine-dev-help@jakarta.apache.org


Re: pool service and recyclable

Posted by John McNally <jm...@collab.net>.
Sean Legassick wrote:
> 
> In message <3A...@collab.net>, John McNally
> <jm...@collab.net> writes
> >It is easy in some cases to get around the reflection by defining no
> >argument constructor/recycle methods and then using an init(...) method
> >to initialize the object which I have done and it looks like Jason has
> >done in the pull service.
> 
> (that was me actually - all the pooling done by the pull service is part
> of my recent changes)
> 
> > But sometimes you would like to have a
> >constructor that caches some expensive operations and takes some
> >arguments, and has a corresponding recycle method.
> 
> Couldn't you use init and some internal state that indicates whether the
> expensive operations have been done yet though? (Like booleans or
> references which start null?)


yes you could, I guess I was exaggerating the problem by stating
sometimes you might have two init methods because I was not satisfied
with Ilkka's reason's for rejection.  I started off doing the same sort
of thing using an init method to get around the reflection.  I felt like
I was not doing things properly and breaking the constructor/recycle
interface which seemed to me very elegant.  So I was attempting to
provide a method around the reflection that kept this interface.  Since
Ilkka said he thinks the init method is considered good or at least okay
form and now you are joining him I am fine with it.

> 
> >  I am just trying to
> >standardize the way a class might be built if it is planned to be pooled
> >during design.  There is no reason to suffer the inefficiency  of
> >reflection if you have complete freedom in the pooled object design.
> >
> >The secondary issue was whether to cache the instanceof results.  I
> >would say my tests show that a simple boolean check is faster than an
> >instanceof check (big surprise).  I would say the results are not so
> >dramatic as to bring me to avoid the use of instanceof, but why make the
> >check every time an object is requested when the result will always be
> >the same for the same pool?
> 
> Performance freakdom here we come! But seriously its great to see this
> level of detail applied to optimising Turbine's core performance, as
> we'll all benefit. I'm curious though to know whether anyone's done any
> overall profiling on the framework to see what the major bottleneck's
> are?
> 

No, it would certainly be worthwile.

John McNally

---------------------------------------------------------------------
To unsubscribe, e-mail: turbine-dev-unsubscribe@jakarta.apache.org
For additional commands, e-mail: turbine-dev-help@jakarta.apache.org


Re: pool service and recyclable

Posted by Santiago Gala <sg...@hisitech.com>.
Sean Legassick wrote:

> In message <3A...@collab.net>, John McNally 
> <jm...@collab.net> writes
> 
>> It is easy in some cases to get around the reflection by defining no
>> argument constructor/recycle methods and then using an init(...) method
>> to initialize the object which I have done and it looks like Jason has
>> done in the pull service.
> 
> 
> (that was me actually - all the pooling done by the pull service is part 
> of my recent changes)
> 
>> But sometimes you would like to have a
>> constructor that caches some expensive operations and takes some
>> arguments, and has a corresponding recycle method.
> 
> 
> Couldn't you use init and some internal state that indicates whether the 
> expensive operations have been done yet though? (Like booleans or 
> references which start null?)
> 
>>  I am just trying to
>> standardize the way a class might be built if it is planned to be pooled
>> during design.  There is no reason to suffer the inefficiency  of
>> reflection if you have complete freedom in the pooled object design.
>> 
>> The secondary issue was whether to cache the instanceof results.  I
>> would say my tests show that a simple boolean check is faster than an
>> instanceof check (big surprise).  I would say the results are not so
>> dramatic as to bring me to avoid the use of instanceof, but why make the
>> check every time an object is requested when the result will always be
>> the same for the same pool?
> 
> 
> Performance freakdom here we come! But seriously its great to see this 
> level of detail applied to optimising Turbine's core performance, as 
> we'll all benefit. I'm curious though to know whether anyone's done any 
> overall profiling on the framework to see what the major bottleneck's are?

I did some allocation profiling of jetspeed. One curious thing I found 
is that URLEncoder/URLDecoder are major (remaining) memory bottlenecks, 
as they are used quite a few times in DynamicURI to encode/decode 
parameters (quite used in Jetspeed), and they allocate a number of 
ByteArrays for each call to URLEncoder.encode() or URLDecoder.decode(). 
Some of these ByteArrays have, further, to grow due to size of the URI 
being large, which causes more allocation.

We have other jetspeed bottlenecks still there. I don't remember any 
other significant bottleneck in turbine after the last pooling was done.


---------------------------------------------------------------------
To unsubscribe, e-mail: turbine-dev-unsubscribe@jakarta.apache.org
For additional commands, e-mail: turbine-dev-help@jakarta.apache.org


Re: pool service and recyclable

Posted by Sean Legassick <se...@informage.net>.
In message <3A...@collab.net>, John McNally 
<jm...@collab.net> writes
>It is easy in some cases to get around the reflection by defining no
>argument constructor/recycle methods and then using an init(...) method
>to initialize the object which I have done and it looks like Jason has
>done in the pull service.

(that was me actually - all the pooling done by the pull service is part 
of my recent changes)

> But sometimes you would like to have a
>constructor that caches some expensive operations and takes some
>arguments, and has a corresponding recycle method.

Couldn't you use init and some internal state that indicates whether the 
expensive operations have been done yet though? (Like booleans or 
references which start null?)

>  I am just trying to
>standardize the way a class might be built if it is planned to be pooled
>during design.  There is no reason to suffer the inefficiency  of
>reflection if you have complete freedom in the pooled object design.
>
>The secondary issue was whether to cache the instanceof results.  I
>would say my tests show that a simple boolean check is faster than an
>instanceof check (big surprise).  I would say the results are not so
>dramatic as to bring me to avoid the use of instanceof, but why make the
>check every time an object is requested when the result will always be
>the same for the same pool?

Performance freakdom here we come! But seriously its great to see this 
level of detail applied to optimising Turbine's core performance, as 
we'll all benefit. I'm curious though to know whether anyone's done any 
overall profiling on the framework to see what the major bottleneck's 
are?

-- 
Sean Legassick
sean@informage.net

---------------------------------------------------------------------
To unsubscribe, e-mail: turbine-dev-unsubscribe@jakarta.apache.org
For additional commands, e-mail: turbine-dev-help@jakarta.apache.org


Re: pool service and recyclable

Posted by Daniel Rall <dl...@collab.net>.
John McNally <jm...@collab.net> writes:

> Finally I tried using a try/catch block to avoid the use of an
> instanceof,  I got a result of 215, so it appears it is slightly faster
> using instance of, but again the results are not so dramatic that I
> would suggest we drop instanceof checks.

I agree that in light of your findings instanceof checks are the way
to go.  They are much more explicit than the try/cast/cache scenario.
-- 

Daniel Rall <dl...@collab.net>

---------------------------------------------------------------------
To unsubscribe, e-mail: turbine-dev-unsubscribe@jakarta.apache.org
For additional commands, e-mail: turbine-dev-help@jakarta.apache.org


RE: pool service and recyclable

Posted by Ilkka Priha <ex...@nokia.com>.
> -----Original Message-----
> From: jmcnally [mailto:jmcnally]On Behalf Of John McNally
> Sent: Wednesday, March 14, 2001 00:12
> To: turbine-dev@jakarta.apache.org
> Subject: Re: pool service and recyclable

The order of the comments of the original message has been changed below.

> > type castings that can cause run-time errors,
>
> I did not remove any type checking or add any casts without a type
> check, so how is this possible?  What I meant by the extended interface
> was that if an object took an object array as the constructor it could
> just let the service know that it can skip the reflection, the object
> knows what to do with it.
>
> > creation of an object array to
> > get a pooled object although the main goal of a pool is to avoid memory
> > allocation don't provide as clean solution as using a default
> constructor
> > and a separate init method to drop the final msecs off.
>
> How can I get an object that uses a constructor with arguments from the
> service without constructing an object array?  The way I read it I can
> save the construction of a String[].


The current args based pooling has the same problems, it needs the Objects[]
and in addition the String[] array. It as well gets objects as parameters
and run-time type casting is needed, instead of compile-time checks, to get
the job done. That's exactly the reason why I prefered the default
constructor/init approach to both args based approaches.


> I am in the habit lately of giving too much time to performance gains
> and I might step on some oo principles, but I was trying to live within
> the spirit of the interface
>
> constructor(args)/recycle(args)
>
> instead of working around the interface to get the pooling benefits
> without the performance hit by doing something like
>
> constructor()/firstInit(args)/init(args)/recycle()
>
> But I do not consider a 10x performance improvement small and will
> construct my objects the second way, especially since you have said it
> is the preferred way to avoid the reflection.


You are right about the performance, I got almost 20x slower results, which
was a surprise for me. You are also right, that the interface fits well to
the service itself, only not so well to the objects to be pooled. But on the
second thought, the difference between an object based init() method and a
standardized recycle(Objects[]) method is not remarkable, we're already
using the same kind of approach with services, i.e. init(Object). Maybe I
was too hurried with my opinions, sorry about that.

So +1 for the SimpleRecyclable interface :-)

-- Ilkka

[mailto:ext-ilkka.priha@nokia.com]


> ---------------------------------------------------------------------
> To unsubscribe, e-mail: turbine-dev-unsubscribe@jakarta.apache.org
> For additional commands, e-mail: turbine-dev-help@jakarta.apache.org
>


---------------------------------------------------------------------
To unsubscribe, e-mail: turbine-dev-unsubscribe@jakarta.apache.org
For additional commands, e-mail: turbine-dev-help@jakarta.apache.org


Re: pool service and recyclable

Posted by John McNally <jm...@collab.net>.
Ilkka Priha wrote:
> 
> Thanks for the clarification, now I understand your goal better. However, I
> personally prefer clear design to quite small performance improvement. I
> mean that an additional parallel interface for the same functional purpose,

I am in the habit lately of giving too much time to performance gains
and I might step on some oo principles, but I was trying to live within
the spirit of the interface

constructor(args)/recycle(args)

instead of working around the interface to get the pooling benefits
without the performance hit by doing something like

constructor()/firstInit(args)/init(args)/recycle()

But I do not consider a 10x performance improvement small and will
construct my objects the second way, especially since you have said it
is the preferred way to avoid the reflection.

> type castings that can cause run-time errors,

I did not remove any type checking or add any casts without a type
check, so how is this possible?  What I meant by the extended interface
was that if an object took an object array as the constructor it could
just let the service know that it can skip the reflection, the object
knows what to do with it.

> creation of an object array to
> get a pooled object although the main goal of a pool is to avoid memory
> allocation don't provide as clean solution as using a default constructor
> and a separate init method to drop the final msecs off.

How can I get an object that uses a constructor with arguments from the
service without constructing an object array?  The way I read it I can
save the construction of a String[].

> Instead I support
> any optimizations inside the pool, like caching the instanceof result (not
> the try-catch approach), as they do not affect the design of the objects to
> be pooled, but are internal matters of an efficient implementation of the
> specified functionality.

I agree with the instanceof vs. try-catch approach conclusion and I do
not think I worded the conclusions of my test correctly.  It appears
instanceof is as fast as the try-catch approach and it is certainly nice
that the correct implementation is not slow.  Earlier I was just
responding to dlr's pondering on the cost of an instanceof check with
something I remembered reading.  I was not recommending the try-catch as
a solution to anything, but at least now I have tested it and will not
be gritting my teeth every time I choose to use instanceof.

John McNally


> 
> > -----Original Message-----
> > From: jmcnally [mailto:jmcnally]On Behalf Of John McNally
> > Sent: Tuesday, March 13, 2001 20:06
> > To: turbine-dev@jakarta.apache.org
> > Subject: Re: pool service and recyclable
> >
> >
> > I ran a few tests of my own because I am not sure you caught the purpose
> > of my changes.  I created two objects with a method that takes 3
> > arguments.  One uses reflection (cached) and the other uses direct
> > method invocation.
> >
> >
> > (minus the try-catch test)
> >                       reverse order forward order
> > reflection/instanceof     3300           3200
> > noreflection/instanceof    375            375
> > reflection/noinstanceof   2650           2800
> > noreflection/noinstanceof  100            205
> >
> > where forward refers to the order shown below and reverse simply runs
> > from bottom to top.  These results show the expected 10X or better
> > improvement by not using reflection.  And that is the intention of the
> > patch.
> >
> > It is easy in some cases to get around the reflection by defining no
> > argument constructor/recycle methods and then using an init(...) method
> > to initialize the object which I have done and it looks like Jason has
> > done in the pull service.  But sometimes you would like to have a
> > constructor that caches some expensive operations and takes some
> > arguments, and has a corresponding recycle method.  I am just trying to
> > standardize the way a class might be built if it is planned to be pooled
> > during design.  There is no reason to suffer the inefficiency  of
> > reflection if you have complete freedom in the pooled object design.
> >
> > The secondary issue was whether to cache the instanceof results.  I
> > would say my tests show that a simple boolean check is faster than an
> > instanceof check (big surprise).  I would say the results are not so
> > dramatic as to bring me to avoid the use of instanceof, but why make the
> > check every time an object is requested when the result will always be
> > the same for the same pool?
> >
> > Finally I tried using a try/catch block to avoid the use of an
> > instanceof,  I got a result of 215, so it appears it is slightly faster
> > using instance of, but again the results are not so dramatic that I
> > would suggest we drop instanceof checks.
> >

---------------------------------------------------------------------
To unsubscribe, e-mail: turbine-dev-unsubscribe@jakarta.apache.org
For additional commands, e-mail: turbine-dev-help@jakarta.apache.org


RE: pool service and recyclable

Posted by Ilkka Priha <ex...@nokia.com>.
Thanks for the clarification, now I understand your goal better. However, I
personally prefer clear design to quite small performance improvement. I
mean that an additional parallel interface for the same functional purpose,
type castings that can cause run-time errors, creation of an object array to
get a pooled object although the main goal of a pool is to avoid memory
allocation don't provide as clean solution as using a default constructor
and a separate init method to drop the final msecs off. Instead I support
any optimizations inside the pool, like caching the instanceof result (not
the try-catch approach), as they do not affect the design of the objects to
be pooled, but are internal matters of an efficient implementation of the
specified functionality.

-- Ilkka

[mailto:ext-ilkka.priha@nokia.com]


> -----Original Message-----
> From: jmcnally [mailto:jmcnally]On Behalf Of John McNally
> Sent: Tuesday, March 13, 2001 20:06
> To: turbine-dev@jakarta.apache.org
> Subject: Re: pool service and recyclable
>
>
> I ran a few tests of my own because I am not sure you caught the purpose
> of my changes.  I created two objects with a method that takes 3
> arguments.  One uses reflection (cached) and the other uses direct
> method invocation.
>
>
> (minus the try-catch test)
> 			reverse order forward order
> reflection/instanceof     3300           3200
> noreflection/instanceof    375            375
> reflection/noinstanceof   2650           2800
> noreflection/noinstanceof  100            205
>
> where forward refers to the order shown below and reverse simply runs
> from bottom to top.  These results show the expected 10X or better
> improvement by not using reflection.  And that is the intention of the
> patch.
>
> It is easy in some cases to get around the reflection by defining no
> argument constructor/recycle methods and then using an init(...) method
> to initialize the object which I have done and it looks like Jason has
> done in the pull service.  But sometimes you would like to have a
> constructor that caches some expensive operations and takes some
> arguments, and has a corresponding recycle method.  I am just trying to
> standardize the way a class might be built if it is planned to be pooled
> during design.  There is no reason to suffer the inefficiency  of
> reflection if you have complete freedom in the pooled object design.
>
> The secondary issue was whether to cache the instanceof results.  I
> would say my tests show that a simple boolean check is faster than an
> instanceof check (big surprise).  I would say the results are not so
> dramatic as to bring me to avoid the use of instanceof, but why make the
> check every time an object is requested when the result will always be
> the same for the same pool?
>
> Finally I tried using a try/catch block to avoid the use of an
> instanceof,  I got a result of 215, so it appears it is slightly faster
> using instance of, but again the results are not so dramatic that I
> would suggest we drop instanceof checks.
>
> John McNally
>
> public interface SimpleRecyclable
> {
>     public void recycle(Object[] params);
> }
>
> public interface Recyclable
> {
>     public void recycle(Integer i, String s1, String s2);
> }
>
>
> public class SimpleRecObject implements SimpleRecyclable
> {
>     int i;
>     String s;
>     String ss;
>     public void recycle(Object[] params)
>     {
>         i = ((Integer)params[0]).intValue();
>         s = (String)params[1];
>         ss = (String)params[2];
>     }
> }
>
> public class RecObject implements Recyclable
> {
>     int i;
>     String s;
>     String ss;
>     public void recycle(Integer ia, String sa, String ssa)
>     {
>         i = ia.intValue();
>         s = sa;
>         ss = ssa;
>     }
> }
>
> import java.lang.reflect.Method;
>
> public class TestReflection
> {
>     Recyclable r = new RecObject();
>     SimpleRecyclable sr = new SimpleRecObject();
>
>
> public static void main(String[] args)
>     throws Exception
> {
>     TestReflection trf = new TestReflection();
>
>     Object[] oa = new Object[2];
>     oa[0] = trf.r;
>     oa[1] = trf.sr;
>
>     boolean[] ba = {true, false};
>
>     Object[] olsa = new Object[3];
>     olsa[0] = new Integer(1);
>     olsa[1] = "adf";
>     olsa[2] = "gfds";
>
>     Class[] clsa = new Class[3];
>     clsa[0] = olsa[0].getClass();
>     clsa[1] = olsa[1].getClass();
>     clsa[2] = olsa[2].getClass();
>     Method m = trf.r.getClass().getMethod("recycle", clsa);
>
>     long nowg = System.currentTimeMillis();
>     for (int i = 0; i < 1000000; i++)
>     {
>         int q = i % 2;
>         if (!ba[q])
>           ((SimpleRecyclable)trf.sr).recycle(olsa);
>     }
>     long nowh = System.currentTimeMillis();
>     System.out.println("Time for noreflection/noinstanceof" + (nowh -
> nowg));
>
>     long nowe = System.currentTimeMillis();
>     for (int i = 0; i < 1000000; i++)
>     {
>         int q = i % 2;
>         if (ba[q])
>           m.invoke(trf.r, olsa);
>     }
>     long nowf = System.currentTimeMillis();
>     System.out.println("Time for reflection/noinstanceof" + (nowf -
> nowe));
>
>
>     long nowc = System.currentTimeMillis();
>     for (int i = 0; i < 1000000; i++)
>     {
>         int q = i % 2;
>         if (oa[q] instanceof SimpleRecyclable)
>           ((SimpleRecyclable)trf.sr).recycle(olsa);
>     }
>     long nowd = System.currentTimeMillis();
>     System.out.println("Time for noreflection/instanceof" + (nowd -
> nowc));
>
>     long nowa = System.currentTimeMillis();
>     for (int i = 0; i < 1000000; i++)
>     {
>         int q = i % 2;
>         if (oa[q] instanceof Recyclable)
>           m.invoke(trf.r, olsa);
>     }
>     long nowb = System.currentTimeMillis();
>     System.out.println("Time for reflection/instanceof" + (nowb -
> nowa));
>
>
>     long nowi = System.currentTimeMillis();
>     for (int i = 0; i < 1000000; i++)
>     {
>         int q = i % 2;
>         try
>         {
>           ((SimpleRecyclable)trf.sr).recycle(olsa);
>         }
>         catch(Exception e){}
>     }
>     long nowj = System.currentTimeMillis();
>     System.out.println("Time for noreflection/try-catch" + (nowh -
> nowg));
>
> }
> }
>
>
>
> Ilkka Priha wrote:
> >
> > I made a small test calling an object implementing a specific
> interface both
> > with instanceof test and without and the same for an object NOT
> implementing
> > the interface (see below).
> >
> > The result was that the instanceof test didn't have any affect to the
> > execution time for the object that did implement the interface.
> Both loops
> > took 30 msecs.
> >
> > For the object that didn't implement the interface, the
> instanceof checked
> > loop took 210 msecs, but the try-catch loop 13069 msecs. So I recommend
> > calling instanceof whenever needed, the overhead is minimal
> compared to many
> > other operations.
> >
> > The pool service uses reflection only for the first instance
> with a specific
> > constructor. Then it keeps the corresponding recycle method in
> its internal
> > cache and calls it directly instead of reflection. So I don't
> see any need
> > for the new interface.
> >
> > -- Ilkka
> >
> > [mailto:ext-ilkka.priha@nokia.com]
> >
> >     Object test = new Test();
> >     Object test2 = new Test2();
> >
> >     long now = System.currentTimeMillis();
> >     for (int i = 0; i < 1000000; i++)
> >     {
> >         if (test instanceof Callable)
> >           ((Callable) test).invoke();
> >     }
> >     System.out.println(System.currentTimeMillis() - now);
> >
> >     now = System.currentTimeMillis();
> >     for (int i = 0; i < 1000000; i++)
> >     {
> >         try { ((Callable) test).invoke(); }
> >         catch (Exception x) { }
> >     }
> >     System.out.println(System.currentTimeMillis() - now);
> >
> >     now = System.currentTimeMillis();
> >     for (int i = 0; i < 1000000; i++)
> >     {
> >         if (test2 instanceof Callable)
> >           ((Callable) test2).invoke();
> >     }
> >     System.out.println(System.currentTimeMillis() - now);
> >
> >     now = System.currentTimeMillis();
> >     for (int i = 0; i < 1000000; i++)
> >     {
> >         try { ((Callable) test2).invoke(); }
> >         catch (Exception x) { }
> >     }
> >     System.out.println(System.currentTimeMillis() - now);
> >
> > > -----Original Message-----
> > > From: jmcnally [mailto:jmcnally]On Behalf Of John McNally
> > > Sent: Tuesday, March 13, 2001 04:24
> > > To: turbine-dev@jakarta.apache.org
> > > Subject: Re: pool service and recyclable
> > >
> > >
> > > I read somewhere that it is faster to just attempt a cast inside a try
> > > block than to call instanceof.  That is the reason I wrote
> this so that
> > > the instanceof is only called for the first object that is put into a
> > > pool and the result is stored as a boolean attribute of the pool.  I
> > > believe something similar could be done for Recyclable objects, but I
> > > was trying to make my patch minimally disruptive.
> > >
> > > John McNally
> > >
> > > Daniel Rall wrote:
> > > >
> > > > John McNally <jm...@collab.net> writes:
> > > >
> > > > > Is there any objection to the addition of the following that
> > > can allow the
> > > > > pooling of objects which can be recycled without reflection?
> > > >
> > > > Looks okay to me.  Anything to remove reflection.  Does
> instanceof use
> > > > reflection, or does it just use getClass() internally?  Does anyone
> > > > know?  I guess we could always disassemble the bytecode.
> > > > --
> > > >
> > > > Daniel Rall <dl...@collab.net>
> > > >
> > > >
> ---------------------------------------------------------------------
> > > > To unsubscribe, e-mail: turbine-dev-unsubscribe@jakarta.apache.org
> > > > For additional commands, e-mail: turbine-dev-help@jakarta.apache.org
> > >
> > > ---------------------------------------------------------------------
> > > To unsubscribe, e-mail: turbine-dev-unsubscribe@jakarta.apache.org
> > > For additional commands, e-mail: turbine-dev-help@jakarta.apache.org
> > >
> >
> > ---------------------------------------------------------------------
> > To unsubscribe, e-mail: turbine-dev-unsubscribe@jakarta.apache.org
> > For additional commands, e-mail: turbine-dev-help@jakarta.apache.org
>
> ---------------------------------------------------------------------
> To unsubscribe, e-mail: turbine-dev-unsubscribe@jakarta.apache.org
> For additional commands, e-mail: turbine-dev-help@jakarta.apache.org
>


---------------------------------------------------------------------
To unsubscribe, e-mail: turbine-dev-unsubscribe@jakarta.apache.org
For additional commands, e-mail: turbine-dev-help@jakarta.apache.org


Re: pool service and recyclable

Posted by John McNally <jm...@collab.net>.
I ran a few tests of my own because I am not sure you caught the purpose
of my changes.  I created two objects with a method that takes 3
arguments.  One uses reflection (cached) and the other uses direct
method invocation.


(minus the try-catch test)
			reverse order forward order
reflection/instanceof     3300           3200
noreflection/instanceof    375            375
reflection/noinstanceof   2650           2800
noreflection/noinstanceof  100            205

where forward refers to the order shown below and reverse simply runs
from bottom to top.  These results show the expected 10X or better
improvement by not using reflection.  And that is the intention of the
patch.  

It is easy in some cases to get around the reflection by defining no
argument constructor/recycle methods and then using an init(...) method
to initialize the object which I have done and it looks like Jason has
done in the pull service.  But sometimes you would like to have a
constructor that caches some expensive operations and takes some
arguments, and has a corresponding recycle method.  I am just trying to
standardize the way a class might be built if it is planned to be pooled
during design.  There is no reason to suffer the inefficiency  of
reflection if you have complete freedom in the pooled object design.

The secondary issue was whether to cache the instanceof results.  I
would say my tests show that a simple boolean check is faster than an
instanceof check (big surprise).  I would say the results are not so
dramatic as to bring me to avoid the use of instanceof, but why make the
check every time an object is requested when the result will always be
the same for the same pool?

Finally I tried using a try/catch block to avoid the use of an
instanceof,  I got a result of 215, so it appears it is slightly faster
using instance of, but again the results are not so dramatic that I
would suggest we drop instanceof checks.

John McNally

public interface SimpleRecyclable
{
    public void recycle(Object[] params);
}

public interface Recyclable
{
    public void recycle(Integer i, String s1, String s2);
}


public class SimpleRecObject implements SimpleRecyclable
{
    int i;
    String s;
    String ss;
    public void recycle(Object[] params)
    {
        i = ((Integer)params[0]).intValue();
        s = (String)params[1];
        ss = (String)params[2];
    }
}

public class RecObject implements Recyclable
{
    int i;
    String s;
    String ss;
    public void recycle(Integer ia, String sa, String ssa)
    {
        i = ia.intValue();
        s = sa;
        ss = ssa;
    }
}

import java.lang.reflect.Method;

public class TestReflection
{
    Recyclable r = new RecObject();
    SimpleRecyclable sr = new SimpleRecObject();


public static void main(String[] args)
    throws Exception
{
    TestReflection trf = new TestReflection();

    Object[] oa = new Object[2];
    oa[0] = trf.r;
    oa[1] = trf.sr;

    boolean[] ba = {true, false};

    Object[] olsa = new Object[3];
    olsa[0] = new Integer(1);
    olsa[1] = "adf";
    olsa[2] = "gfds";

    Class[] clsa = new Class[3];
    clsa[0] = olsa[0].getClass();
    clsa[1] = olsa[1].getClass();
    clsa[2] = olsa[2].getClass();
    Method m = trf.r.getClass().getMethod("recycle", clsa);

    long nowg = System.currentTimeMillis();
    for (int i = 0; i < 1000000; i++)
    {
        int q = i % 2;
        if (!ba[q])
          ((SimpleRecyclable)trf.sr).recycle(olsa);
    }
    long nowh = System.currentTimeMillis();
    System.out.println("Time for noreflection/noinstanceof" + (nowh -
nowg));

    long nowe = System.currentTimeMillis();
    for (int i = 0; i < 1000000; i++)
    {
        int q = i % 2;
        if (ba[q])
          m.invoke(trf.r, olsa);
    }
    long nowf = System.currentTimeMillis();
    System.out.println("Time for reflection/noinstanceof" + (nowf -
nowe));


    long nowc = System.currentTimeMillis();
    for (int i = 0; i < 1000000; i++)
    {
        int q = i % 2;
        if (oa[q] instanceof SimpleRecyclable)
          ((SimpleRecyclable)trf.sr).recycle(olsa);
    }
    long nowd = System.currentTimeMillis();
    System.out.println("Time for noreflection/instanceof" + (nowd -
nowc));

    long nowa = System.currentTimeMillis();
    for (int i = 0; i < 1000000; i++)
    {
        int q = i % 2;
        if (oa[q] instanceof Recyclable)
          m.invoke(trf.r, olsa);
    }
    long nowb = System.currentTimeMillis();
    System.out.println("Time for reflection/instanceof" + (nowb -
nowa));


    long nowi = System.currentTimeMillis();
    for (int i = 0; i < 1000000; i++)
    {
        int q = i % 2;
        try 
        {
          ((SimpleRecyclable)trf.sr).recycle(olsa);
        }
        catch(Exception e){}
    }
    long nowj = System.currentTimeMillis();
    System.out.println("Time for noreflection/try-catch" + (nowh -
nowg));

}
}



Ilkka Priha wrote:
> 
> I made a small test calling an object implementing a specific interface both
> with instanceof test and without and the same for an object NOT implementing
> the interface (see below).
> 
> The result was that the instanceof test didn't have any affect to the
> execution time for the object that did implement the interface. Both loops
> took 30 msecs.
> 
> For the object that didn't implement the interface, the instanceof checked
> loop took 210 msecs, but the try-catch loop 13069 msecs. So I recommend
> calling instanceof whenever needed, the overhead is minimal compared to many
> other operations.
> 
> The pool service uses reflection only for the first instance with a specific
> constructor. Then it keeps the corresponding recycle method in its internal
> cache and calls it directly instead of reflection. So I don't see any need
> for the new interface.
> 
> -- Ilkka
> 
> [mailto:ext-ilkka.priha@nokia.com]
> 
>     Object test = new Test();
>     Object test2 = new Test2();
> 
>     long now = System.currentTimeMillis();
>     for (int i = 0; i < 1000000; i++)
>     {
>         if (test instanceof Callable)
>           ((Callable) test).invoke();
>     }
>     System.out.println(System.currentTimeMillis() - now);
> 
>     now = System.currentTimeMillis();
>     for (int i = 0; i < 1000000; i++)
>     {
>         try { ((Callable) test).invoke(); }
>         catch (Exception x) { }
>     }
>     System.out.println(System.currentTimeMillis() - now);
> 
>     now = System.currentTimeMillis();
>     for (int i = 0; i < 1000000; i++)
>     {
>         if (test2 instanceof Callable)
>           ((Callable) test2).invoke();
>     }
>     System.out.println(System.currentTimeMillis() - now);
> 
>     now = System.currentTimeMillis();
>     for (int i = 0; i < 1000000; i++)
>     {
>         try { ((Callable) test2).invoke(); }
>         catch (Exception x) { }
>     }
>     System.out.println(System.currentTimeMillis() - now);
> 
> > -----Original Message-----
> > From: jmcnally [mailto:jmcnally]On Behalf Of John McNally
> > Sent: Tuesday, March 13, 2001 04:24
> > To: turbine-dev@jakarta.apache.org
> > Subject: Re: pool service and recyclable
> >
> >
> > I read somewhere that it is faster to just attempt a cast inside a try
> > block than to call instanceof.  That is the reason I wrote this so that
> > the instanceof is only called for the first object that is put into a
> > pool and the result is stored as a boolean attribute of the pool.  I
> > believe something similar could be done for Recyclable objects, but I
> > was trying to make my patch minimally disruptive.
> >
> > John McNally
> >
> > Daniel Rall wrote:
> > >
> > > John McNally <jm...@collab.net> writes:
> > >
> > > > Is there any objection to the addition of the following that
> > can allow the
> > > > pooling of objects which can be recycled without reflection?
> > >
> > > Looks okay to me.  Anything to remove reflection.  Does instanceof use
> > > reflection, or does it just use getClass() internally?  Does anyone
> > > know?  I guess we could always disassemble the bytecode.
> > > --
> > >
> > > Daniel Rall <dl...@collab.net>
> > >
> > > ---------------------------------------------------------------------
> > > To unsubscribe, e-mail: turbine-dev-unsubscribe@jakarta.apache.org
> > > For additional commands, e-mail: turbine-dev-help@jakarta.apache.org
> >
> > ---------------------------------------------------------------------
> > To unsubscribe, e-mail: turbine-dev-unsubscribe@jakarta.apache.org
> > For additional commands, e-mail: turbine-dev-help@jakarta.apache.org
> >
> 
> ---------------------------------------------------------------------
> To unsubscribe, e-mail: turbine-dev-unsubscribe@jakarta.apache.org
> For additional commands, e-mail: turbine-dev-help@jakarta.apache.org

---------------------------------------------------------------------
To unsubscribe, e-mail: turbine-dev-unsubscribe@jakarta.apache.org
For additional commands, e-mail: turbine-dev-help@jakarta.apache.org


RE: pool service and recyclable

Posted by Ilkka Priha <ex...@nokia.com>.
I made a small test calling an object implementing a specific interface both
with instanceof test and without and the same for an object NOT implementing
the interface (see below).

The result was that the instanceof test didn't have any affect to the
execution time for the object that did implement the interface. Both loops
took 30 msecs.

For the object that didn't implement the interface, the instanceof checked
loop took 210 msecs, but the try-catch loop 13069 msecs. So I recommend
calling instanceof whenever needed, the overhead is minimal compared to many
other operations.

The pool service uses reflection only for the first instance with a specific
constructor. Then it keeps the corresponding recycle method in its internal
cache and calls it directly instead of reflection. So I don't see any need
for the new interface.

-- Ilkka

[mailto:ext-ilkka.priha@nokia.com]

    Object test = new Test();
    Object test2 = new Test2();

    long now = System.currentTimeMillis();
    for (int i = 0; i < 1000000; i++)
    {
        if (test instanceof Callable)
          ((Callable) test).invoke();
    }
    System.out.println(System.currentTimeMillis() - now);

    now = System.currentTimeMillis();
    for (int i = 0; i < 1000000; i++)
    {
        try { ((Callable) test).invoke(); }
        catch (Exception x) { }
    }
    System.out.println(System.currentTimeMillis() - now);

    now = System.currentTimeMillis();
    for (int i = 0; i < 1000000; i++)
    {
        if (test2 instanceof Callable)
          ((Callable) test2).invoke();
    }
    System.out.println(System.currentTimeMillis() - now);

    now = System.currentTimeMillis();
    for (int i = 0; i < 1000000; i++)
    {
        try { ((Callable) test2).invoke(); }
        catch (Exception x) { }
    }
    System.out.println(System.currentTimeMillis() - now);

> -----Original Message-----
> From: jmcnally [mailto:jmcnally]On Behalf Of John McNally
> Sent: Tuesday, March 13, 2001 04:24
> To: turbine-dev@jakarta.apache.org
> Subject: Re: pool service and recyclable
>
>
> I read somewhere that it is faster to just attempt a cast inside a try
> block than to call instanceof.  That is the reason I wrote this so that
> the instanceof is only called for the first object that is put into a
> pool and the result is stored as a boolean attribute of the pool.  I
> believe something similar could be done for Recyclable objects, but I
> was trying to make my patch minimally disruptive.
>
> John McNally
>
> Daniel Rall wrote:
> >
> > John McNally <jm...@collab.net> writes:
> >
> > > Is there any objection to the addition of the following that
> can allow the
> > > pooling of objects which can be recycled without reflection?
> >
> > Looks okay to me.  Anything to remove reflection.  Does instanceof use
> > reflection, or does it just use getClass() internally?  Does anyone
> > know?  I guess we could always disassemble the bytecode.
> > --
> >
> > Daniel Rall <dl...@collab.net>
> >
> > ---------------------------------------------------------------------
> > To unsubscribe, e-mail: turbine-dev-unsubscribe@jakarta.apache.org
> > For additional commands, e-mail: turbine-dev-help@jakarta.apache.org
>
> ---------------------------------------------------------------------
> To unsubscribe, e-mail: turbine-dev-unsubscribe@jakarta.apache.org
> For additional commands, e-mail: turbine-dev-help@jakarta.apache.org
>


---------------------------------------------------------------------
To unsubscribe, e-mail: turbine-dev-unsubscribe@jakarta.apache.org
For additional commands, e-mail: turbine-dev-help@jakarta.apache.org


Re: pool service and recyclable

Posted by John McNally <jm...@collab.net>.
I read somewhere that it is faster to just attempt a cast inside a try
block than to call instanceof.  That is the reason I wrote this so that
the instanceof is only called for the first object that is put into a
pool and the result is stored as a boolean attribute of the pool.  I
believe something similar could be done for Recyclable objects, but I
was trying to make my patch minimally disruptive.

John McNally

Daniel Rall wrote:
> 
> John McNally <jm...@collab.net> writes:
> 
> > Is there any objection to the addition of the following that can allow the
> > pooling of objects which can be recycled without reflection?
> 
> Looks okay to me.  Anything to remove reflection.  Does instanceof use
> reflection, or does it just use getClass() internally?  Does anyone
> know?  I guess we could always disassemble the bytecode.
> --
> 
> Daniel Rall <dl...@collab.net>
> 
> ---------------------------------------------------------------------
> To unsubscribe, e-mail: turbine-dev-unsubscribe@jakarta.apache.org
> For additional commands, e-mail: turbine-dev-help@jakarta.apache.org

---------------------------------------------------------------------
To unsubscribe, e-mail: turbine-dev-unsubscribe@jakarta.apache.org
For additional commands, e-mail: turbine-dev-help@jakarta.apache.org


Re: pool service and recyclable

Posted by Daniel Rall <dl...@collab.net>.
John McNally <jm...@collab.net> writes:

> Is there any objection to the addition of the following that can allow the
> pooling of objects which can be recycled without reflection?

Looks okay to me.  Anything to remove reflection.  Does instanceof use
reflection, or does it just use getClass() internally?  Does anyone
know?  I guess we could always disassemble the bytecode.
-- 

Daniel Rall <dl...@collab.net>

---------------------------------------------------------------------
To unsubscribe, e-mail: turbine-dev-unsubscribe@jakarta.apache.org
For additional commands, e-mail: turbine-dev-help@jakarta.apache.org