Java-Gaming.org    
Featured games (78)
games approved by the League of Dukes
Games in Showcase (429)
Games in Android Showcase (89)
games submitted by our members
Games in WIP (468)
games currently in development
News: Read the Java Gaming Resources, or peek at the official Java tutorials
 
    Home     Help   Search   Login   Register   
Pages: [1] 2
  ignore  |  Print  
  how to detect occasional stuttering  (Read 7090 times)
0 Members and 1 Guest are viewing this topic.
Offline emzic

Senior Member





« Posted 2008-01-06 21:34:54 »

hello,

my game suffers from stuttering. but not regular stuttering. just occasional. it happens about once every 5 second, that a frame takes extraordinally long to render which is extremely noticeable and pretty annoying for the player. the problem is, that i have no idea how to detect the problem and how to fix it, since it will not show up in a profile because over all the frames measured it is still a very small portion.

so how can i detect what is causing this occasional long frame?

i dont think its garbage collection, since i almost eliminated garbage collection using object pooling (see other thread)

thanks!

www.embege.com - personal website
webstart blendinspect - OpenGL BlendingModes visualization.
Offline Riven
« League of Dukes »

JGO Overlord


Medals: 613
Projects: 4
Exp: 16 years


Hand over your head.


« Reply #1 - Posted 2008-01-06 22:08:45 »

add this to the commandline:
1  
-verbose:gc

Hi, appreciate more people! Σ ♥ = ¾
Learn how to award medals... and work your way up the social rankings
Offline Niwak

Senior Member


Medals: 1
Projects: 1



« Reply #2 - Posted 2008-01-07 08:10:58 »

I had the same problem. I first thought it was the gc. It occurs that I was wrong ; it was the way I managed the AWT event queue.
I ended up switching to SWT and everything is fine now.

By the way, don't go to fast modifying your code with object pools ; I did the same and then had to revert it for sake of code simplicity....

     Vincent
Games published by our own members! Check 'em out!
Legends of Yore - The Casual Retro Roguelike
Offline darkprophet

Senior Member




Go Go Gadget Arms


« Reply #3 - Posted 2008-01-07 09:14:33 »

You guys do know that the java memory model is like one big object pool right? Actually object pooling your stuff in code is only necessary in specific situations...

Just my 2 pence..

DP Smiley

Friends don't let friends make MMORPGs.

Blog | Volatile-Engine
Offline Abuse

JGO Coder


Medals: 10


falling into the abyss of reality


« Reply #4 - Posted 2008-01-15 21:07:13 »

You guys do know that the java memory model is like one big object pool right? Actually object pooling your stuff in code is only necessary in specific situations...

Just my 2 pence..

DP Smiley

I would have thought a multi-tiered fountain would be a better metaphor for describing generational garbage collector.

Make Elite IV:Dangerous happen! Pledge your backing at KICKSTARTER here! https://dl.dropbox.com/u/54785909/EliteIVsmaller.png
Offline cylab

JGO Knight


Medals: 34



« Reply #5 - Posted 2008-01-16 10:08:15 »

You guys do know that the java memory model is like one big object pool right? Actually object pooling your stuff in code is only necessary in specific situations...

Preventing the garbage collector from running might be one of this specific situations Wink

Mathias - I Know What [you] Did Last Summer!
Offline Riven
« League of Dukes »

JGO Overlord


Medals: 613
Projects: 4
Exp: 16 years


Hand over your head.


« Reply #6 - Posted 2008-01-16 13:55:05 »

Don't forget the allocation-time for new objects. These take an order of magnitude longer than fetching some object from a pool.

I know allocation-time in Java is a LOT faster than in C (with malloc), but it's far from 'a pointer shift', which is what Sun is trying us to believe.

Hi, appreciate more people! Σ ♥ = ¾
Learn how to award medals... and work your way up the social rankings
Offline princec

JGO Kernel


Medals: 285
Projects: 3
Exp: 16 years


Eh? Who? What? ... Me?


« Reply #7 - Posted 2008-01-16 15:10:22 »

Construction time can be as little as a pointer-shift. It depends if your objects are expensive to construct or not.

In general:

Only pool objects which are expensive to construct.

and if you find yourself plagued by millions of tiny objects, consider just creating one reusable one and accessing it statically if you can.

Cas Smiley

Offline Riven
« League of Dukes »

JGO Overlord


Medals: 613
Projects: 4
Exp: 16 years


Hand over your head.


