Welcome, Guest. Please login or register.
Did you miss your activation email?
July 31, 2010, 11:40:17 am
advanced search




Pages: [1] 2
  Print  
Author Topic: Pooling for Transient Objects in Maths Classes  (Read 4052 times)
ianp
Jr. Member
**
Offline Offline

Posts: 60


View Profile
« on: January 09, 2009, 03:38:36 pm »

Here's the commit message (if nobody objects):

* Added object pooling for quaternions and arrays and started to update the
  maths classes to use pooled objects for temporary calculations.

I'd like to propose that I am going to mark as deprecated those methods which only exist to allow the caller to pass in 'working objects' such as #multLocal(TransformMatrix,Vector3f) in TransformMatrix. If people agree on this I'll mark them as deprecated and then remove them in, let's say, 2-3 months time.

If everybody is OK with this then I'll go through the rest of the maths classes and do the same.

One thing to note: I've created an ObjectPool class in com.jme.util, there are a couple of reasons for this:

  • it seems wrong to have com.jme classes depending upon com.jmex classes; and
  • the existing object pooling mechanism uses synchronized, which will be problematic with many threads.

also, r.e. synchronized vs. thread local, I think that it would be useful to be able to use the same classes on the client and the server (for multi-player games) and the server environment is probably going to be heavily multi-threaded, so the TL based approach is a huge win there (it should be faster on a modern multi-core CPU based client as well).

The patch is available at http://ianp.org/2009/01/object-pool-patch.txt.gz

Logged
ianp
Jr. Member
**
Offline Offline

Posts: 60


View Profile
« Reply #1 on: January 09, 2009, 03:39:11 pm »

I almost forgot: happy new year!  grin
Logged
hevee
Project Advocate
Sr. Member
*
Offline Offline

Posts: 945


View Profile
« Reply #2 on: January 09, 2009, 04:40:11 pm »

What are the gains? Can you elaborate?
Also your character encoding for the patch is somewhat messed up, jME's encoding is (unfortunately) Windows-1252, but at some point in generating your patch something appears to have misinterpreted the source code as UTF-8.
Logged
Momoko_Fan
Developer
Hero Member
*
Online Online

Posts: 2601



View Profile
« Reply #3 on: January 09, 2009, 06:58:51 pm »

I like the direction of this. Reduces garbage and increases speed as thread locals are supposedly very fast.
I suggest that you take a more centralized approach however, Perhaps all temporary variables should be grouped in one thread local? E.g ObjectPool.get().tempVec, ObjectPool.get().floatArray16, etc. Since each thread has it's own temp var set, there's no need to manage who has access to what.
Using lists to manage all of this, it might actually be slower as lists create garbage as well.. It's much better to take a light-weight approach on this I think.
Logged
nymon
Project Advocate
Hero Member
*
Offline Offline

Posts: 1255



View Profile
« Reply #4 on: January 09, 2009, 08:24:07 pm »

I like the idea. To make sure I understand, this would alleviate the use of temp objects repeatedly defined in individual classes?
Logged

Scene Monitor might help!
basixs
Hero Member
*****
Offline Offline

Posts: 1603


ßâšï¤š


View Profile
« Reply #5 on: January 09, 2009, 08:55:01 pm »

I am rather concerned about the performance loss in a couple of methods actually...

Code:
     public void lookAt(Vector3f direction, Vector3f up ) {
-        tmpZaxis.set( direction ).normalizeLocal();
-        tmpXaxis.set( up ).crossLocal( direction ).normalizeLocal();
-        tmpYaxis.set( direction ).crossLocal( tmpXaxis ).normalizeLocal();
-        fromAxes( tmpXaxis, tmpYaxis, tmpZaxis );
+        Vector3f x = Vector3f.POOL.get();
+        Vector3f y = Vector3f.POOL.get();
+        Vector3f z = Vector3f.POOL.get();
+        z.set(direction).normalizeLocal();
+        x.set(up).crossLocal(direction).normalizeLocal();
+        y.set(direction).crossLocal(x).normalizeLocal();
+        fromAxes(x, y, z);
+        Vector3f.POOL.recycle(x);
+        Vector3f.POOL.recycle(y);
+        Vector3f.POOL.recycle(z);
     }
This method alone has 3 list lookups, and 3 'returns to the pool'; where before it used 3 global temp variables w/ no overhead to access at all.  This method is used ALOT throughout the jME system and could create a noticeable performance drop (IMO)...

I think in some cases using your pool is very appropriate, however in others global variables might be the way to go...
Logged

How would you feel about a world with no pain?  Would it be any better? ... and would you still appreciate a summers day?
renanse
Champion
Hero Member
*
Offline Offline

Posts: 5457



View Profile WWW
« Reply #6 on: January 09, 2009, 09:17:29 pm »

