Improve Transport reader algorith (make it much faster?)

This commit is contained in:
Victor Shcherb 2019-07-31 00:56:54 +02:00
parent c89fda16f4
commit 39845c3601
2 changed files with 63 additions and 73 deletions

View file

@ -504,9 +504,9 @@ public class BinaryMapIndexReader {
result.put(filePointer, transportRoute);
finishInit.add(transportRoute);
}
transportAdapter.initializeStringTable(ind, stringTable);
TIntObjectHashMap<String> indexedStringTable = transportAdapter.initializeStringTable(ind, stringTable);
for(TransportRoute transportRoute : finishInit ) {
transportAdapter.initializeNames(false, transportRoute, stringTable);
transportAdapter.initializeNames(false, transportRoute, indexedStringTable);
}
}
@ -556,27 +556,29 @@ public class BinaryMapIndexReader {
}
return false;
}
public List<TransportStop> searchTransportIndex(TransportIndex index, SearchRequest<TransportStop> req) throws IOException {
if (index.stopsFileLength == 0 || index.right < req.left || index.left > req.right || index.top > req.bottom
|| index.bottom < req.top) {
return req.getSearchResults();
}
codedIS.seek(index.stopsFileOffset);
int oldLimit = codedIS.pushLimit(index.stopsFileLength);
int offset = req.searchResults.size();
TIntObjectHashMap<String> stringTable = new TIntObjectHashMap<String>();
transportAdapter.searchTransportTreeBounds(0, 0, 0, 0, req, stringTable);
codedIS.popLimit(oldLimit);
TIntObjectHashMap<String> indexedStringTable = transportAdapter.initializeStringTable(index, stringTable);
for (int i = offset; i < req.searchResults.size(); i++) {
TransportStop st = req.searchResults.get(i);
transportAdapter.initializeNames(indexedStringTable, st);
}
return req.getSearchResults();
}
public List<TransportStop> searchTransportIndex(SearchRequest<TransportStop> req) throws IOException {
for (TransportIndex index : transportIndexes) {
if (index.stopsFileLength == 0 || index.right < req.left || index.left > req.right || index.top > req.bottom
|| index.bottom < req.top) {
continue;
}
if (req.stringTable != null) {
req.stringTable.clear();
}
codedIS.seek(index.stopsFileOffset);
int oldLimit = codedIS.pushLimit(index.stopsFileLength);
int offset = req.searchResults.size();
transportAdapter.searchTransportTreeBounds(0, 0, 0, 0, req);
codedIS.popLimit(oldLimit);
if (req.stringTable != null) {
transportAdapter.initializeStringTable(index, req.stringTable);
for (int i = offset; i < req.searchResults.size(); i++) {
TransportStop st = req.searchResults.get(i);
transportAdapter.initializeNames(req.stringTable, st);
}
}
searchTransportIndex(index, req);
}
if (req.numberOfVisitedObjects > 0) {
log.debug("Search is done. Visit " + req.numberOfVisitedObjects + " objects. Read " + req.numberOfAcceptedObjects + " objects."); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
@ -1522,7 +1524,6 @@ public class BinaryMapIndexReader {
if (stops != null) {
request.searchResults = stops;
}
request.stringTable = new TIntObjectHashMap<String>();
request.left = sleft >> (31 - TRANSPORT_STOP_ZOOM);
request.right = sright >> (31 - TRANSPORT_STOP_ZOOM);
request.top = stop >> (31 - TRANSPORT_STOP_ZOOM);
@ -1620,9 +1621,6 @@ public class BinaryMapIndexReader {
SearchPoiTypeFilter poiTypeFilter = null;
// internal read information
TIntObjectHashMap<String> stringTable = null;
// cache information
TIntArrayList cacheCoordinates = new TIntArrayList();
TIntArrayList cacheTypes = new TIntArrayList();
@ -1746,9 +1744,6 @@ public class BinaryMapIndexReader {
searchResults = new ArrayList<T>();
cacheCoordinates.clear();
cacheTypes.clear();
if(stringTable != null) {
stringTable.clear();
}
land = false;
ocean = false;
numberOfVisitedObjects = 0;

View file

@ -1,7 +1,6 @@
package net.osmand.binary;
import java.io.IOException;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
@ -9,7 +8,6 @@ import java.util.Map;
import com.google.protobuf.CodedInputStream;
import com.google.protobuf.WireFormat;
import gnu.trove.list.array.TIntArrayList;
import gnu.trove.map.hash.TIntObjectHashMap;
import net.osmand.binary.BinaryMapIndexReader.SearchRequest;
import net.osmand.data.TransportSchedule;
@ -76,10 +74,7 @@ public class BinaryMapTransportReaderAdapter {
protected static class IndexStringTable {
int fileOffset = 0;
int length = 0;
// offset from start for each SIZE_OFFSET_ARRAY elements
// (SIZE_OFFSET_ARRAY + 1) offset = offsets[0] + skipOneString()
TIntArrayList offsets = new TIntArrayList();
TIntObjectHashMap<String> stringTable = null;
}
@ -147,7 +142,7 @@ public class BinaryMapTransportReaderAdapter {
}
protected void searchTransportTreeBounds(int pleft, int pright, int ptop, int pbottom,
SearchRequest<TransportStop> req) throws IOException {
SearchRequest<TransportStop> req, TIntObjectHashMap<String> stringTable) throws IOException {
int init = 0;
int lastIndexResult = -1;
int cright = 0;
@ -197,7 +192,7 @@ public class BinaryMapTransportReaderAdapter {
lastIndexResult = req.getSearchResults().size();
}
req.numberOfVisitedObjects++;
TransportStop transportStop = readTransportStop(stopOffset, cleft, cright, ctop, cbottom, req);
TransportStop transportStop = readTransportStop(stopOffset, cleft, cright, ctop, cbottom, req, stringTable);
if(transportStop != null){
req.publish(transportStop);
}
@ -209,7 +204,7 @@ public class BinaryMapTransportReaderAdapter {
int filePointer = codedIS.getTotalBytesRead();
if (req.limit == -1 || req.limit >= req.getSearchResults().size()) {
oldLimit = codedIS.pushLimit(length);
searchTransportTreeBounds(cleft, cright, ctop, cbottom, req);
searchTransportTreeBounds(cleft, cright, ctop, cbottom, req, stringTable);
codedIS.popLimit(oldLimit);
}
codedIS.seek(filePointer + length);
@ -392,35 +387,33 @@ public class BinaryMapTransportReaderAdapter {
}
protected void initializeStringTable(TransportIndex ind, TIntObjectHashMap<String> stringTable) throws IOException {
int[] values = stringTable.keys();
Arrays.sort(values);
codedIS.seek(ind.stringTable.fileOffset);
int oldLimit = codedIS.pushLimit(ind.stringTable.length);
int current = 0;
int i = 0;
while (i < values.length && codedIS.getBytesUntilLimit() > 0) {
int t = codedIS.readTag();
int tag = WireFormat.getTagFieldNumber(t);
switch (tag) {
case 0:
break;
case OsmandOdb.StringTable.S_FIELD_NUMBER:
if (current == values[i]) {
protected TIntObjectHashMap<String> initializeStringTable(TransportIndex ind,
TIntObjectHashMap<String> requested) throws IOException {
if (ind.stringTable.stringTable == null) {
ind.stringTable.stringTable = new TIntObjectHashMap<>();
codedIS.seek(ind.stringTable.fileOffset);
int oldLimit = codedIS.pushLimit(ind.stringTable.length);
int current = 0;
int i = 0;
while (codedIS.getBytesUntilLimit() > 0) {
int t = codedIS.readTag();
int tag = WireFormat.getTagFieldNumber(t);
switch (tag) {
case 0:
break;
case OsmandOdb.StringTable.S_FIELD_NUMBER:
String value = codedIS.readString();
stringTable.put(values[i], value);
i++;
} else {
ind.stringTable.stringTable.put(current, value);
current++;
break;
default:
skipUnknownField(t);
break;
}
current ++;
break;
default:
skipUnknownField(t);
break;
}
codedIS.popLimit(oldLimit);
}
codedIS.popLimit(oldLimit);
return ind.stringTable.stringTable;
}
protected void initializeNames(boolean onlyDescription, net.osmand.data.TransportRoute dataObject,
@ -513,7 +506,8 @@ public class BinaryMapTransportReaderAdapter {
return dataObject;
}
private TransportStop readTransportStop(int shift, int cleft, int cright, int ctop, int cbottom, SearchRequest<TransportStop> req) throws IOException {
private TransportStop readTransportStop(int shift, int cleft, int cright, int ctop, int cbottom,
SearchRequest<TransportStop> req, TIntObjectHashMap<String> stringTable) throws IOException {
int tag = WireFormat.getTagFieldNumber(codedIS.readTag());
if(OsmandOdb.TransportStop.DX_FIELD_NUMBER != tag) {
throw new IllegalArgumentException();
@ -560,26 +554,26 @@ public class BinaryMapTransportReaderAdapter {
req.cacheIdsB.add(codedIS.readUInt64());
break;
case OsmandOdb.TransportStop.NAME_EN_FIELD_NUMBER :
if (req.stringTable != null) {
dataObject.setEnName(regStr(req.stringTable)); //$NON-NLS-1$
if (stringTable != null) {
dataObject.setEnName(regStr(stringTable)); //$NON-NLS-1$
} else {
skipUnknownField(t);
}
break;
case OsmandOdb.TransportStop.NAME_FIELD_NUMBER :
if (req.stringTable != null) {
dataObject.setName(regStr(req.stringTable)); //$NON-NLS-1$
if (stringTable != null) {
dataObject.setName(regStr(stringTable)); //$NON-NLS-1$
} else {
skipUnknownField(t);
}
break;
case OsmandOdb.TransportStop.ADDITIONALNAMEPAIRS_FIELD_NUMBER :
if (req.stringTable != null) {
if (stringTable != null) {
int sizeL = codedIS.readRawVarint32();
int oldRef = codedIS.pushLimit(sizeL);
while (codedIS.getBytesUntilLimit() > 0) {
dataObject.setName(regStr(req.stringTable,codedIS.readRawVarint32()),
regStr(req.stringTable,codedIS.readRawVarint32()));
dataObject.setName(regStr(stringTable,codedIS.readRawVarint32()),
regStr(stringTable,codedIS.readRawVarint32()));
}
codedIS.popLimit(oldRef);
} else {
@ -593,7 +587,7 @@ public class BinaryMapTransportReaderAdapter {
int length = codedIS.readRawVarint32();
int oldLimit = codedIS.pushLimit(length);
TransportStopExit transportStopExit = readTransportStopExit(cleft, ctop, req);
TransportStopExit transportStopExit = readTransportStopExit(cleft, ctop, req, stringTable);
dataObject.addExit(transportStopExit);
codedIS.popLimit(oldLimit);
break;
@ -604,7 +598,8 @@ public class BinaryMapTransportReaderAdapter {
}
}
private TransportStopExit readTransportStopExit(int cleft, int ctop, SearchRequest<TransportStop> req) throws IOException {
private TransportStopExit readTransportStopExit(int cleft, int ctop, SearchRequest<TransportStop> req,
TIntObjectHashMap<String> stringTable) throws IOException {
TransportStopExit dataObject = new TransportStopExit();
int x = 0;
@ -624,8 +619,8 @@ public class BinaryMapTransportReaderAdapter {
}
return dataObject;
case OsmandOdb.TransportStopExit.REF_FIELD_NUMBER:
if (req.stringTable != null) {
dataObject.setRef(regStr(req.stringTable));
if (stringTable != null) {
dataObject.setRef(regStr(stringTable));
} else {
skipUnknownField(t);
}