« Reply #8 - Posted 2008-01-16 17:12:33 »

Cas, you used that argument for the third time (in a few years) now. So I'll reply like usual:

How expensive is this object-allocation:
1  
2  
3  
4  
class Vec3
{
   public float x,y,z;
}


Pooling gives me a heck of a performance-increase.

It is NOT just a pointer-shift. You gain even more performance when pooling heavy objects, which doesn't mean tiny objects are nearly free. But well, if it's not the bottleneck, you might actually think it's 'fast enough'.

Hi, appreciate more people! Σ ♥ = ¾
Learn how to award medals... and work your way up the social rankings
Offline fletchergames

Senior Member





« Reply #9 - Posted 2008-01-16 17:28:17 »

It's probably an issue with how you're drawing the screen or with timer granularity, not an issue with garbage collection.

You might want to post the code for your main loop if it's short enough for people to read.
Games published by our own members! Check 'em out!
Legends of Yore - The Casual Retro Roguelike
Offline princec

JGO Kernel


Medals: 285
Projects: 3
Exp: 16 years


Eh? Who? What? ... Me?


« Reply #10 - Posted 2008-01-16 18:31:27 »

Constructing that Vec3f and initialising x, y, z in the constructor roughly the same expense as pooling a Vec3f and initializing x, y, z. The real problem of course is destruction which adds a tiny but perceptible extra bit of time. You might be able to tune it out of the VM using GC parameters.

When escape analysis and stack allocation makes it into the VM this year (I believe), all that horribly complicated pooling code dealing with tiny objects is going to look rather messy and complex and actually will be slower, as well. But that's then and this is now; if profiling gives a performance increase, that can't really be argued with I suppose.

Pooling might be overkill for a lot of situations mind - I tend to just declare private static final Vec3f TEMP = new Vec3fs() where I need to keep on constructing and throwing things away, rather than actually using a pool.

Cas Smiley

Offline Riven
« League of Dukes »

JGO Overlord


Medals: 613
Projects: 4
Exp: 16 years


Hand over your head.


« Reply #11 - Posted 2008-01-16 19:03:01 »

Sorry, it's simply not true. The overhead is in the allocation, not in the destructors.

I tested this by incresing the heap, adding -verbose:gc, to monitor the GC, and it was *NOT* run during the benchmark. Still the performance was poor, compared to pooling the Vec3's.

Hi, appreciate more people! Σ ♥ = ¾
Learn how to award medals... and work your way up the social rankings
Offline Linuxhippy

Senior Member


Medals: 1


Java games rock!


« Reply #12 - Posted 2008-01-16 20:33:38 »

Sorry, it's simply not true. The overhead is in the allocation, not in the destructors.
I tested this by incresing the heap, adding -verbose:gc, to monitor the GC, and it was *NOT* run during the benchmark. Still the performance was poor, compared to pooling the Vec3's.

Well there are several factors to consider here:
1.) how large was your data-set? If you only generate 2000 objects in the pool you end up having your whole data-set in the L2 cache, whereas allocation in the heap has to move bytes arround. However this is not likely to be a real-world result.
2.) Do you set your floats to "0" before you hand out the object of the pool - Java's allocation code does this

I created a really simple and stupid micro-benchmark and although I did not expect it - java allocation won without any tuning:
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  
import java.util.*;

public class AllocTester
{
    public static void main(String[] args)
    {
       
        /*warmup*/
        Pooler p = new Pooler();
   
        for(int i=0; i < 1000000; i++)
        {
            new Vec3f();
        }

        for(int i=0; i < 1000000; i++)
        {
           Vec3f v = p.getObject();
            p.releaseObject(v);
        }

    /*measure*/
        long start = System.currentTimeMillis();
        for(int i=0; i < 100000000; i++)
        {
            new Vec3f();
        }
        long end = System.currentTimeMillis();
        System.out.println("Allocation took: "+(end-start));

        start = System.currentTimeMillis();
        for(int i=0; i < 100000000; i++)
        {
           Vec3f v = p.getObject();
            p.releaseObject(v);
        }
        end = System.currentTimeMillis();
        System.out.println("Pool took: "+(end-start));
    }
}

class Vec3f
{
   public float x,y,z;
}

class Pooler
{
    ArrayList pool = new ArrayList();
   
    public Vec3f getObject()
    {
        if(pool.size() > 0)
        {
            return (Vec3f) pool.remove(pool.size() - 1);
        }else  
        {
           return new Vec3f();
        }
    }