If I can still offer my two cents here... Part of the rewrite for Ardor3D was to get rid of static variables such as the mentioned helper variables.  The reason was multithreaded access and the same static variable being easily munged by two competing threads.  So if you think you might want MT access, you may have to make some choices about performance (usually a small hit) vs. function.
Logged

---
next gen Ardor3d has reached 0.6!
basixs
Hero Member
*****
Offline Offline

Posts: 1603


ßâšï¤š


View Profile
« Reply #7 on: January 09, 2009, 09:21:37 pm »

Ah, thanx Renanse that does change my opinion a little bit smiley
Logged

How would you feel about a world with no pain?  Would it be any better? ... and would you still appreciate a summers day?
Momoko_Fan
Developer
Hero Member
*
Online Online

Posts: 2601



View Profile
« Reply #8 on: January 09, 2009, 09:53:21 pm »

Quote
If I can still offer my two cents here... Part of the rewrite for Ardor3D was to get rid of static variables such as the mentioned helper variables.  The reason was multithreaded access and the same static variable being easily munged by two competing threads.  So if you think you might want MT access, you may have to make some choices about performance (usually a small hit) vs. function.
Yes, using static variables the way they are now would cause threading issues. That's why it is preferable to call certain non-GL methods in the GL thread. However the performance hit is not necessary, with the use of thread locals, each thread has it's own private temp variables which means you receive both improved memory usage, performance, and thread safety.
Logged
renanse
Champion
Hero Member
*
Offline Offline

Posts: 5457



View Profile WWW
« Reply #9 on: January 09, 2009, 10:34:38 pm »

Well, maybe.  As long as you don't end up chaining together two methods that make use of the same thread local temp variable.  That was always an interesting issue...  which temp variable is already being used?  Is it tempB that's currently open?  etc. etc.
Logged

---
next gen Ardor3d has reached 0.6!
ianp
Jr. Member
**
Offline Offline

Posts: 60


View Profile
« Reply #10 on: January 10, 2009, 06:10:53 am »

@Momonko_Fan: agreed that having a single thread local would be less overhead then 1 per class, I'll post an updated patch over the weekend.

@nymon: yes, that's right. Although my main concern is not really to improve performance as much as it is to reduce the number of GC pauses. IMHO it's worth sacrificing ~1FPS or so if by doing so it's possible to reduce the number of GC pauses. If the performance actually improves then that's sweet as well smiley

I'll put together some performance tests to try to measure the impact of this change and post the results.
Logged
ianp
Jr. Member
**
Offline Offline

Posts: 60


View Profile
« Reply #11 on: January 10, 2009, 06:13:32 am »

@hevee: oops! I'll make sure the encoding gets set to CP-1252 before it hits the repository.

Hmmm, as I'm using a Mac it seems like I'll have to use ISO-8859-1, as I understand it this is pretty compatible with CP-1252 so I hope there won't be any issues.
« Last Edit: January 10, 2009, 07:06:29 am by ianp » Logged
ianp
Jr. Member
**
Offline Offline

Posts: 60


View Profile
« Reply #12 on: January 10, 2009, 06:42:59 am »

Using lists to manage all of this, it might actually be slower as lists create garbage as well. It's much better to take a light-weight approach on this I think.

I don't think that the lists will be a problem really, if you look at the ObjectPool class it has a (user configurable via a system property) limit on the number of pooled instances that will be held, this is low by default ( 8 ), I've also edited the patch to set the initial size of the list to this value, so that should ensure that it never needs to grow and reallocate storage space.


Logged
vear
Full Member
***
Offline Offline

Posts: 257


View Profile
« Reply #13 on: January 10, 2009, 10:56:52 am »

Just to add my opinion on object pools.

You should avoid having "Vector3f.POOL.recycle(x)". Serving objects from a pool is ok, but when you have to manage the deletion too, it gets unmanageable. I suggest to have a single "Vector3f.POOL.clear()" which just resets the pool to serve the first object again. The point is: its not the memory you want preserve by reusing objects, you just want to avoid new object creation.

http://code.google.com/p/vlengine/source/browse/trunk/vle_cleanup/src/com/vlengine/bounding/ReuseManager.java

You can reset the pool each frame. So the program does not lose too much time micro-managing the pool, but wipes all object at once.
Logged
ianp
Jr. Member
**
Offline Offline

Posts: 60


View Profile
« Reply #14 on: January 11, 2009, 01:42:29 pm »

@vear: doesn't that make it difficult if multiple methods want to grab objects from the pool? having a single clear method would mean that you'd need to manually keep track of which methods are on the stack and when you need to clear the pool. Being able to return individual objects actually seems like it would be easier.

I think that for most temporary objects they're acquired and recycled in the same method, so it's fairly easy to manage (as long as the methods don't get too big, but that's a code smell anyway).

I'll have a look at the VL Engine code though.
Logged
Tags:
Pages: [1] 2
  Print  
 
Jump to: