Java-Gaming.org    
Featured games (81)
games approved by the League of Dukes
Games in Showcase (498)
Games in Android Showcase (116)
games submitted by our members
Games in WIP (563)
games currently in development
News: Read the Java Gaming Resources, or peek at the official Java tutorials
 
   Home   Help   Search   Login   Register   
  Show Posts
Pages: [1] 2 3 ... 15
1  Game Development / Game Mechanics / Re: Composition heavy OOP vs pure entity component systems? on: 2012-08-20 18:23:57
Composition is a good way to split a class that is too big to manage.

It also make it easier to reuse one part of the big class at another place since you already split it in functionality.

Anyway, I'm the only I know that use a MVC composition scheme for writing big class (and it works well).
2  Game Development / Shared Code / Re: Actor Model : Java short implementation on: 2012-08-17 02:23:14
I see a number of big issues in the Java implementation up top.  The big no-no is the use of a single thread per-actor, which you simply should never be doing for any kind of serious actor system.  Use a thread pool, or better yet make the execution strategy pluggable.

The overloading of wait/notify/notifyAll is probably not a good idea either, since it's too easily confused with the same-named methods on Object, but it's minor compared to that previous one.  I think everyone should explore the actor model, try inventing their own, but then look at an industrial-strength implementation and see what they do differently and why.  

Thx for pointing that out. I changed it to use a thread pool instead and my performance increased by 6 times. Strangely, the default Scala actors don't seems so fast. For sending and receiving 100000 messages it takes :

Mine : 100 millis (1 micro per message in average)
Scala : 1000 millis (10 micro per message in average)

 persecutioncomplex

Only problems is that by default, my thread pool is always running until I close my JVM. Wonder what is the best solution for that;

- adding start()/stop() method to actor and when at least one actor is running the thread pool is running
- manually starting/stopping the thread pool directly in the code

EDIT : Decided to make an ActorSystem like Akka. You can specify which ActorSystem an Actor use and you need to start/stop the ActorSystem.
3  Game Development / Shared Code / Re: Actor Model : Java short implementation on: 2012-08-15 21:59:59
PingPong with Scala Actors

1  
2  
3  
4  
5  
6  
7  
8  
9  
10  
11  
12  
13  
14  
15  
16  
17  
18  
19  
20  
21  
22  
23  
24  
25  
26  
27  
28  
29  
30  
31  
32  
33  
34  
35  
36  
37  
38  
39  
40  
41  
42  
43  
44  
45  
46  
47  
48  
49  
50  
51  
52  
53  
54  
55  
56  
57  
58  
59  
60  
61  
62  
import scala.actors.Actor;

object PingPong {

case object Ping
case object Pong
case object Stop

class Ping(count: Int, pong: Pong) extends Actor{
   def act(){
       var begin = System.nanoTime();
      var pingsLeft = count - 1;
      pong ! Ping;
      while (true) {
         receive {
         case Pong =>
         if (pingsLeft % 1000 == 0)
            Console.println("Ping: pong")
            if (pingsLeft > 0) {
               pong ! Ping
               pingsLeft -= 1
            } else {
               Console.println("Ping: stop")
               pong ! Stop
               var end = System.nanoTime();
               var delta = end-begin;
               println(delta);
               println(delta/(1000*1000));
               exit()
            }
         }
      }
     
   }
}

class Pong extends Actor{
   def act(){
      var pongCount = 0;
      while (true) {
         receive {
         case Ping =>
         if (pongCount % 1000 == 0)
            Console.println("Pong: ping "+pongCount)
            sender ! Pong
            pongCount = pongCount + 1
         case Stop =>
         Console.println("Pong: stop")
         exit()
         }
      }
   }
}

def main(args: Array[String]){
   val pong = new Pong;
   val ping = new Ping(100000, pong);
   ping.start
   pong.start
}

}


PingPong with my Java actors

1  
2  
3  
4  
5  
6  
7  
8  
9  
10  
11  
12  
13  
14  
15  
16  
17  
18  
19  
20  
21  
22  
23  
24  
25  
26  
27  
28  
29  
30  
31  
32  
33  
34  
35  
36  
37  
38  
39  
40  
41  
42  
43  
44  
45  
46  
47  
48  
49  
50  
51  
52  
53  
54  
55  
56  
57  
58  
59  
60  
61  
62  
63  
64  
65  
66  
67  
68  
69  
70  
71  
72  
73  
74  
75  
76  
77  
78  
79  
import main.Actor;
import main.Message;

public class PingPong {
   
   private class Stop { }
   
   private static class Ping extends Actor {
     
      private int pingLeft;
      private Pong pong;
     
      public Ping(int count, Pong pong){
         pingLeft = count;
         this.pong = pong;
      }
     
      @Override
      public void init() {
         pingLeft--;
         send(Ping.class, pong);
      }