    public void releaseObject(Vec3f v)
    {
        pool.add(v);
    }
}


My results were:
Allocation took: 2113
Pool took: 4216


lg Clemens
Offline Riven
« League of Dukes »

JGO Overlord


Medals: 613
Projects: 4
Exp: 16 years


Hand over your head.


« Reply #13 - Posted 2008-01-16 21:29:25 »

The VM is way too smart for such micro-benchmarks Smiley It'll realize nothing is happening, and remove the creation of the object.


When I have time, I'll post a 'real' case, turned into a benchmark.

Hi, appreciate more people! Σ ♥ = ¾
Learn how to award medals... and work your way up the social rankings
Offline Riven
« League of Dukes »

JGO Overlord


Medals: 613
Projects: 4
Exp: 16 years


Hand over your head.


« Reply #14 - Posted 2008-01-16 22:21:21 »

Benchmark classes

Vec.java
VecPool.java
Bench.java


Java Server VM 1.6.0_03
1  
2  
Typical tNew:  20399729ns (20.4ms)
Typical tPool:  3582788ns (3.5ms)



Java Client VM 1.6.0_03
1  
2  
Typical tNew:  21358511ns (21.4ms)
Typical tPool:  3895816ns (3.9ms)

Hi, appreciate more people! Σ ♥ = ¾
Learn how to award medals... and work your way up the social rankings
Offline Linuxhippy

Senior Member


Medals: 1


Java games rock!


« Reply #15 - Posted 2008-01-16 22:45:46 »

well i guess the reason is that you are not using ArrayList - furthermore all your methods are static.
Here begins the fight between readability and performance Wink

I modified the benchmark and this way there is no way out for the JIT:
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  
import java.util.*;

public class AllocTester
{
    public static void main(String[] args)
    {
        Vec3f v2 = new Vec3f();
        /*warmup*/
        Pooler p = new Pooler();
   
        for(int i=0; i < 1000000; i++)
        {
            Vec3f v1 = new Vec3f();
            v1.setValues(i);
            v2.add(v1);
        }

        for(int i=0; i < 1000000; i++)
        {
           Vec3f v1 = p.getObject();
            v1.setValues(i);
            v2.add(v1);
            p.releaseObject(v1);
        }

    /*measure*/
        long start = System.currentTimeMillis();
        for(int i=0; i < 100000000; i++)
        {
            Vec3f v1 = new Vec3f();
            v1.setValues(i);
            v2.add(v1);
        }
        long end = System.currentTimeMillis();
        System.out.println("Allocation took: "+(end-start));

        start = System.currentTimeMillis();
        for(int i=0; i < 100000000; i++)
        {
           Vec3f v1 = p.getObject();
            v1.setValues(i);
            v2.add(v1);
            p.releaseObject(v1);
        }
        end = System.currentTimeMillis();
        System.out.println("Pool took: "+(end-start));

         System.out.println(v2.x+v2.y+v2.z);
    }
}

class Vec3f
{
   public float x,y,z;

    public void setValues(float i)
    {
        x = i;
        y = i;
        z = i;
     }
   
    public void add(Vec3f v)
    {
        x += v.x;
        y += v.y;
        z += v.z;
    }
}

class Pooler
{
    ArrayList pool = new ArrayList();
   
    public Vec3f getObject()
    {
        if(pool.size() > 0)
        {
            return (Vec3f) pool.remove(pool.size() - 1);
        }else  
        {
           return new Vec3f();
        }
    }

    public void releaseObject(Vec3f v)
    {
        pool.add(v);
    }
}


So if even ArrayList access is slower, which is heavily inlined and optimized by the JIT (removing and adding the last element are more or less no-ops), I wonder wether this is really worth all the troubles.
Furthermore allocation was not optimized away, as I was able to watch the GC ... which was quite busy.

lg Clemens
Offline Riven
« League of Dukes »

JGO Overlord


Medals: 613
Projects: 4
Exp: 16 years


Hand over your head.


« Reply #16 - Posted 2008-01-16 23:05:22 »

1  
2  
3  
[quote author=Linuxhippy link=topic=18013.msg141667#msg141667 date=1200519946]
well i guess the reason is that you are not using ArrayList - furthermore all your methods are static.
Here begins the fight between readability and performance ;)


Uh... static methods are not faster (!), I used them because I was lazy and wanted to have something up and running quickly.

It turns out ArrayList are indeed slower, but not by much.

