[android-beginners] Re: Poor performance on my file loader (code optimization help!)

2009-09-21 Thread fadden

On Sep 20, 11:28 am, Glen Kimsey  wrote:
> The loading process on a sample (1000+ line) file is abysmally slow
> (more than 4 minutes). [...]
>
> Some possible causes for the slowness:
> - Extensive use of parseFloat()
> - Creating new StringTokenizer for every line
> - Inefficiencies in for() loops (not caching as necessary?)
> - Repeated use of the acos() and sqrt() functions

Re-use objects when possible to avoid allocation and construction
overhead.  For a parser using regular expressions, you avoid the cost
of recompiling the RE.  acos() and sqrt() are not especially fast; sqrt
() in particular, since the G1 lacks floating-point hardware.

You can get some sense for where the time is going with the method
tracing facility:

  http://developer.android.com/guide/developing/tools/traceview.html

> [...]  I could even do something as drastic as
> performing this load in a separate app (before distribution) and
> somehow exporting the resulting object (KdfAnimation) that could more
> easily be picked back up (this would work in C, but I'm doubtful Java
> would allow such low-level memory copying).

Java does provide a serialization mechanism, but it's not widely
loved. :-)

--~--~-~--~~~---~--~~
You received this message because you are subscribed to the Google
Groups "Android Beginners" group.
To post to this group, send email to android-beginners@googlegroups.com
To unsubscribe from this group, send email to
android-beginners-unsubscr...@googlegroups.com
For more options, visit this group at
http://groups.google.com/group/android-beginners?hl=en
-~--~~~~--~~--~--~---



[android-beginners] Re: Poor performance on my file loader (code optimization help!)

2009-09-22 Thread a1



On 20 Wrz, 20:28, Glen Kimsey  wrote:
> Hello!
> I'm fairly new to both Android and Java (pretty experienced in C/C++),
> and (stupidly, perhaps) took on a big project.  In it, I need to load
> information about 3D models and their respective animations from a
> text file (proprietary file format based on PSK/PSA).



>
>         private static float[] parseRotLine(String line) {
>                 float[] retFloat = new float[4];
>                 StringTokenizer tok = new StringTokenizer(line);
>
>                 // Ignore "rot"
>                 tok.nextToken();
>                 // theta
>                 tok.nextToken();
>                 retFloat[0] = wToTheta(Float.parseFloat(tok.nextToken()));
>                 // x
>                 tok.nextToken();
>                 retFloat[1] = Float.parseFloat(tok.nextToken());
>                 // y
>                 tok.nextToken();
>                 retFloat[2] = Float.parseFloat(tok.nextToken());
>                 // z
>                 tok.nextToken();
>                 retFloat[3] = Float.parseFloat(tok.nextToken());
>
>                 // Need to scale this vector to make glRotate happy
>                 retFloat = scaleAxisAngleVector(retFloat);
>
>                 return retFloat;
>         }
>
>         private static float wToTheta(float w) {
>                 // w = cos(theta/2)
>                 float theta = (float)Math.acos((double)w) * 2;
>                 // convert theta to degrees
>                 theta = 180 * theta / (float)Math.PI;
>                 // The above calculation only gave us a value from 0 to 180 
> because
> of arccosine
>                 // TODO: Determine if this is a problem.  Note that w can be
> negative, and this implies 180 degrees
>                 if (w < 0) {
>                         theta += 180;
>                 }
>                 return theta;
>         }
>
>         private static float[] scaleAxisAngleVector(float[] unscaled) {
>                 float[] scaled = new float[4];
>                 // scale = sqrt(x^2 + y^2 + z^2);
>                 float scale = (float)Math.sqrt(unscaled[1] * unscaled[1] + 
> unscaled
> [2] * unscaled[2] + unscaled[3] * unscaled[3]);
>
>                 if (scale != 0) {
>                         scaled[0] = unscaled[0];
>                         scaled[1] = unscaled[1] / scale;
>                         scaled[2] = unscaled[2] / scale;
>                         scaled[3] = unscaled[3] / scale;
>                 }
>                 else
>                 {
>                         // Scale can be 0, which means we're not rotating
>                         // but dividing by zero is bad, and glRotate still
>                         // needs a normalized vector.
>                         scaled[0] = 0;
>                         scaled[1] = 1;
>                         scaled[2] = 0;
>                         scaled[3] = 0;
>                 }
>                 return scaled;
>         }}
>
> End of Loader Code