      @Override
      public void receive(Message m) {
         if(is(Pong.class)){
            if(pingLeft % 1000 == 0){
               println("Ping: pong");
            }
            pingLeft--;
            if(pingLeft > 0){
               send(Ping.class, pong);
            }else{
               println("Ping: stop");
               send(Stop.class, pong);
               stop();
            }
         }
      }

      @Override
      public void end() { }
     
   }
   
   private static class Pong extends Actor {
     
      private int pongCount = 0;

      @Override
      public void init() { }

      @Override
      public void receive(Message m) {
         if(is(Ping.class)){
            if(pongCount % 1000 == 0){
               println("Pong: ping " + pongCount);
            }
            send(Pong.class, m.source);
            pongCount++;
         }else if(is(Stop.class)){
            println("Pong: stop");
            stop();
         }
      }

      @Override
      public void end() { }

   }
   
   public static void main(String [] args){
      Pong pong = new Pong();
      Ping ping = new Ping(100000, pong);
      pong.act();
      ping.act();
   }

}
4  Game Development / Shared Code / Actor Model : Java short implementation on: 2012-08-15 21:58:02
I just learned about the actor model a while ago and decided to see if I could do something similar in Java. The result is pretty short, only 2 class and it works.

1  
2  
3  
4  
5  
6  
7  
8  
9  
10  
11  
public class Message {
   
   public final Object object;
   public final Actor source;
   
   public Message(Object object, Actor source){
      this.object = object;
      this.source = source;
   }

}


1  
2  
3  
4  
5  
6  
7  
8  
9  
10  
11  
12  
13  
14  
15  
16  
17  
18  
19  
20  
21  
22  
23  
24  
25  
26  
27  
28  
29  
30  
31  
32  
33  
34  
35  
36  
37  
38  
39  
40  
41  
42  
43  
44  
45  
46  
47  
48  
49  
50  
51  
52  
53  
54  
55  
56  
57  
58  
59  
60  
61  
62  
63  
64  
65  
66  
67  
68  
69  
70  
71  
72  
73  
74  
75  
76  
77  
78  
79  
80  
81  
82  
83  
84  
85  
86  
87  
88  
89  
90  
91  
92  
93  
94  
95  
96  
97  
98  
99  
100  
101  
102  
103  
104  
105  
106  
107  
108  
109  
110  
111  
112  
113  
114  
115  
116  
117  
118  
119  
120  
121  
122  
123  
124  
import java.util.ArrayList;
import java.util.HashMap;

public abstract class Actor implements Runnable{
   
   private Thread thread;
   private ArrayList<Message> messageList = new ArrayList<Message>();
   private HashMap<Object, ArrayList<Message>> waitMap = new HashMap<Object, ArrayList<Message>>();
   private Object current = null;
   
   private synchronized void add(Message m){
      messageList.add(m);
      notify();
   }
   
   private synchronized Message get(){
      return messageList.remove(0);
   }
   
   private synchronized void waiting(){
      if(messageList.size() == 0){
         try { wait(); }
         catch (InterruptedException e) { } //Do nothing
     }
   }
   
   public void wait(Object key, Message m){
      ArrayList<Message> list = waitMap.get(key);
      if(list == null){
         list = new ArrayList<Message>();
         waitMap.put(key, list);
      }
      list.add(m);
   }
   
   public void notify(Object key){
      ArrayList<Message> list = waitMap.get(key);
      if(list != null && list.size() > 0){
         Message m = list.remove(0);
         add(m);
         if(list.size() == 0){
            waitMap.put(key, null);
         }
      }
   }
   
   public void notifyAll(Object key){
      ArrayList<Message> list = waitMap.get(key);
      if(list != null && list.size() > 0){
         for(Message m : list){
            add(m);
         }
         list.clear();
         waitMap.put(key, null);
      }
   }
   
   public void sleep(int milli){
      try { Thread.sleep(milli); }
      catch (InterruptedException e){ }; //Do nothing
  }
   
   public void println(Object o){
      System.out.println(o);
   }
   
   public void println(){
      System.out.println();
   }
   
   public void print(Object o){
      System.out.print(o);
   }
   
   public void send(Object o, Actor actor){
      if(actor != null){
         actor.add(new Message(o, this));
      }
   }
   
   public void act() {
      thread = new Thread(this);
      thread.start();
   }
   
   public void stop() {
      thread.interrupt();
   }

   @Override
   public void run() {
      init();
      while(!thread.isInterrupted()){
         if(messageList.size() > 0){
            Message m = get();
            current = m.object;
            receive(m);
         }else{ waiting(); }
      }
      end();
   }
   
   public boolean is(Object o){
      if(current == null){ return false; }
      else{ return current.equals(o); }
   }
   