1  
2  
Typical tNew:  19647749
Typical tPool:  4967600



Moving all the references around after converting from static to instance-methods, I lost rougly 10%.

1  
2  
Typical tNew:  19236453
Typical tPool:  5485736




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  
/*
 * Created on 16 jan 2008
 */


package eden.pooling;

import java.util.ArrayList;

public class VecPool
{
   private static ArrayList<Vec> cache;

   static
   {
      int space = 1024;

      VecPool.cache = new ArrayList<Vec>();

      // fill cache
     for (int i = 0; i < space; i++)
         VecPool.dump(VecPool.grab());
   }

   public static Vec grab()
   {
      if (VecPool.cache.size() == 0)
         return new Vec(0, 0, 0);
      return VecPool.cache.get(VecPool.cache.size() - 1);
   }

   public static void dump(Vec v)
   {
      if (VecPool.cache.size() != 1024)
         VecPool.cache.add(v);
   }
}

Hi, appreciate more people! Σ ♥ = ¾
Learn how to award medals... and work your way up the social rankings
Offline princec

JGO Kernel


Medals: 285
Projects: 3
Exp: 16 years


Eh? Who? What? ... Me?


« Reply #17 - Posted 2008-01-16 23:13:29 »

Riven, your VecPool does not initialize the x,y,z members to zero.

Cas Smiley

Offline Riven
« League of Dukes »

JGO Overlord


Medals: 613
Projects: 4
Exp: 16 years


Hand over your head.


« Reply #18 - Posted 2008-01-16 23:15:34 »

So... what? Smiley What's the use?

I know Java-objects are all zero-filled, and that's part of the overhead we want to get rid of.



This is about optimising, not copying VM-behaviour.





Anyway, with zero-fill:
1  
2  
3  
4  
5  
6  
   public static Vec grab()
   {
      if (VecPool.size == 0)
         return new Vec(0, 0, 0);
      return VecPool.cache[--VecPool.size].set(0,0,0);
   }


1  
2  
Typical tNew:  19604587
Typical tPool:  3887017

Hi, appreciate more people! Σ ♥ = ¾
Learn how to award medals... and work your way up the social rankings
Offline Linuxhippy

Senior Member


Medals: 1


Java games rock!


« Reply #19 - Posted 2008-01-16 23:42:10 »

static methods are faster, because you save some fetching and at least one branch (the branch which takes care about de-optimization).

Your benchmark does many different things, it could be quiet possible that some cache-issues come up.
I just can state that in mine allocation is faster, while in yours the pool performs better Wink

lg Clemens
Offline Riven
« League of Dukes »

JGO Overlord


Medals: 613
Projects: 4
Exp: 16 years


Hand over your head.


« Reply #20 - Posted 2008-01-16 23:48:17 »

I already mentioned the performance loss of 10% when converting to instance-methods.



Well, it's yet another 'issue' of the VM... it's darn unpredictable when it comes down to optimisations.


I simply had to use pooling, to get a realworld (3d) application to run 'fast enough', the overall framerate increase was like 350% when doing lots of geometry transformations on the CPU. Since then, I stick to pools, as everytime they beat the crap out of any other solution.

Hi, appreciate more people! Σ ♥ = ¾
Learn how to award medals... and work your way up the social rankings
Offline princec

JGO Kernel


Medals: 285
Projects: 3
Exp: 16 years


Eh? Who? What? ... Me?


« Reply #21 - Posted 2008-01-17 09:13:43 »

Chances are though you'd want your Vec3f's initialized to some value when you get them; the vm doesn't necessarily have to zero the x,y,z members if they are initialized in a constructor. So if both your benchmarks did that it would be a more realistic comparison I think.

Cas Smiley

Offline arm

Senior Newbie




Java games rock!


« Reply #22 - Posted 2008-01-17 09:42:36 »

Riven,

Micro-benchmarking is like quantum phisycs:
observation is disturbed by measurement itself.

Hotspot compiler is known for having strange behaviour in
some cases.

I have slightly modified your code to make it more readable:

1  
2  
3  
4  
5  
6  
7  
8  
9  
10  
11  
12  
13  
14  
15  
16  
17  
18  
19  
      // New
     {
         long ts, te;
         ts = System.nanoTime();
         for (int k = 0; k < loops; k++)
            calcNew(a, b, c);
         te = System.nanoTime();
         tNew[i] = te - ts;
      }

      // Pool
     {
         long ts, te;
         ts = System.nanoTime();
         for (int k = 0; k < loops; k++)
            calcPool(a, b, c);
         te = System.nanoTime();
         tPool[i] = te - ts;
      }