Ugh, why oh why are you transforming quaterninions to axis/angle
representation? Quaternion interpolation is easier, and gives better
result (you will also save a lot of time on calculations).

About performance, if it's possible (eg. you are not downloading the
scene files from network or smth), write a small utility that will
convert text file to binary representation offline, and then read the
binary files on android. Also try to minimize number of allocation
during file loading.

--
Bart 'arcone1' janusz

--~--~-~--~~~---~--~~
You received this message because you are subscribed to the Google
Groups "Android Beginners" group.
To post to this group, send email to android-beginners@googlegroups.com
To unsubscribe from this group, send email to
android-beginners-unsubscr...@googlegroups.com
For more options, visit this group at
http://groups.google.com/group/android-beginners?hl=en
-~--~~~~--~~--~--~---



[android-beginners] Re: Poor performance on my file loader (code optimization help!)

2009-09-23 Thread Glen Kimsey

Thanks for the reply.  I think your suggestion of going binary is one
of the better ones I had considered.  Especially because I can avoid
the parseFloat() calls altogether using this method.

As for the quaternion vs axis/angle, I had thought I HAD to translate
them originally (I found out later with more research that I just had
to use the more complicated matrix math rather than simple glrotate
and gltranslate calls if I didn't).  I don't suppose you could direct
me to a tutorial or good description that will help a 3D rendering
newbie like me use the quaternions?  If it really is better/faster, I
want to go that route rather than finding out later I should have.

I'm still looking for any additional suggestions on what particular
parts of the code might be killing my load times, although I'm sure
switching to binary and not using acos and sqrt will help quite a bit.

Thanks,
Glen

On Sep 22, 5:03 am, a1  wrote:
> On 20 Wrz, 20:28, Glen Kimsey  wrote:
>
> > Hello!
> > I'm fairly new to both Android and Java (pretty experienced in C/C++),
> > and (stupidly, perhaps) took on a big project.  In it, I need to load
> > information about 3D models and their respective animations from a
> > text file (proprietary file format based on PSK/PSA).
>
> 
>
>
>
>
>
> >         private static float[] parseRotLine(String line) {
> >                 float[] retFloat = new float[4];
> >                 StringTokenizer tok = new StringTokenizer(line);
>
> >                 // Ignore "rot"
> >                 tok.nextToken();
> >                 // theta
> >                 tok.nextToken();
> >                 retFloat[0] = wToTheta(Float.parseFloat(tok.nextToken()));
> >                 // x
> >                 tok.nextToken();
> >                 retFloat[1] = Float.parseFloat(tok.nextToken());
> >                 // y
> >                 tok.nextToken();
> >                 retFloat[2] = Float.parseFloat(tok.nextToken());
> >                 // z
> >                 tok.nextToken();
> >                 retFloat[3] = Float.parseFloat(tok.nextToken());
>
> >                 // Need to scale this vector to make glRotate happy
> >                 retFloat = scaleAxisAngleVector(retFloat);
>
> >                 return retFloat;
> >         }
>
> >         private static float wToTheta(float w) {
> >                 // w = cos(theta/2)
> >                 float theta = (float)Math.acos((double)w) * 2;
> >                 // convert theta to degrees
> >                 theta = 180 * theta / (float)Math.PI;
> >                 // The above calculation only gave us a value from 0 to 180 
> > because
> > of arccosine
> >                 // TODO: Determine if this is a problem.  Note that w can be
> > negative, and this implies 180 degrees
> >                 if (w < 0) {
> >                         theta += 180;
> >                 }
> >                 return theta;
> >         }
>
> >         private static float[] scaleAxisAngleVector(float[] unscaled) {
> >                 float[] scaled = new float[4];
> >                 // scale = sqrt(x^2 + y^2 + z^2);
> >                 float scale = (float)Math.sqrt(unscaled[1] * unscaled[1] + 
> > unscaled
> > [2] * unscaled[2] + unscaled[3] * unscaled[3]);
>
> >                 if (scale != 0) {
> >                         scaled[0] = unscaled[0];
> >                         scaled[1] = unscaled[1] / scale;
> >                         scaled[2] = unscaled[2] / scale;
> >                         scaled[3] = unscaled[3] / scale;
> >                 }
> >                 else
> >                 {
> >                         // Scale can be 0, which means we're not rotating
> >                         // but dividing by zero is bad, and glRotate still
> >                         // needs a normalized vector.
> >                         scaled[0] = 0;
> >                         scaled[1] = 1;
> >                         scaled[2] = 0;
> >                         scaled[3] = 0;
> >                 }
> >                 return scaled;
> >         }}
>
> > End of Loader Code
>
> Ugh, why oh why are you transforming quaterninions to axis/angle
> representation? Quaternion interpolation is easier, and gives better
> result (you will also save a lot of time on calculations).
>
> About performance, if it's possible (eg. you are not downloading the
> scene files from network or smth), write a small utility that will
> convert text file to binary representation offline, and then read the
> binary files on android. Also try to minimize number of allocation
> during file loading.
>
> --
> Bart 'arcone1' janusz
--~--~-~--~~~---~--~~
You received this message because you are subscribed to the Google
Groups "Android Beginners" group.
To post to this group, send email to android-beginners@googlegroups.com
To unsubscribe from this group, send email to
android-beginners-unsubscr...@googlegroups.com
For more options, visit this group at
http://groups.google.com/gr