   public boolean isA(Object o){
      if(current == null || o == null){ return false; }
      else{ return o.getClass().isInstance(current); }
   }
   
   public <E> boolean isA(Class<E> c){
      if(current == null || c == null){ return false; }
      else{ return c.isInstance(current); }
   }

   public abstract void init();
   
   public abstract void receive(Message m);
   
   public abstract void end();

}
5  Games Center / WIP games, tools & toy projects / Re: Pink Point on: 2012-08-12 22:39:54
Looks fun Smiley
6  Discussions / Miscellaneous Topics / Re: What is wrong with me? on: 2012-08-12 13:52:23
Once every few months, Eclipse just stops compiling for no reason whatsoever, and you need to close & open the fileyou're editing, or restart Eclipse. Other cuases can be that there are issues with your build-path, which also stops the compiler (for good reason).

Agree, it happens to me a lot of times actually. Most of the time it was when I was working with some plug-ins; different version control and maven if I remember correctly. I have no idea why :S I tried everything, build, clear and build, editing and resaving file. Nothing would work. I had to restart eclipse.
7  Discussions / General Discussions / Re: Nerves of steel or just plain lazy? on: 2012-08-05 22:50:32
We should build something for doing quick prototype or demo. I spend most of my time doing that and every time it's like the same boiler plate code that I have to write again and again. (or copy/paste/trying to find where I already did something similar/refactoring -_-)
8  Discussions / General Discussions / Re: The Unit Testing Advocacy & Derision Thread on: 2012-08-05 17:28:38
Have you tried to manual test every little change that other, not so good, developers are committing to make sure they don't crash the whole project?

Trust me it reduces engineering cost in my case...  Emo
9  Discussions / General Discussions / Re: The Unit Testing Advocacy & Derision Thread on: 2012-08-05 16:01:41
Sorry for reviving this thread but I have to share.

For one month I have been working on a project with 3 other developers that got absolutely no clue what they are doing. When they try to fix something they always break 2 other things. The code is nearly unmanageable. The only thing that still save me are the unit test that I wrote. Every time they change something I can run my test and see if they broke something again. If one test fail, I refuse to merge their work into the main branch.

Really I think unit test were meant for case like that...
10  Discussions / Java Gaming Wiki / Re: ArrayList vs LinkedList on: 2012-08-03 17:54:13
I have to agree with the fact that we will probably never need something else than an ArrayList for game. I tried inserting integer into an arraylist, always in the middle of the list. And I didn't got any performance hit before 10000 elements... After that the performance degrade really fast but I don't think a lot of us are using more than 10000 elements.

<off topic>
Note : With Mark-sweep compact collector there is no fragmentation. I thought Java was using that one instead of Mark-sweep collector for the tenured generation.

@princec : The Concurrent collector is also supposed to do that, but when I tried it the performance were absolutely awful Sad

The concurrent collector performs most of its work concurrently (i.e., while the application is still running) to keep garbage collection pauses short. It is designed for applications with medium- to large-sized data sets for which response time is more important than overall throughput, since the techniques used to minimize pauses can reduce application performance. The concurrent collector is enabled with the option -XX:+UseConcMarkSweepGC.
</off topic>
11  Discussions / Java Gaming Wiki / Re: Concurrency on: 2012-08-03 15:35:24
Immutable object can be used by has many thread as you want without creating any inconsistency. It's kind of useful. Any constants that you declared (public static int SOME_VALUE = 2) is an immutable object.

I'm not really familiar with lock-free data structures. Sad
12  Discussions / Java Gaming Wiki / Re: Java Data structures on: 2012-08-02 01:22:03
I mean it still bothers me that something backed with an array, that has to copy to grow as well as shift indexes is better than LinkedList for regular insertions and the like. Raw. >.>

Well it bother me too when I just finished my class on datastructure but since I learn how to live with it... Creating a lot of object is not free and you need more operation in linked list to add a new element.

Well you might consider using a LinkedArrayList : You get the best of the two world. Here is a quick example

1  
2  
3  
4  
5  
6  
7  
8  
9  
10  
11  
12  
13  
14  
15  
16  
17  
18  
19  
20  
public class ArrayList {
   
   private int[] list = new int[10];
   private int size = 0;
   
   public void add(int n){
      if(size < list.length-1){
         list[size] = n;
         size++;
      }else{
         int[] newlist = new int[list.length*2];
         for(int i=0; i<list.length; i++){
            newlist[i] = list[i];
         }
         list = newlist;
         list[size] = n;
      }
   }

}


1  
2  
3  
4  
5  
6  
7  
8  
9  
10  
11  
12  
13  
14  
15  
16  
17  
18  
19  
20  
21  
22  
23  
24  
25  
26  
27  
28  
29  
30  
31  
32  
33  
34  
35  
36  
37  
38  
39  
40  
41  
42  
43  
44  
45  
46  
public class LinkedArrayList {
   