Results:

   Java HotSpot(TM) Server VM (build 11.0-b09, mixed mode)

   Typical tNew:  64800135
   Typical tPool: 3851607

So I changed execution order inside Bench.main loop as follows :

1  
2  
3  
4  
5  
6  
7  
8  
9  
10  
11  
12  
13  
14  
15  
16  
17  
18  
19  
      // Pool
     {
         long ts, te;
         ts = System.nanoTime();
         for (int k = 0; k < loops; k++)
            calcPool(a, b, c);
         te = System.nanoTime();
         tPool[i] = te - ts;
      }

      // New
     {
         long ts, te;
         ts = System.nanoTime();
         for (int k = 0; k < loops; k++)
            calcNew(a, b, c);
         te = System.nanoTime();
         tNew[i] = te - ts;
      }


and I've got

   Java HotSpot(TM) Server VM (build 11.0-b09, mixed mode)

   Typical tNew:  4922693
   Typical tPool: 64387792

It seems that hotspot compiler doesn't optimize first part of for loop.

Angelo
Offline Riven
« League of Dukes »

JGO Overlord


Medals: 613
Projects: 4
Exp: 16 years


Hand over your head.


« Reply #23 - Posted 2008-01-17 10:16:01 »

The problem is, that this doesn't only happen in microbenchmarks, but also in realworld apps.

It's trial-and-error all over again! Undecided

Maybe I'll write a natively-compiled (DLL) version, without SIMD, to see what the referencepoint is... one nice thing of native code is that it's not having such weird performance-characteristics, when seemingly irrelevant changes are made to the sourcecode.



... I'll write a better benchmark when I get home.

Lips Sealed

Hi, appreciate more people! Σ ♥ = ¾
Learn how to award medals... and work your way up the social rankings
Offline cylab

JGO Knight


Medals: 34



« Reply #24 - Posted 2008-01-17 10:18:00 »

Chances are though you'd want your Vec3f's initialized to some value when you get them; the vm doesn't necessarily have to zero the x,y,z members if they are initialized in a constructor. So if both your benchmarks did that it would be a more realistic comparison I think.

Actually no. Skipping initialization is one of the things you <i>explicitly</i> want if you use object pooling. Other than that, writing initializing pools is non-generic and a lot of wasted work.

Mathias - I Know What [you] Did Last Summer!
Offline Linuxhippy

Senior Member


Medals: 1


Java games rock!


« Reply #25 - Posted 2008-01-17 12:05:01 »

Hi again,

Well the first loop runs interpreted first and the is replaced by OSR compiled code. Thats why my code does warmup for both code-paths, so that I don't see compilation side effects.

However I thought a bit more about the fact why in real-world apps allocation may not be that cheap as its in the benchmark here:
- The benchmark is a best-case for a GC. Almost all objects die in the young generation, which is exactly what the GC was tuned for. Also keep in mind that there are no complex object graphs.
- In real-world applications , if young generation is sized too small, a lot of stuff is propagated to the old generation. An gc in the old-gen is expensive anyway...

Quote
It's trial-and-error all over again!
Well, I just can say hotspot is great. However I have to admit that some knowledge of how hotspot does its things can help to understand whats going on...

lg Clemens
Offline Riven
« League of Dukes »

JGO Overlord


Medals: 613
Projects: 4
Exp: 16 years


Hand over your head.


« Reply #26 - Posted 2008-01-17 12:19:24 »

Hm... I don't think you understand how my timing-loop and determining the typical duration works... (or I misunderstood you.)

My two methods also get 'warmed' by the VM, and those slow executions are put in the tNew/tLoop, but after sorting, they end up at the end of the long[], which makes them irrelevant, as only the middle of the long[] is read for the 'typical' execution-time.

Further, the GC isn't really the bottleneck (you will see a few GC-durations of 0.1ms or so, on a total duration of ~20ms)
=> so the allocation is what's slowing everything down.


But heck, I'll write a better benchmark when I get home tonight...

Hi, appreciate more people! Σ ♥ = ¾
Learn how to award medals... and work your way up the social rankings
Offline Mr_Light

Senior Member




shiny.


« Reply #27 - Posted 2008-01-17 16:38:33 »