[android-beginners] Re: Poor performance on my file loader (code optimization help!)

2009-09-23 Thread Glen Kimsey

Fadden,

Sorry, I missed your reply when I responded to Bart!

I tried to find significant ways that I could avoid allocation, but
the StringTokenizer is the main thing that I'm calling 'new' on and I
didn't see any way to avoid doing that for every line.  Your
suggestion of using regexs for a parser kind of threw me off, because
I didn't even see that as a possibility.  I'll have to look into that
and see what you mean.  I also didn't know the G1 didn't have floating-
point hardware.  Will this likely be the case for other android phones
in the near future?  This information combined with Bart's suggestion
to stick with quaternions means I'll very likely be removing those
calls to acos and sqrt entirely.

Also, thanks for the links.  Your reply was extremely helpful.

Thanks!
Glen

On Sep 21, 7:22 pm, fadden  wrote:
> On Sep 20, 11:28 am, Glen Kimsey  wrote:
>
> > The loading process on a sample (1000+ line) file is abysmally slow
> > (more than 4 minutes). [...]
>
> > Some possible causes for the slowness:
> > - Extensive use of parseFloat()
> > - Creating new StringTokenizer for every line
> > - Inefficiencies in for() loops (not caching as necessary?)
> > - Repeated use of the acos() and sqrt() functions
>
> Re-use objects when possible to avoid allocation and construction
> overhead.  For a parser using regular expressions, you avoid the cost
> of recompiling the RE.  acos() and sqrt() are not especially fast; sqrt
> () in particular, since the G1 lacks floating-point hardware.
>
> You can get some sense for where the time is going with the method
> tracing facility:
>
>  http://developer.android.com/guide/developing/tools/traceview.html
>
> > [...]  I could even do something as drastic as
> > performing this load in a separate app (before distribution) and
> > somehow exporting the resulting object (KdfAnimation) that could more
> > easily be picked back up (this would work in C, but I'm doubtful Java
> > would allow such low-level memory copying).
>
> Java does provide a serialization mechanism, but it's not widely
> loved. :-)
--~--~-~--~~~---~--~~
You received this message because you are subscribed to the Google
Groups "Android Beginners" group.
To post to this group, send email to android-beginners@googlegroups.com
To unsubscribe from this group, send email to
android-beginners-unsubscr...@googlegroups.com
For more options, visit this group at
http://groups.google.com/group/android-beginners?hl=en
-~--~~~~--~~--~--~---