   private class Node {
      Node next;
      Node previous;
      int[] array = new int[1000];
      int size = 0;
     
      public Node(Node previous){
         this.previous = previous;
      }
     
      public boolean isFull(){
         return size > array.length;
      }
     
      public void add(int n){
         array[size] = n;
      }
   }
   
   private Node head;
   private Node tail;
   private int size = 0;
   
   public void add(int n){
      if(size == 0){
         head = new Node(null);
         tail = head;
         tail.add(n);
         size++;
      }else{
         if(tail.isFull()){
            Node newnode = new Node(tail);
            tail.next = newnode;
            tail = newnode;
            tail.add(n);
            size++;
         }else{
            tail.add(n);
            size++;
         }
      }
   }

}


You can test a lot of insertions with that :

1  
2  
3  
4  
5  
6  
7  
8  
9  
10  
11  
12  
13  
14  
15  
16  
17  
18  
19  
20  
21  
22  
23  
24  
25  
26  
27  
28  
29  
30  
31  
32  
33  
34  
public class Test {
   
   public static void main(String [] args){
      long begin;
      long end;
      long delta;
     
      begin = System.nanoTime();
      ArrayList arrayList = new ArrayList();
      for(int i=0; i<100000000; i++){
         arrayList.add(i);
      }
      end = System.nanoTime();
      delta = end-begin;
      System.out.println("--- ArrayList ---");
      System.out.println("Time elapsed in nano : " + delta);
      System.out.println("Time elapse in milli : " + delta/(1000*1000));
      System.out.println();
     
      begin = System.nanoTime();
      LinkedArrayList linkedArrayList = new LinkedArrayList();
      for(int i=0; i<100000000; i++){
         linkedArrayList.add(i);
      }
      end = System.nanoTime();
      delta = end-begin;
      System.out.println("--- LinkedArrayList ---");
      System.out.println("Time elapsed in nano : " + delta);
      System.out.println("Time elapse in milli : " + delta/(1000*1000));
      System.out.println();
     
   }

}


Here are my results running it :

1  
2  
3  
4  
5  
6  
7  
--- ArrayList ---
Time elapsed in nano : 708601408
Time elapse in milli : 708

--- LinkedArrayList ---
Time elapsed in nano : 362729744
Time elapse in milli : 362


You would probably get even more benefits with insertion since in the ArrayList you have to move every objects back one spot while in the LinkedArrayList you only have to move the object in one Node Smiley
13  Discussions / General Discussions / Re: Garbage collector tuning on: 2012-08-02 00:39:29
Ok ok -_-

I guess I should restate my statement since I was wrong... I did a new benchmark with thread pooling this time. Thread are usually long lived object so they are copied back and forth by the copying collector in the young generation if you don't use thread pooling. That create some heavy burden on the GC and it garbages a lot more. Also, creating a thread and starting it take some time, so it decreases performance too. So object pooling can be useful Smiley

New statement : Don't use object pooling for young objects.

In my first benchmark, I got better result because all objects died as soon as you exited the method. All those objects were easy to garbage by the copying collector since it could just ignore them all and copy only the objects currently alive (which was nearly nothing). Also, the object pooling in that example created a lot of reference from old to young objects which is bad.

On the other hand, in the thread pool benchmark, the thread lived a long time so they were copied back in forth by the copying collector.

In regard to that, using object pooling for particle engine is probably a good idea too because the life of the particles are not so short and so they will be copied back and forth by the copying collector, fill up the young memory space and the GC will do collection a lot.

One thing to note; if you use the wrong size for your object pool you will end up with bad performance (at least for thread). So be careful about the size of your object pool.
14  Discussions / General Discussions / Re: Garbage collector tuning on: 2012-08-01 15:46:52
Seriously, I find it really strange that you get the best performance with G1 cas since that collector was designed to work with server like application using a huge amount of memory and running on multiprocessor machines.

How can that description fit a small game running on a single processor machine? For big desktop game it might be the good choice though
15  Discussions / Java Gaming Wiki / Re: Java Data structures on: 2012-08-01 00:30:08
lol Smiley
16  Discussions / Java Gaming Wiki / Re: Java Data structures on: 2012-07-31 21:26:10
Can someone please explain the differenct between a Vector and a ArrayList in java? I've never used a Vector.

Well the difference is that Vector has some synchronization. To understand it correctly you have to understand the 5 level of synchronization for object and method

1. Immutable : The object can't be modified once created. This is the most safe level. No matter how many thread access this object you won't run into any problem
2. Thread-safe : The object contain enough internal synchronization (synchronized method) to be used without worry by multiple threads.
3. Conditionnaly thread-safe : Same as thread-safe except that under some circonstances, you will need to provide external synchronization (outside of that object)
4. Thread-Compatible : Can be use in multi-threaded environment but it is up to the programmer to do the synchronization
5. Thread-hostile : Can't be use in multi-threaded envrionment (Ex.: Thread.stop() - That method was deprecated because it releases the lock when it is called. Hence it could leave an object into an invalid state)

