@@ -41,32 +41,27 @@ public class MemoryGraphSafe implements SaveableGraph {
41
41
private static final int EMPTY_LINK = 0 ;
42
42
private static final float DIST_UNIT = 10000f ;
43
43
private Logger logger = LoggerFactory .getLogger (getClass ());
44
+ // number of integers not edges
45
+ private static final int MIN_SEGMENT_SIZE = 1 << 13 ;
44
46
private static final float FACTOR = 1.5f ;
45
47
// keep in mind that we address integers here - not bytes!
46
48
private static final int LEN_DIST = 1 ;
47
49
private static final int LEN_NODEID = 1 ;
48
50
private static final int LEN_FLAGS = 1 ;
49
51
private static final int LEN_LINK = 1 ;
50
52
private static final int LEN_EDGE = LEN_FLAGS + LEN_DIST + LEN_NODEID + LEN_LINK ;
51
- // or should we use int and a factor? private static double MICRO = 1000000;
52
53
private float [] lats ;
53
54
private float [] lons ;
54
- // private int[] priorities;
55
55
private long creationTime = System .currentTimeMillis ();
56
56
private int size ;
57
57
private int [] refToEdges ;
58
- // TODO use a bitset to memorize fragmented edges-area!
59
- private int [] edgesArea ;
60
- private int nextEdgePointer ;
61
- // private final ReadWriteLock lock;
62
- // private final Lock writeLock;
63
- // private final Lock readLock;
58
+ private int [][] edgesSegments ;
59
+ private int edgesSegmentSize ;
60
+ private int edgeCurrentSegment ;
61
+ private int edgeNextGlobalPointer ;
64
62
private String storageLocation ;
65
63
private MyBitSet deletedNodes ;
66
64
67
- // public MemoryGraphSafe() {
68
- // this(10);
69
- // }
70
65
public MemoryGraphSafe (int cap ) {
71
66
this (null , cap );
72
67
}
@@ -83,13 +78,21 @@ public MemoryGraphSafe(String storageDir, int cap, int capEdge) {
83
78
}
84
79
}
85
80
81
+ int getSegmentSize () {
82
+ return edgesSegmentSize ;
83
+ }
84
+
85
+ int getSegments () {
86
+ return edgesSegments .length ;
87
+ }
88
+
86
89
@ Override public int getNodes () {
87
90
// readLock.lock();
88
91
return size ;
89
92
}
90
93
91
- public int getMaxEdges () {
92
- return edgesArea .length / LEN_EDGE ;
94
+ private int getMaxEdges () {
95
+ return edgesSegments .length * edgesSegmentSize / LEN_EDGE ;
93
96
}
94
97
95
98
@ Override
@@ -101,27 +104,25 @@ public void setNode(int index, double lat, double lon) {
101
104
}
102
105
103
106
private void initEdges (int cap ) {
104
- cap *= LEN_EDGE ;
105
- edgesArea = new int [cap ];
106
- }
107
-
108
- // Use ONLY within a writer lock area
109
- private void ensureEdgesCapacity (int cap ) {
110
- ensureEdgePointer (cap * LEN_EDGE );
107
+ int tmp = (int ) (Math .log (cap ) / Math .log (2 ));
108
+ edgesSegmentSize = Math .max ((int ) Math .pow (2 , tmp ), MIN_SEGMENT_SIZE );
109
+ edgesSegments = new int [1 ][edgesSegmentSize ];
111
110
}
112
111
113
112
// Use ONLY within a writer lock area
114
113
private void ensureEdgePointer (int pointer ) {
115
- if (pointer + LEN_EDGE < edgesArea . length )
114
+ if (pointer + LEN_EDGE < edgesSegmentSize * getSegments () )
116
115
return ;
117
116
118
- // TODO instead of reallocation (memory waste, time to copy), create multiple segments for
119
- // edges and use the highest bits (any number 2^x) as the segment number.
120
- // Choose 2^x as segment number so we can use bit operations and avoid modulo for edgeId lookup!
121
- pointer = Math .max (10 * LEN_EDGE , Math .round (pointer * FACTOR ));
122
- logger .info ("ensure space to " + (int ) (pointer / LEN_EDGE ) + " edges (" + (float ) 4 * pointer / (1 << 20 ) + " MB)" );
123
- int newLen = pointer ;
124
- edgesArea = Arrays .copyOf (edgesArea , newLen );
117
+ // create a new segment
118
+ edgeCurrentSegment ++;
119
+ int [][] tmp = new int [edgeCurrentSegment + 1 ][];
120
+ for (int i = 0 ; i < edgesSegments .length ; i ++) {
121
+ tmp [i ] = edgesSegments [i ];
122
+ }
123
+ tmp [edgeCurrentSegment ] = new int [edgesSegmentSize ];
124
+ edgesSegments = tmp ;
125
+ // nextEdgePointer = 0;
125
126
}
126
127
127
128
// Use ONLY within a writer lock area
@@ -181,6 +182,20 @@ public void edge(int a, int b, double distance, boolean bothDirections) {
181
182
internalAdd (b , a , distance , dirFlag );
182
183
}
183
184
185
+ private void saveToEdgeArea (int pointer , int data ) {
186
+ // TODO improve speed via bit operations!
187
+ int segNumber = pointer / edgesSegmentSize ;
188
+ int segPointer = pointer % edgesSegmentSize ;
189
+ edgesSegments [segNumber ][segPointer ] = data ;
190
+ }
191
+
192
+ private int getFromEdgeArea (int pointer ) {
193
+ // TODO improve speed via bit operations!
194
+ int segNumber = pointer / edgesSegmentSize ;
195
+ int segPointer = pointer % edgesSegmentSize ;
196
+ return edgesSegments [segNumber ][segPointer ];
197
+ }
198
+
184
199
private void internalAdd (int fromNodeId , int toNodeId , double dist , int flags ) {
185
200
int edgePointer = refToEdges [fromNodeId ];
186
201
int newPos = nextEdgePointer ();
@@ -197,7 +212,7 @@ private void internalAdd(int fromNodeId, int toNodeId, double dist, int flags) {
197
212
throw new IllegalStateException ("list cannot be empty for positive edgePointer " + edgePointer + " node:" + fromNodeId );
198
213
199
214
int linkPointer = getLink (list .get (list .size () - 1 ));
200
- edgesArea [ linkPointer ] = newPos ;
215
+ saveToEdgeArea ( linkPointer , newPos ) ;
201
216
} else
202
217
refToEdges [fromNodeId ] = newPos ;
203
218
@@ -211,30 +226,30 @@ private int getLink(int edgePointer) {
211
226
private void writeEdge (int edgePointer , int flags , double dist , int toNodeId , int nextEdgePointer ) {
212
227
ensureEdgePointer (edgePointer );
213
228
214
- edgesArea [ edgePointer ] = flags ;
229
+ saveToEdgeArea ( edgePointer , flags ) ;
215
230
edgePointer += LEN_FLAGS ;
216
231
217
- edgesArea [ edgePointer ] = (int ) (dist * DIST_UNIT );
232
+ saveToEdgeArea ( edgePointer , (int ) (dist * DIST_UNIT ) );
218
233
edgePointer += LEN_DIST ;
219
234
220
- edgesArea [ edgePointer ] = toNodeId ;
235
+ saveToEdgeArea ( edgePointer , toNodeId ) ;
221
236
edgePointer += LEN_NODEID ;
222
237
223
- edgesArea [ edgePointer ] = nextEdgePointer ;
238
+ saveToEdgeArea ( edgePointer , nextEdgePointer ) ;
224
239
// edgePointer += LEN_LINK;
225
240
}
226
241
227
242
private int nextEdgePointer () {
228
- nextEdgePointer += LEN_EDGE ;
229
- return nextEdgePointer ;
243
+ edgeNextGlobalPointer += LEN_EDGE ;
244
+ return edgeNextGlobalPointer ;
230
245
}
231
246
232
247
private TIntArrayList readAllEdges (int edgePointer ) {
233
248
TIntArrayList list = new TIntArrayList (5 );
234
249
int i = 0 ;
235
250
for (; i < 1000 ; i ++) {
236
251
list .add (edgePointer );
237
- edgePointer = edgesArea [ getLink (edgePointer )] ;
252
+ edgePointer = getFromEdgeArea ( getLink (edgePointer )) ;
238
253
if (edgePointer == EMPTY_LINK )
239
254
break ;
240
255
}
@@ -282,20 +297,20 @@ public EdgeIterable(int node, boolean in, boolean out) {
282
297
283
298
void readNext () {
284
299
// readLock.lock();
285
- flags = edgesArea [ pointer ] ;
300
+ flags = getFromEdgeArea ( pointer ) ;
286
301
if (!in && (flags & 1 ) == 0 || !out && (flags & 2 ) == 0 ) {
287
- pointer = edgesArea [ getLink (pointer )] ;
302
+ pointer = getFromEdgeArea ( getLink (pointer )) ;
288
303
return ;
289
304
}
290
305
pointer += LEN_FLAGS ;
291
306
292
- dist = edgesArea [ pointer ] / DIST_UNIT ;
307
+ dist = getFromEdgeArea ( pointer ) / DIST_UNIT ;
293
308
pointer += LEN_DIST ;
294
309
295
- nodeId = edgesArea [ pointer ] ;
310
+ nodeId = getFromEdgeArea ( pointer ) ;
296
311
pointer += LEN_NODEID ;
297
312
// next edge
298
- pointer = edgesArea [ pointer ] ;
313
+ pointer = getFromEdgeArea ( pointer ) ;
299
314
foundNext = true ;
300
315
}
301
316
@@ -334,14 +349,25 @@ public int flags() {
334
349
@ Override
335
350
public Graph clone () {
336
351
// readLock.lock();
337
- MemoryGraphSafe g = new MemoryGraphSafe (null , refToEdges .length , getMaxEdges ());
338
- System .arraycopy (lats , 0 , g .lats , 0 , lats .length );
339
- System .arraycopy (lons , 0 , g .lons , 0 , lons .length );
340
- System .arraycopy (refToEdges , 0 , g .refToEdges , 0 , refToEdges .length );
341
- System .arraycopy (edgesArea , 0 , g .edgesArea , 0 , edgesArea .length );
342
- g .nextEdgePointer = nextEdgePointer ;
343
- g .size = size ;
344
- return g ;
352
+ MemoryGraphSafe clonedGraph = new MemoryGraphSafe (null , refToEdges .length , getMaxEdges ());
353
+
354
+ System .arraycopy (lats , 0 , clonedGraph .lats , 0 , lats .length );
355
+ System .arraycopy (lons , 0 , clonedGraph .lons , 0 , lons .length );
356
+ System .arraycopy (refToEdges , 0 , clonedGraph .refToEdges , 0 , refToEdges .length );
357
+
358
+ clonedGraph .edgesSegments = new int [edgeCurrentSegment + 1 ][];
359
+ for (int i = 0 ; i < clonedGraph .edgesSegments .length ; i ++) {
360
+ clonedGraph .edgesSegments [i ] = new int [edgesSegmentSize ];
361
+ }
362
+
363
+ for (int i = 0 ; i < edgesSegments .length ; i ++) {
364
+ System .arraycopy (edgesSegments [i ], 0 , clonedGraph .edgesSegments [i ], 0 , edgesSegmentSize );
365
+ }
366
+ clonedGraph .edgeCurrentSegment = edgeCurrentSegment ;
367
+ clonedGraph .edgesSegmentSize = edgesSegmentSize ;
368
+ clonedGraph .edgeNextGlobalPointer = edgeNextGlobalPointer ;
369
+ clonedGraph .size = size ;
370
+ return clonedGraph ;
345
371
}
346
372
347
373
private MyBitSet getDeletedNodes () {
@@ -380,7 +406,7 @@ public void optimize() {
380
406
if (deleted == 0 )
381
407
return ;
382
408
383
- // if (deleted < size / 5 ) {
409
+ // if (deleted < size / 4 ) {
384
410
inPlaceDelete (deleted );
385
411
// } else
386
412
// optimizeIfLotsOfDeletes(deleted);
@@ -524,7 +550,10 @@ void replacingDelete(int deleted) {
524
550
lats = inMemGraph .lats ;
525
551
lons = inMemGraph .lons ;
526
552
refToEdges = inMemGraph .refToEdges ;
527
- edgesArea = inMemGraph .edgesArea ;
553
+ for (int i = 0 ; i < edgesSegments .length ; i ++) {
554
+ edgesSegments [i ] = inMemGraph .edgesSegments [i ];
555
+ }
556
+
528
557
size = inMemGraph .size ;
529
558
deletedNodes = null ;
530
559
}
@@ -541,9 +570,10 @@ public void save() {
541
570
Helper .writeFloats (storageLocation + "/lats" , lats );
542
571
Helper .writeFloats (storageLocation + "/lons" , lons );
543
572
Helper .writeInts (storageLocation + "/refs" , refToEdges );
544
- Helper .writeInts (storageLocation + "/edges" , edgesArea );
545
- // Helper.writeInts(storageLocation + "/priorities", priorities);
546
- Helper .writeSettings (storageLocation + "/settings" , size , creationTime , nextEdgePointer );
573
+ for (int i = 0 ; i < edgesSegments .length ; i ++) {
574
+ Helper .writeInts (storageLocation + "/edges" + i , edgesSegments [i ]);
575
+ }
576
+ Helper .writeSettings (storageLocation + "/settings" , size , creationTime , edgeNextGlobalPointer , edgeCurrentSegment , edgesSegmentSize );
547
577
} catch (IOException ex ) {
548
578
throw new RuntimeException ("Couldn't write data to storage. location was " + storageLocation , ex );
549
579
}
@@ -561,15 +591,22 @@ public boolean loadExisting(String storageDir) {
561
591
562
592
size = (Integer ) ob [0 ];
563
593
creationTime = (Long ) ob [1 ];
564
- nextEdgePointer = (Integer ) ob [2 ];
565
- logger .info ("found graph " + storageLocation + " with size:" + size
566
- + ", edges:" + nextEdgePointer / LEN_EDGE + ", created-at:" + new Date (creationTime ));
594
+ edgeNextGlobalPointer = (Integer ) ob [2 ];
595
+ edgeCurrentSegment = (Integer ) ob [3 ];
596
+ edgesSegmentSize = (Integer ) ob [4 ];
597
+ logger .info ("found graph " + storageLocation + " with nodes:" + size
598
+ + ", edges:" + edgeNextGlobalPointer / LEN_EDGE
599
+ + ", edges segments:" + (edgeCurrentSegment + 1 )
600
+ + ", edges segmentSize:" + edgesSegmentSize
601
+ + ", created-at:" + new Date (creationTime ));
567
602
568
603
lats = Helper .readFloats (storageLocation + "/lats" );
569
604
lons = Helper .readFloats (storageLocation + "/lons" );
570
605
refToEdges = Helper .readInts (storageLocation + "/refs" );
571
- edgesArea = Helper .readInts (storageLocation + "/edges" );
572
- // priorities = Helper.readInts(storageLocation + "/priorities");
606
+ edgesSegments = new int [edgeCurrentSegment + 1 ][];
607
+ for (int i = 0 ; i <= edgeCurrentSegment ; i ++) {
608
+ edgesSegments [i ] = Helper .readInts (storageLocation + "/edges" + i );
609
+ }
573
610
deletedNodes = new MyOpenBitSet (lats .length );
574
611
return true ;
575
612
} catch (IOException ex ) {
0 commit comments