Show Posts
|
|
Pages: [1] 2 3
|
|
2
|
Game Development / Artificial Intelligence / Re: pathfinding for multiple objects?
|
on: 2006-05-05 16:53:41
|
|
i have a similar problem. my virtual frog/spaceship/whatever wants to get through a street full of cars/an asteroid field/whatever. i can calculate the position of any object at any moment in time, because the movement is pretty simple. my idea was to use the a*-algorithm, but alter the world after every step. i didn't try it yet, but it should work. this is pretty similar to brute-forcing a chess game, btw. the "world", and "other movable objects" are changing their states also.
as for the "but i have 200 units and therefore need a billion years for this calculation"-problem, i'd simply define a leader and let the others follow him.
|
|
|
|
|
3
|
Game Development / Shared Code / Re: Fastest get2fold algorithm
|
on: 2006-03-31 11:39:43
|
Who will turn this code into a massive (()?a: (?b:c))?d:e block?  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
| public static final int get2FoldUnrolled(int n) { return n < 0 ? 0xFFFFFFFF : n > 0x00010000 ? n > 0x01000000 ? n > 0x10000000 ? n > 0x40000000 ? 0xFFFFFFFF : (n > 0x20000000) ? 0x40000000 : 0x20000000 : n > 0x04000000 ? (n > 0x08000000) ? 0x10000000 : 0x08000000 : (n > 0x02000000) ? 0x04000000 : 0x02000000 : n > 0x00100000 ? n > 0x00400000 ? (n > 0x00800000) ? 0x01000000 : 0x00800000 : (n > 0x00200000) ? 0x00400000 : 0x00200000 : n > 0x00040000 ? (n > 0x00080000) ? 0x00100000 : 0x00080000 : (n > 0x00020000) ? 0x00040000 : 0x00020000 : n > 0x00000100 ? n > 0x00001000 ? n > 0x00004000 ? (n > 0x00008000) ? 0x00010000 : 0x00008000 : (n > 0x00002000) ? 0x00004000 : 0x00002000 : n > 0x00000400 ? (n > 0x00000800) ? 0x00001000 : 0x00000800 : (n > 0x00000200) ? 0x00000400 : 0x00000200 : n > 0x00000010 ? n > 0x00000040 ? (n > 0x00000080) ? 0x00000100 : 0x00000080 : (n > 0x00000020) ? 0x00000040 : 0x00000020 : n > 0x00000004 ? (n > 0x00000008) ? 0x00000010 : 0x00000008 : (n > 0x00000002) ? 0x00000004 : n;
} |
scnr
|
|
|
|
|
4
|
Game Development / Performance Tuning / Re: A poor man's struct (err, MappedObject)
|
on: 2006-03-29 12:36:00
|
Does the JVM do bounds-check removal on Buffer types? I know i does on arrays..
i'd say: no. a bytebuffer's get and put methods are always a bit slower than direct array accesses. (at least the last 10 times i looked at the results) if i simply call a bytebuffer's private put/get-methods (jdk hack) which don't do bounds checks manually, i'm almost at array speed (50% slower). if i inline the calls and access the unsafe object directly, using (base+(offset<<2)) as the address to get an int, i'm really almost at array speed (up to 10% difference, sometimes faster, sometimes slower, which means it's pretty equal). using any precalucated value as an address speeds things up, and i'm at 200% array speed. i assume this means: a) java uses the same calculation to access random values in arrays b) java doesn't do array bounds checks if the vm can be sure that no evil index will be used.
|
|
|
|
|
5
|
Game Development / Performance Tuning / Re: A poor man's struct (err, MappedObject)
|
on: 2006-03-22 21:23:08
|
the reason for unsafedemo being slower is that i use a "naked" unsafe instance. benchy extracts it from a bytebuffer. if i use a bytebuffer's Unsafe, unsafe.get/put & arrays are almost equally fast. Unsafe is a bit faster, but you could have trouble avoiding the "base + (index<<bytes_of_type)"-calculation when accessing the buffer. if you can avoid it, Unsafe is the way to go 
|
|
|
|
|
6
|
Game Development / Performance Tuning / Re: A poor man's struct (err, MappedObject)
|
on: 2006-03-22 14:05:47
|
|
that backed-by-float[]-floatbuffer is STILL faster than using Unsafe.
i removed the double increment. saved about 2ms (of 29). i'm at 27 now. and i'm just reading the same element 10 million times now, so there shouldn't be cache flushing, right?. the 10mb size shouldn't matter at all. every test iterates over every element.
on my machine, your direct float buffer is slower (a few ms) than the backed one...
|
|
|
|
|
7
|
Game Development / Performance Tuning / Re: A poor man's struct (err, MappedObject)
|
on: 2006-03-22 13:45:08
|
here's my result: Array time: 4.799727 ms unsafe time 29.210326 ms Floatbuffer time: 23.882264 ms Directbytebuffer2float time: 46.760005 ms
it seems that arrays are a LOT faster than any buffer available. running on 1.5.0_06 -server wtf? looking at this, i have to ask: what are buffers good for? why is the unsafe access that slow? shouldn't it be faster? 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 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150
| import sun.misc.Unsafe;
import java.lang.reflect.Field; import java.nio.FloatBuffer; import java.nio.ByteBuffer;
public class UnsafeDemo { private static final int SIZE = 10000000; private static final int LOOPS = 50;
public static void main(String[] args) throws Exception { Unsafe unsafe = getUnsafe(); System.out.println("Unsafe = " + unsafe); System.out.println(" addressSize() = " + unsafe.addressSize()); System.out.println(" pageSize() = " + unsafe.pageSize()); System.out.println(" pageSize() = " + unsafe.pageSize()); int cap = SIZE; int ps = unsafe.pageSize(); long base = unsafe.allocateMemory(cap + ps); long pointer; unsafe.setMemory(base, cap + ps, (byte) 0); if (base % ps != 0) { pointer = base + ps - (base & (ps - 1)); } else { pointer = base; } for (int i = 0; i < 5; i++) { benchArray(); benchUnsafe(unsafe, pointer); benchBuffer(); benchDirectBuffer(); System.out.println("-------"); } unsafe.freeMemory(pointer); }
private static void benchDirectBuffer() { ByteBuffer fb = ByteBuffer.allocateDirect(SIZE); int INTS = SIZE / 4; float[] dummy = new float[INTS]; for (int i = 0; i < INTS; i++) { fb.putFloat(i,(float) (Math.random() * 1000)); } long time = System.nanoTime(); float x = 0; for (int i = 0; i < INTS; i++) { x += fb.getFloat(i); } System.out.println("Directbytebuffer2float time: " + (System.nanoTime() - time) / 1000000.0d + " ms"); System.out.println("x array= " + x); }
private static void benchUnsafe(final Unsafe unsafe, long pointer) { int INTS = SIZE / 4; long absAdr = pointer-4; for (int i = 0; i < INTS; i++) { unsafe.putFloat(absAdr+=4, (float) (Math.random() * 1000)); } long time = System.nanoTime(); int x = 0; absAdr = pointer-4; for (int i = 0; i < INTS; i++) { x += unsafe.getFloat(absAdr+=4); } System.out.println("unsafe time " + (System.nanoTime() - time) / 1000000.0d + " ms"); System.out.println("x unsafe= " + x); }
private static void benchArray() { int INTS = SIZE / 4; float[] dummy = new float[INTS]; for (int i = 0; i < INTS; i++) { dummy[i] = (float) (Math.random() * 1000); } long time = System.nanoTime(); float x = 0; for (int i = 0; i < INTS; i++) { x += dummy[i]; } System.out.println("Array time: " + (System.nanoTime() - time) / 1000000.0d + " ms"); System.out.println("x array= " + x); }
private static void benchBuffer() { FloatBuffer fb = FloatBuffer.allocate(SIZE/4); int INTS = SIZE / 4; float[] dummy = new float[INTS]; for (int i = 0; i < INTS; i++) { fb.put(i,(float) (Math.random() * 1000)); } long time = System.nanoTime(); float x = 0; for (int i = 0; i < INTS; i++) { x += fb.get(i); } System.out.println("Floatbuffer time: " + (System.nanoTime() - time) / 1000000.0d + " ms"); System.out.println("x array= " + x); }
public static Unsafe getUnsafe() throws Exception { Unsafe unsafe = null;
try { Class uc = Unsafe.class; Field[] fields = uc.getDeclaredFields(); for (int i = 0; i < fields.length; i++) { if (fields[i].getName().equals("theUnsafe")) { fields[i].setAccessible(true); unsafe = (Unsafe) fields[i].get(uc); break; } } } catch (Exception ignore) { }
return unsafe; } } |
for completition, the client result: Array time: 24.679127 ms unsafe time 40.004324 ms Floatbuffer time: 23.507286 ms Directbytebuffer2float time: 59.796623 ms
what does that tell us? array access is about 10 times faster when using the server vm. rofl? jrockit: Array time: 5.091692999999999 ms unsafe time 29.136017 ms Floatbuffer time: 5.340409 ms Directbytebuffer2float time: 11.336103 ms
*giving up*
|
|
|
|
|
8
|
Game Development / Performance Tuning / Re: A poor man's struct (err, MappedObject)
|
on: 2006-03-21 22:28:06
|
|
how to put/get floats/ints/etc using the unsafe-class?
i've looked at sun's directbytebuffer. it seems i can allocate, access and free memory using Unsafe pretty simply. the only reason not using a bytebuffer when going for performance seems to be that a range check is performed at every access. however, i found a lot of "anInt << 0"-bitshifts. my brain, and my ide also say that these are completely pointless. what are they good for?
[some time later]
i wrote a small benchmark, but it lies. the java float array is, depening on some fine tuning, up to 30 times faster than accessing the data via Unsafe. i guess the vm is understanding my benchmark and starts to cheat.
|
|
|
|
|
11
|
Game Development / Performance Tuning / garbage collector locks up
|
on: 2006-02-14 17:59:57
|
|
to make it short: tomcat, arguments: -Xmx513m -Xms512m -server -XX:+UseParNewGC -XX:+CMSParallelRemarkEnabled -XX:+UseConcMarkSweepGC -XX:+PrintGCDetails -verbosegc -XX:+CMSPermGenSweepingEnabled -XX:+CMSClassUnloadingEnabled
runs fine for a while, then prints:
[GC [1 CMS-initial-mark: 261312K(516096K)] 261420K(524224K), 0.0008936 secs] [CMS-concurrent-mark: 0.673/0.673 secs] [CMS-concurrent-preclean: 0.000/0.000 secs] [GC[YG occupancy: 107 K (8128 K)][Rescan (parallel) , 0.0034411 secs][weak refs processing, 0.0000064 secs][class unloading, 0.0214873 secs][scrub symbol & string tables, 0.0053496 secs] [1 CMS-remark: 261312K(516096K)] 261420K(524224K), 0.0353675 secs] [CMS-concurrent-sweep: 0.186/0.186 secs] [CMS-concurrent-reset: 0.009/0.009 secs]
over and over again, consuming 50% of my hyperthreading p4.
sometimes i get: [Full GC [CMS (concurrent mode failure): 261308K->261317K(516096K), 1.3826536 secs] 261493K->261317K(524224K), [CMS Perm : 65535K->65534K(65536K)], 1.3828157 secs] [GC [1 CMS-initial-mark: 261317K(516096K)] 261317K(524224K), 0.0008784 secs] [Full GC [CMS[CMS-concurrent-mark: 0.621/0.623 secs] (concurrent mode failure): 261317K->261315K(516096K), 2.0470819 secs] 261502K->261315K(524224K), [CMS Perm : 65535K->65535K(65536K)], 2.0472546 secs] [Full GC [CMS (concurrent mode failure): 261315K->261315K(516096K), 1.1678882 secs] 261368K->261315K(524224K), [CMS Perm : 65535K->65535K(65536K)], 1.1680489 secs] [GC [1 CMS-initial-mark: 261315K(516096K)] 261315K(524224K), 0.0011766 secs] [Full GC [CMS[CMS-concurrent-mark: 0.686/0.686 secs] (concurrent mode failure): 261315K->261314K(516096K), 1.9247622 secs] 261368K->261314K(524224K), [CMS Perm : 65535K->65535K(65536K)], 1.9249726 secs] [Full GC [CMS (concurrent mode failure): 261314K->261314K(516096K), 1.2463526 secs] 261314K->261314K(524224K), [CMS Perm : 65535K->65535K(65536K)], 1.2464900 secs] [GC [1 CMS-initial-mark: 261314K(516096K)] 261314K(524224K), 0.0008861 secs]
again and again. whats wrong?
|
|
|
|
|
18
|
Game Development / Performance Tuning / Re: New C1 in Mustang b59
|
on: 2006-02-04 21:59:43
|
|
both ibm's jdk5 beta and jrockit5 are faster than the newest mustang server vm (not really much, but still ->) 1. my connect4-ai: 2.5 million checks (sun) vs 2.8 million (bea) vs 3 million (ibm) on my machine (1.5.0_06 client crowls at 1.4 million) 2. my minesweeper-solver: ibm 60 seconds, sun 62 seconds, bea 50 seconds (for a specific field)
what's causing the difference?
|
|
|
|
|
20
|
Game Development / Newbie & Debugging Questions / Re: strange hashmap error
|
on: 2006-01-30 21:41:49
|
try replacing found = map.get(sequence); if (found != null) { map.put(sequence,found + 1); } else { map.put(sequence,1); } with if (map.containsKey(sequence)) { map.put(sequence,found + 1); } else { map.put(sequence,1); }
that would just slow it down, unless there is a null-sequence. btw, don't do 1
| res.append(line + " "); |
and complain about " " being in your strings
|
|
|
|
|
23
|
Game Development / Performance Tuning / Re: minesweeper contest
|
on: 2006-01-23 23:35:59
|
|
the field has probably no unambigous solution at the point where my algorithm "hangs" (in fact it started to identify every possible solution which can take a while, depending on the number of open fields). it takes about 1 minute (1.8 ghz opteron) to check if 50 fields (forming an area) are solvable or not. 51 fields should take about 2 minutes, and 100 fields...forget it^^. there are some optimisations, but there's no guarantee they work. they can help, but it depends on the situation. i'm thinking hard to solve this problem. smoke already comes out.
|
|
|
|
|
24
|
Game Development / Performance Tuning / Re: minesweeper contest
|
on: 2006-01-23 12:06:23
|
you could even use java6 if you wanted to. there is no scoring algorithm implemented afaik. the original scoring was like this: time: 20% ( i have no idea how they exactly counted the scores here) found bombs: 70% (all bombs = 70%, half bombs = 35% etc) documentation: 5% implementing the interface: 5% and most likely some poor guy had do to it manually. since i don't know how to weigth the time and skipped the documentation (won anyway  ), i'd say we use these updated rules: the rules: a) open as much fields as possible. if you open more fields than the others, you win. b) open the fields as fast as possible. if you open the same amount of fields as the others and are faster, you win. c) if you hit a bomb, it's the same as if you just stopped solving the field. the reason for c) is that my algorithm stops here. it doesn't take any risk. therefore, rule c) will allow some freaky strategies, which means more fun. i'll start improving by solver as soon as you beat it in speed and/or found bombs
|
|
|
|
|
25
|
Game Development / Performance Tuning / Re: Will be escape analysis based optimizations integrated into Mustang?
|
on: 2006-01-21 17:29:33
|
if you need the best performance, do it like this 1 2 3 4
| for (int i = lengthOfList;--i>=0;) { doStuff(); } |
comparisons against 0 are fast because only 1 value has to be loaded into the register (instead of the loop variable and the list size) AND you already got it there because of the "--". 1 2 3 4 5 6
| try { while (true) { doStuff(i++); } } catch () |
may be faster for very long lists, or on IBM's vm, which is a lot faster regarding exceptions. however, in 97% of all cases, the performance doesn't matter that much (0.5 seconds or 0.52 seconds after a click on a button, who cares)
|
|
|
|
|
29
|
Game Development / Performance Tuning / Re: Volatile vs Buffered
|
on: 2006-01-19 19:12:50
|
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 125 126 127 128 129 130 131 132 133 134 135 136 137
| package src;
import javax.imageio.ImageIO; import javax.swing.JFrame; import javax.swing.JPanel; import javax.swing.border.EmptyBorder; import java.awt.BorderLayout; import java.awt.Color; import java.awt.Dimension; import java.awt.DisplayMode; import java.awt.Graphics2D; import java.awt.Image; import java.awt.Toolkit; import java.awt.Window; import java.io.File; import java.io.IOException; import java.util.ArrayList; import java.util.List;
public class SpinBench extends JFrame {
public static SpinBench instance; private JPanel jpMain;
private String title;
public SpinBench(Image img) { super(); instance = this; this.title = "Spinbench"; setResizable(false); buildGUI(); addListener(); pack(); center();
Window w = new Window(this); getGraphicsConfiguration().getDevice().setFullScreenWindow(w); getGraphicsConfiguration().getDevice().setDisplayMode(new DisplayMode(1600, 1200, 32, 60)); Image buffered = getImg(); Graphics2D graphics; List<Graphics2D> g2d = new ArrayList<Graphics2D>(); for (int i = 1; i < 31; i++) { for (int i2 = 1; i2 < 31; i2++) { Graphics2D g2 = (Graphics2D) buffered.getGraphics(); g2.translate(i * 50, i2 * 50); g2.scale(0.1, 0.1); g2d.add(g2); } } graphics = (Graphics2D) buffered.getGraphics(); graphics.setColor(Color.black); while (true) { long startTime = System.nanoTime(); int frames = 0; while (frames++ < 100) { graphics.fillRect(0, 0, 1600, 1200); for (Graphics2D graphics2D : g2d) { graphics2D.rotate(0.1 * Math.random()); graphics2D.drawImage(img, 0, 0, null); } w.getGraphics().drawImage(buffered, 0, 0, null); } long elapsed = System.nanoTime() - startTime; double nsPerDraw = elapsed / (float) frames; System.out.println(nsPerDraw + " ns per frame = " + 1.0 / (nsPerDraw / 1000000000.0) + " fps"); } }
private Image getImg() { return this.createVolatileImage(1600, 1200); }
protected void buildGUI() { setTitle(title); getContentPane().setLayout(new BorderLayout(6, 6)); jpMain = new JPanel(); getContentPane().add(jpMain, BorderLayout.CENTER); jpMain.setBorder(new EmptyBorder(6, 6, 6, 6)); jpMain.setLayout(new BorderLayout(6, 6));
jpMain.setPreferredSize(new Dimension(640, 480)); }
protected void addListener() { setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); }
private void center() { Toolkit tk = Toolkit.getDefaultToolkit(); setLocation((int) (tk.getScreenSize().getWidth() / 2 - getWidth() / 2), (int) (tk.getScreenSize().getHeight() / 2 - getHeight() / 2)); setVisible(true); }
public static void main(String[] args) throws IOException { Image image = ImageIO.read(new File("resource/hamster.jpg")); new SpinBench(image); } }
|
|
|
|
|
|
|
Add your game by posting it in the WIP section,
or publish it in Showcase.
The first screenshot will be displayed as a thumbnail.
|
|