Optimizing OBJ file (3d model) loading in java - java

Before I begin I apologize for my lack of comments in my code. I am currently making a OBJ file loader (in java.) Although my code works as expected for small files, when files become large (for example I am currently attempting to load a obj file which has 25,958 lines) my entire system crashes. I recently migrated my entire project over from C++ which could load this model quickly. I utilized a profiler alongside a debugger to determine where the entire process crashes my system. I noticed a few things; first, it was hanging at the initiation process; second, my heap was nearly completely used up (I used up about 90% of the heap.)
My code can be found here:
http://pastebin.com/VjN0pzyi
I was curious about methods I could employ to optimize this code.

When you're really low on memory, everything slows down a lot. I guess you should improve you coding skills, things like
startChar = line[i].toCharArray()[k];
probably don't get optimized to
startChar = line[i].charAt(k);
automagically. Maybe interning your strings could save a lot of memory, try String.intern or Guava Interner.
The Hotspot loves short methods, so refactor. The code as it is hard to read and I guess that given its size no optimizations get done at all!

I know this is an old question, but I wanted to throw in my two cents on your performance issues. You're saying that your code not only runs slow, but it takes up 90% of the heap. I think saying 90% is an egregious exaggeration, but this still allows me to point out the biggest flaw with Java game development. Java does not support value types, such as structs. That means that in order to gain speed you're required to avoid OOP, because every time you instance a class for your loader it is allocated onto the heap. You must then invariably wait for GC to kick in to get rid of the clutter and left over instances that your loader created. Now take a language like C# as an example of how to create a real language. C# fully supports structs. You could replace every class of your loader with them. Faces, groups, Vertex, Normal, classes are then treated as value types; they are deleted when the stack unwinds. No garbage is generated, or at least very little if you're required to use a class or two.
In my opinion, don't use Java for game development. I used it for years before discovering C#. Strictly my opinion, here, but Java is a horrible language; I will never use it again.

Related