Vector are Conditionnally thread-safe. That means that most of the time you don't need to provide external synchronization but in some case you might. One of that example is when iterating over the Vector and modifying it.
Collection.getSynchronizedCollection() - (or something like that) are also conditionnally thread-safe : meaning that you have to provide external synchronization for some operation.
ArrayList is thread compatible : meaning that if you want to use it in a multi-threaded environment you have to provide all the synchronization

There are no magic solution to synchronization, except for the human brain Smiley
17  Discussions / General Discussions / Re: Garbage collector tuning on: 2012-07-31 15:05:49
Anyone knows if the JVM can now do that thing or not?

Quote
The JIT compiler can perform additional optimizations that can reduce the cost of object allocation to zero. Consider the code in Listing 2, where the getPosition() method creates a temporary object to hold the coordinates of a point, and the calling method uses the Point object briefly and then discards it. The JIT will likely inline the call to getPosition() and, using a technique called escape analysis, can recognize that no reference to the Point object leaves the doSomething() method. Knowing this, the JIT can then allocate the object on the stack instead of the heap or, even better, optimize the allocation away completely and simply hoist the fields of the Point into registers. While the current Sun JVMs do not yet perform this optimization, future JVMs probably will. The fact that allocation can get even cheaper in the future, with no changes to your code, is just one more reason not to compromise the correctness or maintainability of your program for the sake of avoiding a few extra allocations.

EDIT : It seems it does : Java 7 Enhancements
18  Discussions / General Discussions / Re: Garbage collector tuning on: 2012-07-31 15:01:32
From Java 6 documentation

Quote
5. Available Collectors
The discussion to this point has been about the serial collector. The Java HotSpot VM includes three different collectors, each with different performance characteristics.

1. The serial collector uses a single thread to perform all garbage collection work, which makes it relatively efficient since there is no communication overhead between threads. It is best-suited to single processor machines, since it cannot take advantage of multiprocessor hardware, although it can be useful on multiprocessors for applications with small data sets (up to approximately 100MB). The serial collector is selected by default on certain hardware and operating system configurations, or can be explicitly enabled with the option -XX:+UseSerialGC.

2. The parallel collector (also known as the throughput collector) performs minor collections in parallel, which can significantly reduce garbage collection overhead. It is intended for applications with medium- to large-sized data sets that are run on multiprocessor or multi-threaded hardware. The parallel collector is selected by default on certain hardware and operating system configurations, or can be explicitly enabled with the option -XX:+UseParallelGC.

New: parallel compaction is a feature introduced in J2SE 5.0 update 6 and enhanced in Java SE 6 that allows the parallel collector to perform major collections in parallel. Without parallel compaction, major collections are performed using a single thread, which can significantly limit scalability. Parallel compaction is enabled by adding the option -XX:+UseParallelOldGC to the command line.

3. The concurrent collector performs most of its work concurrently (i.e., while the application is still running) to keep garbage collection pauses short. It is designed for applications with medium- to large-sized data sets for which response time is more important than overall throughput, since the techniques used to minimize pauses can reduce application performance. The concurrent collector is enabled with the option -XX:+UseConcMarkSweepGC.

And there is one new garbage collector in Java 7 : G1

Quote
The Garbage-First (G1) garbage collector is fully supported in Oracle JDK 7 update 4 and later releases. The G1 collector is a server-style garbage collector, targeted for multi-processor machines with large memories. It meets garbage collection (GC) pause time goals with high probability, while achieving high throughput. Whole-heap operations, such as global marking, are performed concurrently with the application threads. This prevents interruptions proportional to heap or live-data size.
19  Discussions / General Discussions / Re: Garbage collector tuning on: 2012-07-31 14:51:25
I find it hard to believe that you could write an object pool that is slower than doing a new.

I didn't even tried Sad I just wrote it and got those results...

Also, the GC will eventually have to collect when you're doing new, and it is the unpredictable nature of "eventually" and the duration of said collection that pooling solves.

Also, the GC is collecting the objects (as you see when I post the output in the console). One thing that I have to agree is the unpredictable nature when you don't have object pooling. With object pooling the pause are usually between 60 and 80 ms for my example. Without object pooling, the pause can be as low as 2ms or as high as 24ms (12 times bigger than lowest). But still the pauses are much shorter.
20  Discussions / General Discussions / Re: Garbage collector tuning on: 2012-07-31 13:45:25
"text"+n means 4 allocations right there (StringBuilder & char[], String & char[])

