In my current project (OpenGL Voxel Engine) I have a serious issue when generating models. I have a very object oriented structure, meaning that even single parameters of my vertices are Objects. This way I am creating about 75000 Objects for 750 voxels in about 5 seconds. Is Java really this slow when allocating new Objects or do I miss a big failure somewhere in my code?
Very big question. Generally speaking, it depends from the object class definition and by the amount of work required to construct object.
Some issue:
avoid finalize method,
tune memory and GC in order to avoid excessive GC activity,
avoid big work during constructor,
do not use syncronization call during object construction,
use Weak references
these issues solved my problem.
See also http://oreilly.com/catalog/javapt/chapter/ch04.html
Finally let me suggest you the (deprecated) Object Pool pattern or reuse objects.
Concluding, no, generally speaking, java object creation is not slow
Of course it isn't. The following code allocates 10 million objects and stores them in an array. On my 5 year old notebook, it completes in 1.4 seconds.
public class Test {
public static void main(String[] args) {
Object[] o = new Object[10_000_000];
long start = System.nanoTime();
for (int i = 0; i < o.length; i++) {
o[i] = new Object();
}
long end = System.nanoTime();
System.out.println(Arrays.hashCode(o));
System.out.println(new BigDecimal(end - start).movePointLeft(9));
}
}
... and that's even though this benchmark is quite naive in that it doesn't trigger just in time compilation of the code under test before starting the timer.
Simply creating 75,000 objects should not take 5 seconds. Take a look at the work your constructor is doing. What else are you doing during this time besides creating the objects? Have you tried timing the code to pinpoint where delays occur?
Objects will be slower than primitives, and they will also consume considerably more memory - so it's possible you are going overboard on them. It's hard to say without seeing more details.
75000 objects will not take a long time to create though, try this:
List<Integer> numbers = new ArrayList<Integer>();
for(int i = 0;i<75000;i++){
numbers.add(i); // Note this will autobox creating an Integer object after the first 128
}
System.out.println(numbers.size());
}
http://www.tryjava8.com/app/snippets/52d070b1e4b004716da5cb4f
Total time taken less than a second.
When I put the number up to 7,500,000 it finally took a second...
The new operator in java is very fast compared to the common approach in languages without automatic memory management (e.g. the new operator is usually faster than the malloc-command in C because it does not need a system call).
Although the new operator can still be a bottleneck, it is certainly not the problem in your case. Creating 75K objects should be WAY faster than 5 seconds.
I have the same issue with creating new objects.
My object in constructor allocate single three dimensional array 64x64x64 and no more. FPS fell down to quarter of a value.
I solve this issue with reusing old object and reset it's state (BTW this method reallocate this array without lost performance).
If I move allocation array into separate method and call it after creating the object, speed does not increase to acceptable value.
This object I created is in Main game loop.
Related
I'm new to java. I came through the following code while reading an introductory book on Java while reading about the finalize method.
class FDemo{ int x;
FDemo(int i){
x=i;
}
protected void finalize(){
System.out.println("Finalizing " +x)
}
void generator(int i) {
FDemo o= new FDemo(i);
}
}
Now while creating objects I encountered the following in the new class
int count;
FDemo ob= new FDemo(0);
for (count=1;count<10000000;count++)
ob.generator(count);
I'm having trouble understanding how are we creating new objects using the same name 'o' in the for loop? Would we have to create a new object and then on the next iteration discard the existing object 'o' throughout the loop?
Also, why does finalize execute for 10 million but not for 1000 if we are constantly creating and discarding the same object? Like I said, I'm a beginner and this question might sound very basic or even silly for most of the people here but I would appreciate it very much if you could take out a few minutes to answer.
Thank you
Also, why does finalize execute for 10 million but not for 1000 if we
are constantly creating and discarding the same object
You really create 10 million distinct objects in this applications's lifetime, each of which gets referenced by o , one after the other.
Each time, the de-referenced one becomes eligible for garbage collection, because it has become unreachable from the application, and the garbage collector then calls it's finalize method.
How are we creating new objects using the same name 'o' in the for loop?
You should learn some C and how pointers works, Java hide this, so it can be weird some time.
In Java, there is 2 type of data : objects (like String or your FDemo) and primitives (like int, char...).
Variables that references a primitive works like you intended to, each time you give it a new value, it erase the previous one.
Variables that references objects don't work that way, they are pointers. A pointer can be seen as an address. It's clearer in C (and C++), where they are in fact primitives and can be print as well.
Next come the life time of your variables. When you quit the section where you variable is declared, it's cease to exist (but objects are not automatically destroyed and I think it's the purpose of your exercise).
As example :
public void someMethod() {
int a = 1;
// I have access to a
{ // I create a new section, generally, it's use by condition, loop...
int b = 2;
// Here I have access to a and b
} // End of my section
// b is destroyed, I still have access to a
}
// I'm outside my method, a is destroyed
Why does finalize execute for 10 million but not for 1000 if we are constantly creating and discarding the same object?
That's the purpose of the Java's Garbage Collector. It's a big system used to clean memory. It destroys (call the finalize() method) all object that don't have pointers that references them. It's only called when you really need it, because it can use a lot of processing power (in old machine, applications could freeze when the garbage collector starts).
Your object is very simple (only 1 primitive), so it doesn't use a lot of memory. That's why the garbage collector is called only when you create 10 millions objects.
Ok I'm going to break this up into parts.
How are we creating new objects using the same name 'o' in the for
loop?
So, what you are doing here is actually just overriding/re-assiging the reference variable of o to a differnt FDemo. That leaves the old one empty and eventually gets destroyed by garbage collector. (Which is what invokes the finalize() method)
Would we have to create a new object and then on the next iteration
discard the existing object 'o' throughout the loop?
Well that is exactly what you are doing, when you re assign o you are overwriting the old one.
Also, why does finalize execute for 10 million but not for 1000 if we
are constantly creating and discarding the same object?
Well, this is because java's trash collector is only triggered when a massive amount of objects are made. However, I am surprised that 100000 didn't do it.
The thing you have to remember about finalize(), its only called on the trash collection of the object. Now, thats a very unreliable process and isn't really within your control. Like #TT. said in the comments, dont rely on this. The program that you have written simpliy forces the finalize() method to eventually be invoked due to generating a massive amount of objects intentionally. It's a good way to learn about finalize and how it works, but in practice this may not be a great solution.
tl;dr: In Java, which is better, reusing of container object or creating object every time and let garbage collector do the work
I am dealing with huge amount of data in Java where frequently I have following type of code structure:-
Version1:
for(...){//outer loop
HashSet<Integer> test = new HashSet<>(); //Some container
for(...){
//Inner loop working on the above container Data Structure
}
//More operation on the container defined above
}//Outer loop ends
Here I allocated new memory every time in a loop and do some operations in inner/outer loop before allocating empty memory again.
Now I am concerned about the memory leaks in Java. I know that Java has a fairly good Garbage Collector but instead of relying on that should I modify my code as follows:-
Version2:
HashSet<Integer> test = null;
for(...){//outer loop
if(test == null){
test = new HashSet<>(); //Some container
}else{
test.clear()
}
for(...){
//Inner loop working on the above container Data Structure
}
//More operation on the container defined above
}//Outer loop ends
I have three questions:-
Which will perform better, or there is no definitive answer.
Will second version will have more time complexity? In other other words is clear() function O(1) of O(n) in complexity. I didn't anything in javadocs.
This pattern is quite common, which version is more recommended one?
To my opinion it's better to use the first approach. Note that HashSet.clear never shrinks the size of hash-table. Thus if the first iteration of the outer loop adds many elements to the set, the hash-table will become quite big, but on the subsequent iterations even if much less space is necessary if won't be shrinked.
Also first version makes the further refactoring easier: you may later want to put the whole inner loop into the separate method. Using the first version you can just move it together with HashSet.
Finally note that for garbage-collection it's usually easier to manage short-lived objects. If your HashSet is long-lived, it may be moved to old generation and removed only during the full GC.
I think it's simpler to create a new HashSet each time, and likely to be less prone to refactoring errors later on. Unless you have a good reason to resuse the HashSet (Garbage Collection pauses are an issue for you, and profiling shows this part of the code is the cause) - I would keep things as simple as possible and stick to 1. Focus on maintainability, Premature Optimization should be avoided.
I would recommend you to stick to the first variant. The main reason behind this will be keeping the scope of your HashSet variable as small as possible. This way you actually ensure that it will be eligible for garbage collection after the iteration has ended. Promoting it's scope may cause other problems - the reference can be later used to actually change the state of the object.
Also, most modern Java compilers will produce the same byte code if you are creating the instance inside or outside the loop.
Which one is faster?. Actually the answer could vary depending on various factors.
Version-1 advantages :
Predictive branching at processor level might make this faster.
Scope of instance is limited to the first loop. If reference doesn't escape, JIT might actually compile your method. GC's job will
probably be easier.
Version -2 :
Less time in creation of new containers (frankly, this is not too much).
clear() is O(n)
Escaped reference might prevent JIT from making some optimizations.
Which one to choose?. measure performance for both versions several times. Then if you find significant difference, change your code, if not, don't do anything :)
Version 2 is better
but it will take little bit of more time but memory performance will be good
It depends.
Recycling objects can be useful in tight loops to eliminate GC pressure. Especially when the object is too large for the young generation or the loop runs long enough for it be tenured.
But in your particular example it's it may not help much because a hashset still contains node objects which will be created on inserting and become eligible for GC on clearing.
On the other hand, if you put so many items into the set that its internal Object[] array has to be resized multiple times and becomes too large for the young generation then it might be useful to recycle the set. But in that case you should be pre-sizing the set anyway.
Additionally objects that only live for the duration of a code block may be eligible for object decomposition/stack allocation via escape analysis. The shorter their lifetime and the less complex the code-paths touching those objects the more likely it is for EA to succeed.
In the end it doesn't matter much though until this method actually becomes an allocation hotspot in your application, in which case it would show up in profiler results and you could act accordingly.
Let's say we are trying to build a document scanner class in java that takes 1 input argument, the log path(eg. C:\document\text1.txt). Which of the following implementations would you prefer based on performance/memory/modularity?
ArrayList<String> fileListArray = new ArrayList<String>();
fileListArray.add("C:\\document\\text1.txt");
fileListArray.add("C:\\document\\text2.txt");
.
.
.
//Implementation A
for(int i =0, j = fileListArray.size(); i < j; i++){
MyDocumentScanner ds = new MyDocumentScanner(fileListArray.get(i));
ds.scanDocument();
ds.resultOutput();
}
//Implementation B
MyDocumentScanner ds = new MyDocumentScanner();
for(int i=0, j=fileListArray.size(); i < j; i++){
ds.setDocPath(fileListArray.get(i));
ds.scanDocument();
ds.resultOutput();
}
Personally I would prefer A due to its encapsulation, but it seems like more memory usage due to creation of multiple instances. I'm curious if there is an answer to this, or it is another "that depends on the situation/circumstances" dilemma?
Although this is obviously opinion-based, I will try an answer to tell my opinion.
You approach A is far better. Your document scanner obviously handles a file. That should be set at construction time and be saved in an instance field. So every method can refer to this field. Moreover, the constructor can do some checks on the file reference (null check, existence, ...).
Your approach B has two very serious disadvantages:
After constructing a document scanner, clients could easily call all of the methods. If no file was set before, you must handle that "illegal state" with maybe an IllegalStateException. Thus, this approach increases code and complexity of that class.
There seems to be a series of method calls that a client should or can perform. It's easy to call the file setting method again in the middle of such a series with a completely other file, breaking the whole scan facility. To avoid this, your setter (for the file) should remember whether a file was already set. And that nearly automatically leads to approach A.
Regarding the creation of objects: Modern JVMs are really very fast at creating objects. Usually, there is no measurable performance overhead for that. The processing time (here: the scan) usually is much higher.
If you don't need multiple instances of DocumentScanner to co-exist, I see no point in creating a new instance in each iteration of the loop. It just creates work to the garbage collector, which has to free each of those instances.
If the length of the array is small, it doesn't make much difference which implementation you choose, but for large arrays, implementation B is more efficient, both in terms of memory (less instances created that the GC hasn't freed yet) and CPU (less work for the GC).
Are you implementing DocumentScanner or using an existing class?
If the latter, and it was designed for being able to parse multiple documents in a row, you can just reuse the object as in variant B.
However, if you are designing DocumentScanner, I would recommend to design it such that it handles a single document and does not even have a setDocPath method. This leads to less mutable state in that class and thus makes its design much easier. Also using an instance of the class becomes less error-prone.
As for performance, there won't be a measurable difference unless instantiating a DocumentScanner is doing a lot of work (like instantiating many other objects, too). Instantiating and freeing objects in Java is pretty cheap if they are used only for a short time due to the generational garbage collector.
Here I would focus on custom application where I got degradation (no need for general discussion about fastness of threads against processes).
I've got MPI application on Java which solve some problem using iteration method. The schematic view to application bellow lets call it MyProcess(n), where "n" is the number of processes:
double[] myArray = new double[M*K];
for(int iter = 0;iter<iterationCount;++iter)
{
//some communication between processes
//main loop
for(M)
for(K)
{
//linear sequence of arithmetical instructions
}
//some communication between processes
}
To improve performance I've decided to use Java threads (lets call it MyThreads(n)). The code is almost the same – myArray becomes matrix, where each row contains array for appropriate thread.
double[][] myArray = new double[threadNumber][M*K];
public void run()
{
for(int iter = 0;iter<iterationCount;++iter)
{
//some synchronization primitives
//main loop
for(M)
for(K)
{
//linear sequence of arithmetical instructions
counter++;
}
// some synchronization primitives
}
}
Threads created and started using Executors.newFixedThreadPool(threadNumber).
The problem is that while for MyProcess(n) we got adequate performance(n in [1,8]), in case of MyThreads(n) performance degrades essentially(on my system by factor of n).
Hardware: Intel(R) Xeon(R) CPU X5355(2 processors, 4 cores on each)
Java version: 1.5(using d32 option).
At first I thought that got different workloads on threads, but no, variable “counter” shows, that number of iterations between different run of MyThreads(n) (n in [1,8]) are identical.
And it isn’t synchronization fault, because I have temporary comment all synchronization primitives.
Any suggestions/ideas would be appreciated.
Thanks.
There are 2 issues I see in your piece of code.
Firstly caching problem. Since you try to do this in multi thread/process I'd assume your M * K results in a large number; then when you do
double[][] myArray = new double[threadNumber][M*K];
You are essentially creating an array of double pointer with size threadNumber; each pointing to a double array of size M*K. The interesting point here is that the threadNumber count of arrays are not necessarily allocated onto the same block of memory. They are just double pointers which can be allocated anywhere inside JVM heap. As a result, when multiple threads run, you might encounter a lot of cache miss and you end up reading memory many times, eventually slow down your program.
If the above is the root cause, you can try enlarge your JVM heap size, and then do
double[] myArray = new double[threadNumber * M * K];
And have the threads operating on different segment of the same array. You should be able to see performance better.
Secondly synchronization issue. Note that double (or any primitive) array is NOT volatile. Thus your result on 1 thread isn't guaranteed to be visible to other threads. If you are using synchronization block this resolves the issue, as a side effect of synchronization is make sure visibility across threads; If not, when you are reading and writing the array, please always make sure you use Unsafe.putXXXVolatile() and Unsafe.getXXXVolatile() so that you can do volatile operations on arrays.
To take this further, Unsafe can also be used to create a continuous segment of memory which you can used to hold your data structure and achieve better performance. In your case I think 1) already do the trick.
Hello I am curious are there any serious performance consequences from performing the following type of cast? Especially when it's performance millions of times thanks
Object [] car = new Object[1];
car[0] = new Long[2][2];
long[][] values = (long[][]) car[0];
Casting really isn't much of a performance issue. It's just meta data for the compiler to know how to treat the object. Of course, if it tries to use a object as the wrong type, you'll get a ClassCastException, which can cause performance issues.
I'd say the performance issue is that that case makes absolutely no sense whatsoever. Why would you ever do that?
The code you have written will cause a class cast exception. Throwing millions of class cast exceptions will probably be slow. It is also unlikely to be the intended logic.
The impact of a cast depends on your jvm and the code in which it is used. The cast operation should be highly optimized in modern jvms since it is used quite often for generic classes so its overhead should be quite low.
If your code has to be fast you should profile it to find bottlenecks, this will also answer if the cast is a problem in your specific case.
You can't do the following cast. I suggest you make the array a long[][] from the start and you won't need to convert the array type.
// these won't work as these are different types of references.
long[] longs = (long[]) new Long[0];
long[][] longs = (long[][]) new Long[0][];
The only way to convert them is to iterate over them.
Long[][] longs = ...
long[][] longs2 = new long[longs.length][];
for(int i=0;i<longs.length;i++) {
longs2[i] = new long[longs[i].length];
for(int j=0;j<longs[i].length;j++) longs2[i][j] = longs[i][j];
}
The main performance cost is in creating the Long[][] in the first place as you have to create many objects whereas with long[][] you have only the arrays making the structure much more efficient for memory and cpu.
if hotspot can prove that Object is actually long[][] the cost is none, otherwise it costs a check + branch prediction, which usually is successful and it is an extra (only one) cpu cycle.
The casting is not exactly free like one of the answer suggests and it's not only metadata.