Actually no. Skipping initialization is one of the things you <i>explicitly</i> want if you use object pooling. Other than that, writing initializing pools is non-generic and a lot of wasted work.

so you going to do work based on unknown stuff? construction is what you want to skip if your pooling; if you want to skip the assignment of 0/zero filling step use a constructor or pool like so:

class Vec3f {
   public float x,y,z;

   Vec3f(float x,float y,float z) {
     this.x = x;
     this.y = y;
     this.z = z;
   }
}

pool.newVec3f(float x,float y,float z);
(With the pool you know for sure the zero filling is not done and the Vec3f is only assign a value, but I think the jvm should note this too and filter it out)

But that step need to be in there and should be forced else it leads to impossible obscured bugs
unknown value + 5 = unknown value => unreliable / useless


I though immutable stuff was promoted for tiny objects. btw Also I though optimisations where the act of doing things faster without changing behaviour.

It's harder to read code than to write it. - it's even harder to write readable code.

The gospel of brother Riven: "The guarantee that all bugs are in *your* code is worth gold." Amen brother a-m-e-n.
Offline cylab

JGO Knight


Medals: 34



« Reply #28 - Posted 2008-01-17 17:57:42 »

so you going to do work based on unknown stuff?
No - I know that objects taken from a pool are uninitialized. Nothing problematic with that. If I need them to be initialized, I can do it right after getting them from the pool.

pool.newVec3f(float x,float y,float z);
Too much work - I wouldn't want to create typed pools except by using generics...

But that step need to be in there and should be forced else it leads to impossible obscured bugs
Usually I know what I am doing...  Tongue

unknown value + 5 = unknown value => unreliable / useless
This won't happen, since I either initialize pooled objects myself or only use them left hand in assignments...

Also I though optimisations where the act of doing things faster without changing behaviour.
Yeah... the application should do the same as before after an optimization - but changing behaviours of the implementation is inevitable.

Mathias - I Know What [you] Did Last Summer!
Offline Mr_Light

Senior Member




shiny.


« Reply #29 - Posted 2008-01-17 20:45:22 »

Usually I know what I am doing...  Tongue
This won't happen, since I either initialize pooled objects myself or only use them left hand in assignments...
I can only speak for myself but I avoid these sharp edges if I'm coding alone; in team environments you need so much red/white tape around these types of things that it will start coming out of your ass.


Yeah... the application should do the same as before after an optimization - but changing behaviours of the implementation is inevitable.
This boiles down to what behavor is expected/taken for granted and if ppl are going to depend on it; in short it's dangerous. Esp in the light that one person designs, one codes and an other one optimised. Differendly put 'do the same' can mean different things to different ppl, some behaviour you don't find significant might be something somone else is depending upon.

Perhaps you'll never encounter a case / the above will never apply for you, but this forum is still read by ppl in a different situation. That being said, it would be tedious to supply a disclaimer with every single bit of advice being given here.

(this also puts "use what you can, when you can" in a very subtle perspective Wink )

It's harder to read code than to write it. - it's even harder to write readable code.

The gospel of brother Riven: "The guarantee that all bugs are in *your* code is worth gold." Amen brother a-m-e-n.
Pages: [1] 2
  ignore  |  Print  
 
 
You cannot reply to this message, because it is very, very old.

 

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

The first screenshot will be displayed as a thumbnail.

theagentd (6 views)
2014-04-24 23:00:44

xsi3rr4x (83 views)
2014-04-15 18:08:23

BurntPizza (75 views)
2014-04-15 03:46:01

UprightPath (86 views)
2014-04-14 17:39:50

UprightPath (69 views)
2014-04-14 17:35:47

Porlus (86 views)
2014-04-14 15:48:38

tom_mai78101 (109 views)
2014-04-10 04:04:31

BurntPizza (169 views)
2014-04-08 23:06:04

tom_mai78101 (265 views)
2014-04-05 13:34:39

trollwarrior1 (217 views)
2014-04-04 12:06:45
Escape Analysis
by Roquen
2014-04-25 10:22:13

List of Learning Resources
by SHC
2014-04-18 03:17:39

List of Learning Resources
by Longarmx
2014-04-08 03:14:44

Good Examples
by matheus23
2014-04-05 13:51:37

Good Examples
by Grunnt
2014-04-03 15:48:46

Good Examples
by Grunnt
2014-04-03 15:48:37

Good Examples
by matheus23
2014-04-01 18:40:51

Good Examples
by matheus23
2014-04-01 18:40:34
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!