It's nice to realize that that code is so slow Smiley When you remove it the speed of the benchmark is increased by 50 times Smiley Also, the GC doesn't have to collect anything anymore. But object pooling is still slower.
21  Discussions / General Discussions / Re: Garbage collector tuning on: 2012-07-31 13:39:24
Sad How should I write a good benchmark?
22  Discussions / General Discussions / Re: Garbage collector tuning on: 2012-07-31 13:30:33
And yet we have more surprises! Smiley

I run my previous test with the vm argument : -verbose:gc

Result with object pooling :

1  
2  
3  
4  
5  
6  
7  
8  
9  
10  
[GC 49216K->10758K(188352K), 0.0076902 secs]
[GC 59974K->12750K(237568K), 0.0070728 secs]
[GC 111182K->14302K(237568K), 0.0070655 secs]
[GC 112734K->15478K(336000K), 0.0067169 secs]
[GC 212342K->16430K(336000K), 0.0067652 secs]
[GC 213294K->17246K(535872K), 0.0063414 secs]
[GC 410974K->17214K(535872K), 0.0072485 secs]
[GC 410942K->17246K(929728K), 0.0069668 secs]
Time elapsed in nano : 918742224
Time elapse in milli : 918


Result without object pooling

1  
2  
3  
4  
5  
6  
7  
8  
9  
10  
11  
12  
13  
[GC 49216K->256K(188352K), 0.0007276 secs]
[GC 49472K->192K(188352K), 0.0005208 secs]
[GC 49408K->256K(188352K), 0.0004196 secs]
[GC 49472K->160K(237568K), 0.0003678 secs]
[GC 98592K->208K(237568K), 0.0004676 secs]
[GC 98640K->224K(328192K), 0.0005211 secs]
[GC 197088K->176K(328192K), 0.0008081 secs]
[GC 197040K->176K(320064K), 0.0004403 secs]
[GC 189168K->176K(312896K), 0.0002397 secs]
[GC 181680K->176K(305472K), 0.0003220 secs]
[GC 174576K->176K(299008K), 0.0002982 secs]
Time elapsed in nano : 654859105
Time elapse in milli : 654


Conclusion : The pause with object pooling are usually 10 to 20 times longer and the throughput is a lot worse!
23  Discussions / General Discussions / Re: Garbage collector tuning on: 2012-07-31 13:22:15
Quote
In general, a particular generation sizing chooses a trade-off between these considerations. For example, a very large young generation may maximize throughput, but does so at the expense of footprint, promptness, and pause times. young generation pauses can be minimized by using a small young generation at the expense of throughput. To a first approximation, the sizing of one generation does not affect the collection frequency and pause times for another generation.

From : http://www.oracle.com/technetwork/java/gc-tuning-5-138395.html

I'm still reading Smiley
24  Discussions / General Discussions / Re: Garbage collector tuning on: 2012-07-31 13:06:54
You confuse throughput with latency.

Right...

Still the performance is worse with object pooling.

I would need a way to calculate the pause of the GC for each. Since there is a big difference in the performance of the 2, you might still be surprise.

EDIT: I found it -> The command line argument -verbose:gc prints information at every collection.
25  Discussions / General Discussions / Re: Garbage collector tuning on: 2012-07-31 13:00:04
I'm afraid you have misconception and are using wrong optimization. Here is a quick example that I did and see right away that object pooling degrade the performance.

It took 620 ms in average without object pulling.
It took 860 ms in average with object pulling.

1  
2  
3  
4  
5  
6  
7  
8  
9  
10  
11  
12  
13  
14  
15  
16  
17  
18  
19  
20  
21  
22  
23  
24  
public class NoPool {
   
   long count = 0;
   
   public void run(){
      for(int i=0; i<100000; i++){
         SomeObject o = new SomeObject(i, "Creation : " + i);
         count += o.getI();
      }
   }
   
   public static void main(String [] args){
      NoPool np = new NoPool();
      long begin = System.nanoTime();
      for(int i=0; i<100; i++){
         np.run();
      }
      long end = System.nanoTime();
      long delta = end-begin;
      System.out.println("Time elapsed in nano : " + delta);
      System.out.println("Time elapse in milli : " + delta/(1000*1000));
   }

}


1  
2  
3  
4  
5  
6  
7  
8  
9  
10  
11  
12  
13  
14  
15  
16  
17  
18  
19  
20  
21  
22  
23  
24  
25  
26  
27  
28  
29  
30  
31  
32  
33  
public class ObjectPool {
   
   private SomeObject[] pool = new SomeObject[100000];
   long count = 0;
   
   public ObjectPool(){
      for(int i=0; i<100000; i++){
         pool[i] = new SomeObject(0, "");
      }
   }
   
   public void run(){
      for(int i=0; i<100000; i++){
         SomeObject o = pool[i];
         o.setI(i);
         o.setS("Creation : " + i);
         count += o.getI();
      }
   }
   
