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 <gkim...@gmail.com> 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 explicit linkage > while(true) { > lnr.mark(1000); > line = lnr.readLine(); > if (line.startsWith("obj")) { > tok = new > StringTokenizer(line); > // ignore "obj" > tok.nextToken(); > > bone.partLinks.add(tok.nextToken()); > > anim.explicitPartLinkage = true; > } > else { > // Reset to previous > line number > lnr.reset(); > break; > } > } > > // Add bone to animation > if (boneNum == 0) { > anim.rootBone = bone; > } > else { > // Add this bone to its > parent's list of children > > bone.parent.children.add(bone); > } > anim.allBones.add(bone); > > boneNum++; > } > else if (line.startsWith("action")) { > // Action define > StringTokenizer tok = new > StringTokenizer(line); > KdfAction action = new KdfAction(); > > // ignore "action" > tok.nextToken(); > > // Set name > action.actionName = tok.nextToken(); > > // ignore "numframes" text > tok.nextToken(); > > // Get number of frames > action.numberOfFrames = > Integer.parseInt(tok.nextToken()); > > // Get all bone actions > while(true) { > //Mark the current line > lnr.mark(1000); > line = lnr.readLine(); > if (line == null) { > break; > } > if (!line.startsWith("bone")) > { > // Go back to the > previous line so the for() loop we're in > doesn't skip one > lnr.reset(); > break; > } > > KdfBoneAction bact = new > KdfBoneAction(); > > tok = new > StringTokenizer(line); > // ignore "bone" > tok.nextToken(); > > // Figure out the bone this > using > String boneName = > tok.nextToken(); > for (int i = 0; i < > anim.allBones.size(); i++) { > if > (anim.allBones.get(i).boneName.equalsIgnoreCase(boneName)) { > bact.bone = > anim.allBones.get(i); > break; > } > } > > // Get [numberOfFrames] locs > for (int i = 0; i < > action.numberOfFrames; i++) { > line = lnr.readLine(); > > bact.locs.add(parseLocLine(line)); > } > > // Get [numberOfFrames] rots > for (int i = 0; i < > action.numberOfFrames; i++) { > line = lnr.readLine(); > > bact.rots.add(parseRotLine(line)); > } > > // Add the BoneAction to the > action > action.boneActions.add(bact); > } > > // Add the action to the animation > anim.actions.add(action); > } > } > } > > } catch (Exception e) { > System.err.println("Error parsing file:"); > System.err.println(lnr.getLineNumber()+" : "+line); > } > > return anim; > } > > private static float[] parseLocLine(String line) { > float[] retFloat = new float[3]; > StringTokenizer tok = new StringTokenizer(line); > > // Ignore "loc" > tok.nextToken(); > // x > tok.nextToken(); > retFloat[0] = Float.parseFloat(tok.nextToken()); > // y > tok.nextToken(); > retFloat[1] = Float.parseFloat(tok.nextToken()); > // z > tok.nextToken(); > retFloat[2] = Float.parseFloat(tok.nextToken()); > > return retFloat; > } > > 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==== --~--~---------~--~----~------------~-------~--~----~ 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 -~----------~----~----~----~------~----~------~--~---