[android-beginners] Re: Poor performance on my file loader (code optimization help!)

2009-09-23 Thread fadden

On Sep 23, 8:49 am, Glen Kimsey  wrote:
> I tried to find significant ways that I could avoid allocation, but
> the StringTokenizer is the main thing that I'm calling 'new' on and I
> didn't see any way to avoid doing that for every line.  Your
> suggestion of using regexs for a parser kind of threw me off, because
> I didn't even see that as a possibility.  I'll have to look into that
> and see what you mean.

>From the JavaDoc for StringTokenizer:

"StringTokenizer is a legacy class that is retained for compatibility
reasons although its use is discouraged in new code. It is recommended
that anyone seeking this functionality use the split method of String
or the java.util.regex package instead."

> I also didn't know the G1 didn't have floating-
> point hardware.  Will this likely be the case for other android phones
> in the near future?  This information combined with Bart's suggestion
> to stick with quaternions means I'll very likely be removing those
> calls to acos and sqrt entirely.

It also lacks an integer divide instruction, so go easy on divisions
and modulus. :-)

If you do a google search for "ODROID" you can see an example of a
device with hardware FP.

--~--~-~--~~~---~--~~
You received this message because you are subscribed to the Google
Groups "Android Beginners" group.
To post to this group, send email to android-beginners@googlegroups.com
To unsubscribe from this group, send email to
android-beginners-unsubscr...@googlegroups.com
For more options, visit this group at
http://groups.google.com/group/android-beginners?hl=en
-~--~~~~--~~--~--~---



[android-beginners] Re: Poor performance on my file loader (code optimization help!)

2009-09-23 Thread a1

Hi,

> As for the quaternion vs axis/angle, I had thought I HAD to translate
> them originally (I found out later with more research that I just had
> to use the more complicated matrix math rather than simple glrotate
> and gltranslate calls if I didn't).  I don't suppose you could direct
> me to a tutorial or good description that will help a 3D rendering
> newbie like me use the quaternions?  If it really is better/faster, I
> want to go that route rather than finding out later I should have.

Quaternions aren't faster (well ok nlerp can be) but they are better
at least for interpolation, sice you are clearly reading keyframing
data, thus I assumed that you will interpolate it sooner or later
therefore transforming them to axis/angle looks a bit redundant (since
usually rotation is interpolated with cubic quaternion interpolation
aka. squad).

If yor some basic info about quaternions you can check this old (very)
flipcode FAQ:
http://www.flipcode.com/documents/matrfaq.html (this is really basic
so may be a bit too basic :))

After bit searching I also found this:
www.itu.dk/people/erikdam/DOWNLOAD/98-5.pdf looks ok to me