   public static void main(String [] args){
      ObjectPool op = new ObjectPool();
      long begin = System.nanoTime();
      for(int i=0; i<100; i++){
         op.run();
      }
      long end = System.nanoTime();
      long delta = end-begin;
      System.out.println("Time elapsed in nano : " + delta);
      System.out.println("Time elapse in milli : " + delta/(1000*1000));
   }

}


1  
2  
3  
4  
5  
6  
7  
8  
9  
10  
11  
12  
13  
14  
15  
16  
17  
18  
19  
20  
21  
22  
23  
24  
25  
26  
27  
public class SomeObject {
   
   private int i;
   private String s;
   
   public SomeObject(int i, String s){
      this.i = i;
      this.s = s;
   }
   
   public int getI(){
      return i;
   }
   
   public String getS(){
      return s;
   }
   
   public void setI(int i){
      this.i = i;
   }
   
   public void setS(String s){
      this.s = s;
   }

}
26  Discussions / General Discussions / Re: Garbage collector tuning on: 2012-07-31 12:27:14
If you want semi-realtime behavior (a stable framerate), then object pooling can still be a good idea, as the GC won't have to clean up those tens of thousands of objects created every frame.

That is wrong... There are absolutely no cost for the GC to clear tens of thousands of objects created every frame. For all those that didn't bother to read the 3 articles here is the idea:

