performance - Can I allocate objects contiguously in java? -


assume have large array of relatively small objects, need iterate frequently.
i optimize iteration improving cache performance, allocate the objects [and not reference] contiguously on memory, i'll fewer cache misses, , overall performance segnificantly better.

in c++, allocate array of objects, , allocate them wanted, in java - when allocating array, allocate reference, , allocation being done 1 object @ time.

i aware if allocate objects "at once" [one after other], jvm most likely allocate objects contiguous can, might not enough if memory fragmented.

my questions:

  1. is there way tell jvm defrag memory before start allocating objects? enough ensure [as possible] objects allocated continiously?
  2. is there different solution issue?

new objects creating in eden space. eden space never fragmented. empty after gc.

the problem have when gc performed, object can arranged randomly in memory or surprisingly in reverse order referenced.

a work around store fields series of arrays. call column-based table instead of row based table.

e.g. instead of writing

class pointcount {     double x, y;     int count; }  pointcount[] pc = new lots of small objects. 

use columns based data types.

class pointcounts {     double[] xs, ys;     int[] counts; } 

or

class pointcounts {     tdoublearraylist xs, ys;     tintarraylist counts; } 

the arrays in 3 different places, data otherwise continuous. can marginally more efficient if perform operations on subset of fields.

public int totalcount() {    int sum = 0;    // counts continuous without between values.    for(int i: counts) sum += i;    return i; } 

a solution use avoid gc overhead having large amounts of data use interface access direct or memory mapped bytebuffer

import java.nio.bytebuffer; import java.nio.byteorder;  public class mycounters {     public static void main(string... args) {         runtime rt = runtime.getruntime();         long used1 = rt.totalmemory() - rt.freememory();         long start = system.nanotime();         int length = 100 * 1000 * 1000;         pointcount pc = new pointcountimpl(length);         (int = 0; < length; i++) {             pc.index(i);             pc.setx(i);             pc.sety(-i);             pc.setcount(1);         }         (int = 0; < length; i++) {             pc.index(i);             if (pc.getx() != i) throw new assertionerror();             if (pc.gety() != -i) throw new assertionerror();             if (pc.getcount() != 1) throw new assertionerror();         }         long time = system.nanotime() - start;         long used2 = rt.totalmemory() - rt.freememory();         system.out.printf("creating array of %,d used %,d bytes of heap , tool %.1f seconds set , get%n",                 length, (used2 - used1), time / 1e9);     } }  interface pointcount {     // set index of element referred to.     public void index(int index);      public double getx();      public void setx(double x);      public double gety();      public void sety(double y);      public int getcount();      public void setcount(int count);      public void incrementcount(); }  class pointcountimpl implements pointcount {     static final int x_offset = 0;     static final int y_offset = x_offset + 8;     static final int count_offset = y_offset + 8;     static final int length = count_offset + 4;      final bytebuffer buffer;     int start = 0;      pointcountimpl(int count) {         this(bytebuffer.allocatedirect(count * length).order(byteorder.nativeorder()));     }      pointcountimpl(bytebuffer buffer) {         this.buffer = buffer;     }      @override     public void index(int index) {         start = index * length;     }      @override     public double getx() {         return buffer.getdouble(start + x_offset);     }      @override     public void setx(double x) {         buffer.putdouble(start + x_offset, x);     }      @override     public double gety() {         return buffer.getdouble(start + y_offset);     }      @override     public void sety(double y) {         buffer.putdouble(start + y_offset, y);     }      @override     public int getcount() {         return buffer.getint(start + count_offset);     }      @override     public void setcount(int count) {         buffer.putint(start + count_offset, count);     }      @override     public void incrementcount() {         setcount(getcount() + 1);     } } 

run -xx:-usetlab option (to accurate memory allocation sizes) prints

creating array of 100,000,000 used 12,512 bytes of heap , took 1.8 seconds set , get

as off heap, has next no gc impact.


Comments

Popular posts from this blog

jasper reports - Fixed header in Excel using JasperReports -

media player - Android: mediaplayer went away with unhandled events -

python - ('The SQL contains 0 parameter markers, but 50 parameters were supplied', 'HY000') or TypeError: 'tuple' object is not callable -