And of course if you have Foley, van Dam "CG: Principles And Practice"
book. (It may be a bit outdated nowadays but still it's a CG bible)

--
Bart 'arcone1' Janusz
--~--~-~--~~~---~--~~
You received this message because you are subscribed to the Google
Groups "Android Beginners" group.
To post to this group, send email to android-beginners@googlegroups.com
To unsubscribe from this group, send email to
android-beginners-unsubscr...@googlegroups.com
For more options, visit this group at
http://groups.google.com/group/android-beginners?hl=en
-~--~~~~--~~--~--~---



[android-beginners] Re: Poor performance on my file loader (code optimization help!)

2009-09-24 Thread Kaj Bjurman
Is there a reason to why you use a LineNumberReader? I would instead
use a BufferedReader, that will probably improve your performance.

I don't know anything about the dataformat in the file, but there
probably is a much faster way to parse it than using all those
StringTokenizers (or regexp even if that might be faster). I would
also try to parse the file without mark and reset.





On 20 Sep, 20:28, Glen Kimsey  wrote:
> Hello!
> I'm fairly new to both Android and Java (pretty experienced in C/C++),
> and (stupidly, perhaps) took on a big project.  In it, I need to load
> information about 3D models and their respective animations from a
> text file (proprietary file format based on PSK/PSA).
>
> The loading process on a sample (1000+ line) file is abysmally slow
> (more than 4 minutes).  The good news is that there are lots and lots
> of ways I can improve it.  What I'm hoping to find out here is if
> there's anything in *particular* in my code that is very inefficient
> that I can change.  Don't worry about offending me, I know this is
> amateur code here.
>
> Some possible causes for the slowness:
> - Extensive use of parseFloat()
> - Creating new StringTokenizer for every line
> - Inefficiencies in for() loops (not caching as necessary?)
> - Repeated use of the acos() and sqrt() functions
>
> I'd like to find out from you gentlemen (ladies) what you think is the
> major thing eating up my time here.  If there's some tool I can use to
> find out what lines of code are taking up the most time that'd be
> ideal.  I'm open to any possible solutions.  The file format can
> change (and probably will).  I could even do something as drastic as
> performing this load in a separate app (before distribution) and
> somehow exporting the resulting object (KdfAnimation) that could more
> easily be picked back up (this would work in C, but I'm doubtful Java
> would allow such low-level memory copying).
>
> One final note is that the "action" loading section of this code
> occupies about 3/4 of the files being loaded (so this section may be
> more important to optimize).
>
> Loader Code
> public class KdfLoader {
>
>         public static KdfAnimation load(String file) throws IOException {
>                 KdfAnimation anim = new KdfAnimation();
>
>                 FileInputStream fis = new FileInputStream(file);
>                 String line = "[start]";
>                 LineNumberReader lnr = new LineNumberReader(new 
> InputStreamReader
> (fis));
>
>                 int boneNum = 0;
>
>                 try {
>
>                 for (line = lnr.readLine(); line != null; line = 
> lnr.readLine()) {
>                         if (line.length() > 0) {
>                                 if (line.startsWith("numbones")) {
>                                         // Ignore it for now
>                                 }
>                                 else if (line.startsWith("bone")) {
>                                         // Bone define
>                                         StringTokenizer tok = new 
> StringTokenizer(line);
>                                         KdfBone bone = new KdfBone();
>
>                                         // Toss out "bone"
>                                         tok.nextToken();
>
>                                         // Set name
>                                         bone.boneName = tok.nextToken();
>
>                                         if (boneNum == 0) {
>                                                 // Root bone.  Ignore 
> children and parent id in file
>                                                 bone.parentId = 0;
>                                                 bone.parent = null;
>                                                 // ignore "numchildren x"
>                                                 // ignore "parentid x"
>                                         }
>                                         else
>                                         {
>                                                 // ignore "numchildren x"
>                                                 tok.nextToken();
>                                                 tok.nextToken();
>                                                 // ignore "parentid" text
>                                                 tok.nextToken();
>                                                 bone.parentId = 
> Integer.parseInt(tok.nextToken());
>                                                 bone.parent = 
> anim.allBones.get(bone.parentId);
>                                         }
>                                         // get loc and rot
>                                         line = lnr.readLine();
>                                         bone.loc = parseLocLine(line);
>                                         line = lnr.readLine();
>                                         bone.rot = parseRotLine(line);
>
>                                         // Handle

[android-beginners] Re: Poor performance on my file loader (code optimization help!)

2009-09-29 Thread Glen Kimsey
Thanks to everyone for the help on this.  As I mentioned, I'm rather
new to Java, so things like StringTokenizer being legacy are news.

Believe it or not the file format uses actual frames instead of
keyframes (hence no timestamp or other indication of time or frames
between each being parsed out), but this is all still up in the air.
Obviously it's a very amateur way to do it right now.  I'll probably
shift back to quaternions and worry about interpolating later (it
might be a application size vs. performance vs. memory usage thing in
the end.  I'm not sure).  Thanks for the links.

The LineNumberReader was actually hijacked from some open source code
intended for a very similar purpose.  I didn't know what to use for
this scenario and so finding someone else using LNR meant I jumped on
it as the "ideal" solution.  Safe to say I'll be trying R.E.s and/or
buffered reader soon enough.  Are mark and reset really that taxing?
More so than basically buffering the several lines that might need to
be re-parsed?

Thanks again.  Very helpful.
Glen

On Sep 24, 10:14 am, Kaj Bjurman  wrote:
> Is there a reason to why you use a LineNumberReader? I would instead
> use a BufferedReader, that will probably improve your performance.
>
> I don't know anything about the dataformat in the file, but there
> probably is a much faster way to parse it than using all those
> StringTokenizers (or regexp even if that might be faster). I would
> also try to parse the file without mark and reset.
>
> On 20 Sep, 20:28, Glen Kimsey  wrote:
>
> > Hello!
> > I'm fairly new to both Android and Java (pretty experienced in C/C++),
> > and (stupidly, perhaps) took on a big project.  In it, I need to load
> > information about 3D models and their respective animations from a
> > text file (proprietary file format based on PSK/PSA).
>
> > The loading process on a sample (1000+ line) file is abysmally slow
> > (more than 4 minutes).  The good news is that there are lots and lots
> > of ways I can improve it.  What I'm hoping to find out here is if
> > there's anything in *particular* in my code that is very inefficient
> > that I can change.  Don't worry about offending me, I know this is
> > amateur code here.
>
> > Some possible causes for the slowness:
> > - Extensive use of parseFloat()
> > - Creating new StringTokenizer for every line
> > - Inefficiencies in for() loops (not caching as necessary?)
> > - Repeated use of the acos() and sqrt() functions
>
> > I'd like to find out from you gentlemen (ladies) what you think is the
> > major thing eating up my time here.  If there's some tool I can use to
> > find out what lines of code are taking up the most time that'd be
> > ideal.  I'm open to any possible solutions.  The file format can
> > change (and probably will).  I could even do something as drastic as
> > performing this load in a separate app (before distribution) and
> > somehow exporting the resulting object (KdfAnimation) that could more
> > easily be picked back up (this would work in C, but I'm doubtful Java
> > would allow such low-level memory copying).
>
> > One final note is that the "action" loading section of this code
> > occupies about 3/4 of the files being loaded (so this section may be
> > more important to optimize).
>
> > Loader Code
> > public class KdfLoader {
>
> >         public static KdfAnimation load(String file) throws IOException {
> >                 KdfAnimation anim = new KdfAnimation();
>
> >                 FileInputStream fis = new FileInputStream(file);
> >                 String line = "[start]";
> >                 LineNumberReader lnr = new LineNumberReader(new 
> > InputStreamReader
> > (fis));
>
> >                 int boneNum = 0;
>
> >                 try {
>
> >                 for (line = lnr.readLine(); line != null; line = 
> > lnr.readLine()) {
> >                         if (line.length() > 0) {
> >                                 if (line.startsWith("numbones")) {
> >                                         // Ignore it for now
> >                                 }
> >                                 else if (line.startsWith("bone")) {
> >                                         // Bone define
> >                                         StringTokenizer tok = new 
> > StringTokenizer(line);
> >                                         KdfBone bone = new KdfBone();
>
> >                                         // Toss out "bone"
> >                                         tok.nextToken();
>
> >                                         // Set name
> >                                         bone.boneName = tok.nextToken();
>
> >                                         if (boneNum == 0) {
> >                                                 // Root bone.  Ignore 
> > children and parent id in file
> >                                                 bone.parentId = 0;
> >                                                 bone.parent = null;
> >