By default, in JDK 1.4 (ok it's old), the GC is a generational garbage collector. What that means? Simply that the GC makes a differences between yound object and old object. Young object are object that doesn't last a long time. There are a lot of those object in your programs; in fact the average is 98% of young object. For example of young object, consider variable that you create only for the scope of a method. Old object are usually static class field or instance variable in another object.

Now the GC use 2 differents algorithm for young and for old objects. For old objects, it use a mark-sweep-compact GC. For the the young objects, it use a copying collector. The way he acheives that is by splitting the memory the JVM use in two. In the first half, the GC stores the old objects and in the second half it stores the young object. Further more, the second half is again split in two; one part where are the young object and the other part is empty and will be used to copy the live young objects when the first part is full.

For the young objects, the GC use the copying collector. With the copying collector you split the memory in two and when one part is full you copy everything that is still active in the other part. There is indeed a cost to copying everything to the other side. The good point is that only object that are still active need to be copied. In fact, object that are not active anymore will not even be visited as the copying collector only visit active object.

So there are absolutely no cost in clearing the thousands of object created every frame.

In fact, you can think of the copying collector for young object as automatic object pooling. You don't even have to think about it and if you try to do it by hand you will fight against the GC.
27  Discussions / General Discussions / Garbage collector tuning on: 2012-07-31 04:18:48
Currently reading a nice article on Java performance :

http://www.ibm.com/developerworks/java/library/j-jtp01274/index.html

I thought I would share because it talk about a subject I heard a lot around here : Object pooling. I guess it's nice to understand why it is a bad idea to use Object pooling Smiley

Quote
Object pooling
Object pooling is a straightforward concept -- maintain a pool of frequently used objects and grab one from the pool instead of creating a new one whenever needed. The theory is that pooling spreads out the allocation costs over many more uses. When the object creation cost is high, such as with database connections or threads, or the pooled object represents a limited and costly resource, such as with database connections, this makes sense. However, the number of situations where these conditions apply is fairly small.
In addition, object pooling has some serious downsides. Because the object pool is generally shared across all threads, allocation from the object pool can be a synchronization bottleneck. Pooling also forces you to manage deallocation explicitly, which reintroduces the risks of dangling pointers. Also, the pool size must be properly tuned to get the desired performance result. If it is too small, it will not prevent allocation; and if it is too large, resources that could get reclaimed will instead sit idle in the pool. By tying up memory that could be reclaimed, the use of object pools places additional pressure on the garbage collector. Writing an effective pool implementation is not simple.
In his "Performance Myths Exposed" talk at JavaOne 2003, Dr. Cliff Click offered concrete benchmarking data showing that object pooling is a performance loss for all but the most heavyweight objects on modern JVMs. Add in the serialization of allocation and the dangling-pointer risks, and it's clear that pooling should be avoided in all but the most extreme cases.

Here are 2 other links that give the necessary information to understand this article Smiley

http://www.ibm.com/developerworks/java/library/j-jtp10283/
http://www.ibm.com/developerworks/java/library/j-jtp11253/#1.0
28  Discussions / General Discussions / Re: Scala Actor on: 2012-07-31 03:28:34
I'm pondering porting scalaz actors to Java, since the implementation is simple enough to do it.  Not going to bother til I have a use case for doing it in Java and not Scala though..

Sounds like fun Smiley
29  Discussions / General Discussions / Re: Scala Actor on: 2012-07-31 03:22:08
Yeah I found out about scala.actors memory leak while I was struggling to do my first example with actor. I implemented the Box, Producer, Consumer example from Java. Here is how the code look like :

1  
2  
3  
4  
5  
6  
7  
8  
9  
10  
11  
12  
13  
14  
15  
16  
17  
18  
19  
20  
21  
22  
23  
24  
25  
26  
27  
28  
29  
30  
31  
32  
33  
34  
35  
36  
37  
38  
39  
40  
41  
42  
43  
44  
45  
46  
47  
48  
49  
50  
51  
52  
53  
54  
55  
56  
57  
58  
59  
60  
61  
62  
63  
64  
65  
66  
67  
68  
69  
70  
71  
package scalasync

import scala.actors.Actor;

object Bonjour {
 
  case object Get;
  case object OK;
 
  class Box2 extends Actor{
    var isEmpty = true;
    var content : Any = null;
    def act(){
      while(true){
         if(isEmpty){
            receive {
            case i:Any => put(i); sender ! OK;
            }
         }else{
           receive {
             case Get => get(); sender ! OK;
           }
         }
      }
    }
    def put(ref : Any){
      content = ref;
      isEmpty = false;
      println("---Put : " + ref);
    }
    def get(){
      println("Get : " + content);
      content = null;
      isEmpty = true;
    }
  }
 
  class Producer(box : Box2) extends Actor{
    def act(){
      for(i <- 0 until 10){
        println("Putting : " + i);
        box ! i;
        receive{
          case OK => ;//Do nothing
       }
      }
    }
  }
 
  class Consumer(box : Box2) extends Actor{
    def act(){
      for(i <- 0 until 10){
        println("Getting : " + i);
        box ! Get
        receive{
          case OK => ;//Do nothing
       }
      }
    }
  }
 
  def main(args: Array[String]){
    var box2 = new Box2();
    var producer = new Producer(box2);
    var consumer = new Consumer(box2);
    box2.start();
    producer.start();
    consumer.start();
  }

}


But the strange thing is that I currently consider that sort of memory leak as wanted behavior... I mean if you look at the code, the consumer is waiting until the producer put something in the box. If the Consumer send the message first, the box will not understand it and that message will be stored and process later when the box will wait for the Get message. Is there another way to get the same behavior?
30  Discussions / General Discussions / Re: Scala Actor on: 2012-07-31 02:58:06
I use Akka actors quite a bit at work, and I'm working on a new fun project that I'm trying to use Scalaz actors with, though I might give in and switch to Akka actors for that too.  The built-in actors in the scala stdlib aren't all that great.

Scala is definitely my favorite language now, though I do wish the IDE tooling weren't so awful.


Oh really, what is the problem with Scala actor?

One problem I noticed with Eclipse IDE is that when refactoring a mixed project Java/Scala, the refactor name in scala code won't be apply to the Java part Sad

EDIT : Scala stdlib Actor implements the same actor as Erlang right? I thought Erlang was great in that field.
Pages: [1] 2 3 ... 15
 

Add your game by posting it in the WIP section,
or publish it in Showcase.

The first screenshot will be displayed as a thumbnail.

radar3301 (12 views)
2014-09-21 23:33:17

BurntPizza (30 views)
2014-09-21 02:42:18

BurntPizza (22 views)
2014-09-21 01:30:30

moogie (20 views)
2014-09-21 00:26:15

UprightPath (28 views)
2014-09-20 20:14:06

BurntPizza (32 views)
2014-09-19 03:14:18

Dwinin (48 views)
2014-09-12 09:08:26

Norakomi (74 views)
2014-09-10 13:57:51

TehJavaDev (103 views)
2014-09-10 06:39:09

Tekkerue (50 views)
2014-09-09 02:24:56
List of Learning Resources
by Longor1996
2014-08-16 10:40:00

List of Learning Resources
by SilverTiger
2014-08-05 19:33:27

Resources for WIP games
by CogWheelz
2014-08-01 16:20:17

Resources for WIP games
by CogWheelz
2014-08-01 16:19:50

List of Learning Resources
by SilverTiger
2014-07-31 16:29:50

List of Learning Resources
by SilverTiger
2014-07-31 16:26:06

List of Learning Resources
by SilverTiger
2014-07-31 11:54:12

HotSpot Options
by dleskov
2014-07-08 01:59:08
java-gaming.org is not responsible for the content posted by its members, including references to external websites, and other references that may or may not have a relation with our primarily gaming and game production oriented community. inquiries and complaints can be sent via email to the info‑account of the company managing the website of java‑gaming.org
Powered by MySQL Powered by PHP Powered by SMF 1.1.18 | SMF © 2013, Simple Machines | Managed by Enhanced Four Valid XHTML 1.0! Valid CSS!