Can you/How do you save CPU and memory by choosing wisely [closed]

Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 8 years ago.
Improve this question
I understand the JVM optimizes some things for you (not clear on which things yet), but lets say I were to do this:
while(true) {
int var = 0;
}
would doing:
int var;
while(true) {
var = 0;
}
take less space? Since you aren't declaring a new reference every time, you don't have to specify the type every time.
I understand you really would only need to put var outside of while if I wanted to use it outside of that loop (instead of only being able to use it locally like in the first example). Also, what about objects, would it be different that primitive types in that situation? I understand it's a small situation, but build-up of this kind of stuff can cause my application to take a lot of memory/cpu. I'm trying to use the least amount of operations possible, but I don't completely understand whats going on behind the scenes.
If someone could help me out, even maybe link me to somewhere I can learn about saving cpu by decreasing amount of operations, it would be highly appreciated. Please no books (unless they're free! :D), no way of getting one right now /:
Don't. Premature optimization is the root of all evil.
Instead, write your code as it makes most sense conceptually. Write it thoughtfully, yes. But don't think you can be a 'human compiler' and optimize and still write good code.
Once you have written your code (more or less naively, depending on your level of experience) you write performance tests for it. Try to think of different ways in which the code may be used (many times in a row, from front to back or reversed, many concurrent invocations etc) and try to cover these in test cases. Then benchmark your code.
If you find that some test cases are not performing well, investigate why. Measure parts of the test case to see where the time is going. Zoom into the parts where most time is spent.
Mostly, you will find weird loops where, upon reading the code again, you will think 'that was silly to write it that way. Of course this is slow' and easily fix it. In my experience most performance problems can be solved this way and 'hardcore optimization' is hardly ever needed.
In the end you will find that 99* percent of all performance problems can be solved by touching only 1 percent of the code. The other code never comes into play. This is why you should not 'prematurely' optimize. You will be spending valuable time optimizing code that had no performance issues in the first place. And making it less readable in the process.
Numbers made up of course but you know what I mean :)
Hot Licks points out the fact that this isn't much of an answer, so let me expand on this with some good ol' perfomance tips:
Keep an eye out for I/O
Most performance problems are not in pure Java. Instead they are in interfacing with other systems. In particular disk access is notoriously slow. So is the network. So minimize it's use.
Optimize SQL queries
SQL queries will add seconds, even minutes, to your program's execution time if you don't watch out. So think about those very carefully. Again, benchmark them. You can write very optimized Java code, but if it first spends ten seconds waiting for the database to run some monster SQL query than it will never be fast.
Use the right kind of collections
Most performance problems are related to doing things lots of times. Usually when working with big sets of data. Putting your data in a Map instead of in a List can make a huge difference. Also there are specialized collection types for all sorts of performance requirements. Study them and pick wisely.
Don't write code
When performance really matters, squeezing the last 'drops' out of some piece of code becomes a science all in itself. Unless you are writing some very exotic code, chances are great there will be some library or toolkit to solve your kind of problems. It will be used by many in the real world. Tried and tested. Don't try to beat that code. Use it.
We humble Java developers are end-users of code. We take the building blocks that the language and it's ecosystem provides and tie it together to form an application. For the most part, performance problems are caused by us not using the provided tools correctly, or not using any tools at all for that matter. But we really need specifics to be able to discuss those. Benchmarking gives you that specifity. And when the slow code is identified it is usually just a matter of changing a collection from list to map, or sorting it beforehand, or dropping a join from some query etc.
Attempting to optimise code which doesn't need to be optimised increases complexity and decreases readability.
However, there are cases were improving readability also comes with improved performance.
For example,
if a numeric value cannot be null, use a primitive instead of a wrapper. This makes it clearer that the value cannot be null but also uses less memory and reduces pressure on the GC.
use a Set when you have a collection which cannot have duplicates. Often a List is used when in fact a Set would be more appropriate, depending on the operations you perform, this can also be faster by reducing time complexity.
consider using an enum with one instance for a singleton (if you have to use singletons at all) This is much simpler as well as faster than double check locking. Hint: try to only have stateless singletons.
writing simpler, well structured code is also easier for the JIT to optimise. This is where trying to out smart the JIT with more complex solutions will back fire because you end up confusing the JIT and what you think should be faster is actually slower. (And it's more complicated as well)
try to reduce how much you write to the console (and IO in general) in critical sections. Writing to the console is so expensive, both for the program and the poor human having to read it that is it worth spending more time producing concise console output.
try to use a StringBuilder when you have a loop of elements to add. Note: Avoid using StringBuilder for one liners, just series of append() as this can actually be slower and harder to read.
Perfection is achieved, not when there is nothing more to add, but when there is nothing left to take away. --
Antoine de Saint-Exupery,
French writer (1900 - 1944)
Developers like to solve hard problems and there is a very strong temptation to solve problems which don't need to be solved. This is a very common behaviour for developers of up to 10 years experience (it was for me anyway ;), after about this point you have already solved most common problem before and you start selecting the best/minimum set of solutions which will solve a problem. This is the point you want to get to in your career and you will be able to develop quality software in far less time than you could before.
If you dream up an interesting problem to solve, go ahead and solve it in your own time, see what difference it makes, but don't include it in your working code unless you know (because you measured) that it really makes a difference.
However, if you find a simpler, elegant solution to a problem, this is worth including not because it might be faster (thought it might be), but because it should make the code easier to understand and maintain and this is usually far more valuable use of your time. Successfully used software usually costs three times as much to maintain as it cost to develop. Do what will make the life of the poor person who has to understand why you did something easier (which is harder if you didn't do it for any good reason in the first place) as this might be you one day ;)
A good example on when you might make an application slower to improve reasoning, is in the use of immutable values and concurrency. Immutable values are usually slower than mutable ones, sometimes much slower, however when used with concurrency, mutable state is very hard to get provably right, and you need this because testing it is good but not reliable. Using concurrency you have much more CPU to burn so a bit more cost in using immutable objects is a very sensible trade off. In some cases using immutable objects can allow you to avoid using locks and actually improve throughput. e.g. CopyOnWriteArrayList, if you have a high read to write ration.

Benchmarking of RCPP or RCaller of C++ or Java calling R script?

I have looked high and low for this answer so I resorted to posting here. Is there any expectation of any noticeable latency if I have a Linux C++ program call an R script/function with something like RCpp? Would this be expected or even sound reasonable? What if I use something like RCaller from a Java JAR file? Do you think C++ is still faster than Java if it is calling the same R script/function? Any expected differences?
Thanks
I think you want RInside which makes it very easy to embed R in your C++ application. It ships with numerous examples in four directories, including some to use it with Qt, Wt (for webapps) and MPI.
In that framework, you instantiate R once at startup and then have your own instance. Round-trip latency will be whatever time it takes you to send a command to the R instance, plus however long R takes (which may well dominate) plus the return.
RInside uses Rcpp so you get whole object transfer and all the other niceties. Have a look at the RInside example, and post questions on the rcpp-devel list.
I don't have special knowledge of the R foreign function interface or RCpp but have worked with quite a few others. Your questions can't be answered with certainty. There are only some rules of thumb. The job of an FFI is to satisfy the assumptions of both the calling and called environments. This is usually about matching the data layouts of both languages by copying from one to the other. (This is what RCpp is all about.) Or you can be very lucky and have them match. If the runtime environments are similar or the data being moved over the boundary between languages is small, this can be very efficient: not much more costly than a self function call. Calling C from Fortran is often very fast for this reason. If the environments are very different, large data structures must be copied. Copies consume resources: memory and processor cycles. Garbage collection is the poster child for differences between environments: separate collectors will seldom (read never) cooperate. R and Java (both garbage collected) will probably require copying for this reason. If you are writing the C++ specifically to calL R, you may be able to set up your data in RCpp structures so that no copies are needed.
I'd write some small tests starting with C++ that mimic the amount of data you must move through the interface. Run and time them to get the overhead cost. From this you can make real decisions.

Obsolete Java Optimization Tips

There are number of performance tips made obsolete by Java compiler and especially Profile-guided optimization. For example, these platform-provided optimizations can drastically (according to sources) reduces the cost of virtual function calls. VM is also capable of method inlining, loop unrolling etc.
What are other performance optimization techniques you came around still being applied but are actually made obsolete by optimization mechanisms found in more modern JVMs?
The final modifier on methods and method parameters doesn't help with the performance at all.
Also, the Java HotSpot wiki gives a good overview of the optimizations used by HotSpot and how to efficiently use them in Java code.
People replacing String a = "this" + var1 + " is " + var2; with multiple calls to StringBuilder or StringBuffer. It actually already uses StringBuilder behind the scenes.
It is necessary to define time/memory trade-offs before starting the performance optimization. This is how I do it for my memory/time critical application (repeating some answers above, to be complete):
Rule #1 Never do performance optimization on the earlier stage of development. Never do it if your don't need it really. If decided to do it, then:
use profiler to find bottlenecks, review the source code to find the reasons for bottlenecks;
choose appropriate data structure with the best fit into the defined time/memory trade-offs;
choose appropriate algorithms (e.g. iteration vs recursion, etc);
avoid using synchronized objects from java library, if you don't need it really;
avoid explicitly/implicitly new object creation;
override/re-implement data types/algorithms coming with the java if and only if you are sure they doesn't fit your requirements.
Use small, independent tests to test the performance of chosen algos/data structures.
In 2001 I made apps for a J2ME phone. It was the size of a brick. And very nearly the computational power of a brick.
Making Java apps run acceptably on it required writing them in as procedural fashion as possible. Furthermore, the very large performance improvement was to catch the ArrayIndexOutOfBoundsException to exit for-loops over all items in a vector. Think about that!
Even on Android there are 'fast' loops through all items in an array and 'slow' ways of writing the same thing, as mentioned in the Google IO videos on dalvik VM internals.
However, in answer to your question, I would say that it is most unusual to have to micro-optimise this kind of thing these days, and I'd further expect that on a JIT VM (even the new Android 2.2 VM, which adds JIT) these optimisations are moot.
In 2001 the phone ran KVM interpreter at 33MHz. Now it runs dalvik - a much faster VM than KVM - at 500MHz to 1500MHz, with a much faster ARM architecture (better processor even allowing for clock speed gains) with L1 e.t.c. and JIT arrives.
We are not yet in the realms where I'd be comfortable doing direct pixel manipulation in Java - either on-phone or on the desktop with an i7 - so there are still normal every-day code that Java isn't fast enough for. Here's an interesting blog that claims an expert has said that Java is 80% of C++ speed for some heavy CPU task; I am sceptical, I write image manipulation code and I see an order of magnitude between Java and native for loops over pixels. Maybe I'm missing some trick...? :D
Don't manually call the garbage collector, it hurts performance on modern JVM implementations.
Integer instead of Long will not save much space, but will limit the range of the numbers.
Avoid hand generated Enum classes and use the built in Enum instead. Java 1.5 introduced real Enums, use them.
When using x64 JVM with RAM less than 32GB:
64bit JVM use 30%-50% more memory in comparision to 32bit JVM because of bigger ordinary object pointers. You can heavily reduce this factor by using JDK6+.
From JDK6u6p to JDK6u22 it is optional and can be enabled by adding JVM argument:
-XX:+UseCompressedOops
From JDK6u23 (JDK7 also) it is enabled by default. More info here.
"Premature optimization is the root of all evil"(Donald Knuth)
It is useful to optimize only the bottlenecks.
You should analyze the code in each situation. Maybe you can replace the TreeSet by a fast HashSet because you don't need the sorting feature or maybe you can use float instead of double( look at the Android SDK).
If no technique helps you can try to rewrite a piece of code and call it via JNI, so that native code is working.
I found links above outdated. Here is a new one on Java optimization: http://www.appperfect.com/support/java-coding-rules/optimization.html

How to generate histogram of Java object lifetimes

I have a Tomcat Java webapp which is thrashing the Java GC when under load. I think this is due to a combination of a large amount of short lived objects along with an unknown amount of moderately long lived objects.
To validate this theory I want to find a tool which will let me determine the object lifetimes for all allocated objects (or every 10th object etc for better performance). Ideally the final output will be a histogram showing the relative number of objects which live for different amounts of time.
I think this tool will likely be built on top of either the Instrumentation API or the JVMTI. If there are no good tools which already do this I would also appreciate suggestions about which of the JVM's interfaces would be best to use when writing such a tool.
I have now started writing a tool to do what I originally asked about. The current code can be found here:
http://wiki.github.com/mchr3k/org.inmemprofiler/
So far I have managed to get a textual histogram of all object allocations by instance count. This does not include array allocations which are handled differently.
I am now working on adding instance size information along with tracking of array allocations by using the JVMTI.

determining java memory usage

Hmmm. Is there a primer anywhere on memory usage in Java? I would have thought Sun or IBM would have had a good article on the subject but I can't find anything that looks really solid. I'm interested in knowing two things:
at runtime, figuring out how much memory the classes in my package are using at a given time
at design time, estimating general memory overhead requirements for various things like:
how much memory overhead is required for an empty object (in addition to the space required by its fields)
how much memory overhead is required when creating closures
how much memory overhead is required for collections like ArrayList
I may have hundreds of thousands of objects created and I want to be a "good neighbor" to not be overly wasteful of RAM. I mean I don't really care whether I'm using 10% more memory than the "optimal case" (whatever that is), but if I'm implementing something that uses 5x as much memory as I could if I made a simple change, I'd want to use less memory (or be able to create more objects for a fixed amount of memory available).
I found a few articles (Java Specialists' Newsletter and something from Javaworld) and one of the builtin classes java.lang.instrument.getObjectSize() which claims to measure an "approximation" (??) of memory use, but these all seem kind of vague...
(and yes I realize that a JVM running on two different OS's may be likely to use different amounts of memory for different objects)
I used JProfiler a number of years ago and it did a good job, and you could break down memory usage to a fairly granular level.
As of Java 5, on Hotspot and other VMs that support it, you can use the Instrumentation interface to ask the VM the memory usage of a given object. It's fiddly but you can do it.
In case you want to try this method, I've added a page to my web site on querying the memory size of a Java object using the Instrumentation framework.
As a rough guide in Hotspot on 32 bit machines:
objects use 8 bytes for
"housekeeping"
fields use what you'd expect them to
use given their bit length (though booleans tend to be allocated an entire byte)
object references use 4 bytes
overall obejct size has a
granularity of 8 bytes (i.e. if you
have an object with 1 boolean field
it will use 16 bytes; if you have an
object with 8 booleans it will also
use 16 bytes)
There's nothing special about collections in terms of how the VM treats them. Their memory usage is the total of their internal fields plus -- if you're counting this -- the usage of each object they contain. You need to factor in things like the default array size of an ArrayList, and the fact that that size increases by 1.5 whenever the list gets full. But either asking the VM or using the above metrics, looking at the source code to the collections and "working it through" will essentially get you to the answer.
If by "closure" you mean something like a Runnable or Callable, well again it's just a boring old object like any other. (N.B. They aren't really closures!!)
You can use JMP, but it's only caught up to Java 1.5.
I've used the profiler that comes with newer versions of Netbeans a couple of times and it works very well, supplying you with a ton of information about memory usage and runtime of your programs. Definitely a good place to start.
If you are using a pre 1.5 VM - You can get the approx size of objects by using serialization. Be warned though.. this can require double the amount of memory for that object.
See if PerfAnal will give you what you are looking for.
This might be not the exact answer you are looking for, but the bosts of the following link will give you very good pointers. Other Question about Memory
I believe the profiler included in Netbeans can moniter memory usage also, you can try that

Categories

Resources