Speedup native load

This commit is contained in:
Victor Shcherb 2012-08-28 02:08:41 +02:00
parent 1842c0369b
commit 788d108746
11 changed files with 6333 additions and 29 deletions

View file

@ -84,6 +84,10 @@ public class NativeLibrary {
return initBinaryMapFile(filePath); return initBinaryMapFile(filePath);
} }
public boolean initCacheMapFile(String filePath) {
return initCacheMapFiles(filePath);
}
public boolean closeMapFile(String filePath) { public boolean closeMapFile(String filePath) {
return closeBinaryMapFile(filePath); return closeBinaryMapFile(filePath);
} }
@ -110,6 +114,8 @@ public class NativeLibrary {
protected static native boolean initBinaryMapFile(String filePath); protected static native boolean initBinaryMapFile(String filePath);
protected static native boolean initCacheMapFiles(String filePath);
protected static native boolean closeBinaryMapFile(String filePath); protected static native boolean closeBinaryMapFile(String filePath);
protected static native void initRenderingRulesStorage(RenderingRulesStorage storage); protected static native void initRenderingRulesStorage(RenderingRulesStorage storage);

View file

@ -45,6 +45,11 @@ public class CachedOsmandIndexes {
storedIndexBuilder = OsmandIndex.OsmAndStoredIndex.newBuilder(); storedIndexBuilder = OsmandIndex.OsmAndStoredIndex.newBuilder();
storedIndexBuilder.setVersion(VERSION); storedIndexBuilder.setVersion(VERSION);
storedIndexBuilder.setDateCreated(System.currentTimeMillis()); storedIndexBuilder.setDateCreated(System.currentTimeMillis());
if(storedIndex != null) {
for(FileIndex ex : storedIndex.getFileIndexList()) {
storedIndexBuilder.addFileIndex(ex);
}
}
} }
FileIndex.Builder fileIndex = OsmandIndex.FileIndex.newBuilder(); FileIndex.Builder fileIndex = OsmandIndex.FileIndex.newBuilder();

View file

@ -2,9 +2,10 @@
option java_package = "net.osmand.binary"; option java_package = "net.osmand.binary";
//protoc --java_out=DataExtractionOSM/src DataExtractionOSM/src/osmand_index.proto //protoc --java_out=DataExtractionOSM/src DataExtractionOSM/src/osmand_index.proto
// C++ # cd OsmAnd // C++ # cd OsmAnd-Kernel
// # protoc --proto_path=../DataExtractionOSM/src --cpp_out=jni/osmand/proto ../DataExtractionOSM/src/osmand_odb.proto // # protoc --proto_path=../DataExtractionOSM/src --cpp_out=osmand/src/proto ../DataExtractionOSM/src/osmand_index.proto
option optimize_for = LITE_RUNTIME;
message OsmAndStoredIndex { message OsmAndStoredIndex {
required uint32 version = 1; required uint32 version = 1;

View file

@ -39,6 +39,7 @@ import net.osmand.plus.AsyncLoadingThread.MapLoadRequest;
import net.osmand.plus.AsyncLoadingThread.TileLoadDownloadRequest; import net.osmand.plus.AsyncLoadingThread.TileLoadDownloadRequest;
import net.osmand.plus.AsyncLoadingThread.TransportLoadRequest; import net.osmand.plus.AsyncLoadingThread.TransportLoadRequest;
import net.osmand.plus.render.MapRenderRepositories; import net.osmand.plus.render.MapRenderRepositories;
import net.osmand.plus.render.NativeOsmandLibrary;
import net.osmand.plus.views.OsmandMapLayer.DrawSettings; import net.osmand.plus.views.OsmandMapLayer.DrawSettings;
import net.osmand.render.RenderingRulesStorage; import net.osmand.render.RenderingRulesStorage;
@ -533,6 +534,11 @@ public class ResourceManager {
if(indCache.exists()) { if(indCache.exists()) {
try { try {
cachedOsmandIndexes.readFromFile(indCache, CachedOsmandIndexes.VERSION); cachedOsmandIndexes.readFromFile(indCache, CachedOsmandIndexes.VERSION);
NativeOsmandLibrary nativeLib = context.getSettings().NATIVE_RENDERING.get() ? NativeOsmandLibrary.getLoadedLibrary()
: null;
if(nativeLib != null) {
nativeLib.initCacheMapFile(indCache.getAbsolutePath());
}
} catch (Exception e) { } catch (Exception e) {
log.error(e.getMessage(), e); log.error(e.getMessage(), e);
} }
@ -546,7 +552,6 @@ public class ResourceManager {
BinaryMapIndexReader index = null; BinaryMapIndexReader index = null;
try { try {
index = cachedOsmandIndexes.getReader(f); index = cachedOsmandIndexes.getReader(f);
if (index.getVersion() != IndexConstants.BINARY_MAP_VERSION) { if (index.getVersion() != IndexConstants.BINARY_MAP_VERSION) {
index = null; index = null;
} }

View file

@ -114,13 +114,13 @@ public class MapRenderRepositories {
NativeOsmandLibrary nativeLib = prefs.NATIVE_RENDERING.get() ? NativeOsmandLibrary.getLoadedLibrary() : null; NativeOsmandLibrary nativeLib = prefs.NATIVE_RENDERING.get() ? NativeOsmandLibrary.getLoadedLibrary() : null;
if (nativeLib != null) { if (nativeLib != null) {
if (!nativeLib.initMapFile(file.getAbsolutePath())) { if (!nativeLib.initMapFile(file.getAbsolutePath())) {
log.debug("Initializing native db " + file.getAbsolutePath() + " failed!"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ log.error("Initializing native db " + file.getAbsolutePath() + " failed!"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
} else { } else {
nativeFiles.add(file.getAbsolutePath()); nativeFiles.add(file.getAbsolutePath());
long val = System.currentTimeMillis(); // long val = System.currentTimeMillis();
if (log.isDebugEnabled()) { // if (log.isDebugEnabled()) {
log.debug("Initializing native db " + file.getAbsolutePath() + " " + (val - start) + "ms"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ // log.debug("Initializing native db " + file.getAbsolutePath() + " " + (val - start) + "ms"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
} // }
} }
} }
} }

View file

@ -21,7 +21,8 @@ LOCAL_SRC_FILES := \
src/multipolygons.cpp \ src/multipolygons.cpp \
src/renderRules.cpp \ src/renderRules.cpp \
src/rendering.cpp \ src/rendering.cpp \
src/binaryRead.cpp src/binaryRead.cpp \
src/proto/osmand_index.pb.cpp
ifdef OSMAND_PROFILE_NATIVE_OPERATIONS ifdef OSMAND_PROFILE_NATIVE_OPERATIONS
LOCAL_CFLAGS += \ LOCAL_CFLAGS += \

View file

@ -9,6 +9,7 @@
#include "google/protobuf/io/zero_copy_stream_impl.h" #include "google/protobuf/io/zero_copy_stream_impl.h"
#include "google/protobuf/wire_format_lite.cc" #include "google/protobuf/wire_format_lite.cc"
#include "proto/osmand_odb.pb.h" #include "proto/osmand_odb.pb.h"
#include "proto/osmand_index.pb.h"
#include "osmand_log.h" #include "osmand_log.h"
using namespace std; using namespace std;
@ -20,6 +21,7 @@ using google::protobuf::internal::WireFormatLite;
std::map< std::string, BinaryMapFile* > openFiles; std::map< std::string, BinaryMapFile* > openFiles;
OsmAndStoredIndex* cache = NULL;
inline bool readInt(CodedInputStream* input, uint32_t* sz ){ inline bool readInt(CodedInputStream* input, uint32_t* sz ){
uint8_t buf[4]; uint8_t buf[4];
@ -1035,21 +1037,22 @@ ResultPublisher* searchObjectsForRendering(SearchQuery* q, bool skipDuplicates,
return q->publisher; return q->publisher;
} }
void searchRouteRegion(CodedInputStream* input, SearchQuery* q, RoutingIndex* ind, std::vector<RouteSubregion>& subregions, void searchRouteRegion(CodedInputStream* input, SearchQuery* q, RoutingIndex* ind, std::vector<RouteSubregion>& subregions,
std::vector<RouteSubregion>& toLoad) { std::vector<RouteSubregion>& toLoad, BinaryMapFile* file) {
for (std::vector<RouteSubregion>::iterator subreg = subregions.begin(); for (std::vector<RouteSubregion>::iterator subreg = subregions.begin();
subreg != subregions.end(); subreg++) { subreg != subregions.end(); subreg++) {
if (subreg->right >= q->left && q->right >= subreg->left && subreg->bottom >= q->top if (subreg->right >= q->left && q->right >= subreg->left && subreg->bottom >= q->top
&& q->bottom >= subreg->top) { && q->bottom >= subreg->top) {
if(subreg->subregions.empty()){ if(subreg->subregions.empty()){
bool contains = subreg->right <= q->right && q->left <= subreg->left && subreg->top <= q->top bool contains = subreg->right <= q->right && q->left <= subreg->left && subreg->top <= q->top
&& subreg->bottom >= q->bottom; && subreg->bottom >= q->bottom;
input->Seek(subreg->filePointer); input->Seek(subreg->filePointer);
uint32_t old = input -> PushLimit(subreg->length); uint32_t old = input->PushLimit(subreg->length);
readRouteTree(input, &(*subreg), NULL, contains? -1 : 1, false); readRouteTree(input, &(*subreg), NULL, contains? -1 : 1, false);
input->PopLimit(old); input->PopLimit(old);
} }
searchRouteRegion(input, q, ind, subreg->subregions, toLoad); searchRouteRegion(input, q, ind, subreg->subregions, toLoad, file);
if(subreg->mapDataBlock != 0) { if(subreg->mapDataBlock != 0) {
toLoad.push_back(*subreg); toLoad.push_back(*subreg);
} }
@ -1312,11 +1315,6 @@ void searchRouteRegion(SearchQuery* q, std::vector<RouteDataObject*>& list, Rout
bool basemapExists = false; bool basemapExists = false;
for (; i != openFiles.end() && !q->publisher->isCancelled(); i++) { for (; i != openFiles.end() && !q->publisher->isCancelled(); i++) {
BinaryMapFile* file = i->second; BinaryMapFile* file = i->second;
lseek(file->routefd, 0, SEEK_SET);
FileInputStream input(file->routefd);
input.SetCloseOnDelete(false);
CodedInputStream cis(&input);
cis.SetTotalBytesLimit(INT_MAX, INT_MAX >> 2);
for (std::vector<RoutingIndex>::iterator routingIndex = file->routingIndexes.begin(); for (std::vector<RoutingIndex>::iterator routingIndex = file->routingIndexes.begin();
routingIndex != file->routingIndexes.end(); routingIndex++) { routingIndex != file->routingIndexes.end(); routingIndex++) {
if (q->publisher->isCancelled()) { if (q->publisher->isCancelled()) {
@ -1325,10 +1323,44 @@ void searchRouteRegion(SearchQuery* q, std::vector<RouteDataObject*>& list, Rout
if(rs != NULL && (rs->name != routingIndex->name || rs->filePointer != routingIndex->filePointer)){ if(rs != NULL && (rs->name != routingIndex->name || rs->filePointer != routingIndex->filePointer)){
continue; continue;
} }
// check boundaries and init
if (routingIndex->decodingRules.size() == 0) {
bool contain = false;
for (std::vector<RouteSubregion>::iterator subreg = routingIndex->subregions.begin(); subreg != routingIndex->subregions.end();
subreg++) {
if (subreg->right >= q->left && q->right >= subreg->left && subreg->bottom >= q->top
&& q->bottom >= subreg->top) {
contain = true;
}
}
if (contain) {
routingIndex->subregions.clear();
osmand_log_print(LOG_INFO, "Init native index %s", routingIndex->name.c_str());
lseek(file->routefd, 0, SEEK_SET);
FileInputStream input(file->routefd);
input.SetCloseOnDelete(false);
CodedInputStream cis(&input);
cis.SetTotalBytesLimit(INT_MAX, INT_MAX >> 2);
cis.Seek(routingIndex->filePointer);
uint32_t old = cis.PushLimit(routingIndex->length);
readRoutingIndex(&cis, routingIndex);
cis.PopLimit(old);
} else {
continue;
}
}
// could be simplified but it will be concurrency with init block
lseek(file->routefd, 0, SEEK_SET);
FileInputStream input(file->routefd);
input.SetCloseOnDelete(false);
CodedInputStream cis(&input);
cis.SetTotalBytesLimit(INT_MAX, INT_MAX >> 2);
std::vector<RouteSubregion> toLoad; std::vector<RouteSubregion> toLoad;
searchRouteRegion(&cis, q, &(*routingIndex), routingIndex->subregions, toLoad); searchRouteRegion(&cis, q, &(*routingIndex), routingIndex->subregions, toLoad, file);
sort(toLoad.begin(), toLoad.end(), sortRouteRegions); sort(toLoad.begin(), toLoad.end(), sortRouteRegions);
;
std::vector<RouteDataObject*> iteration; std::vector<RouteDataObject*> iteration;
int cnt = 0; int cnt = 0;
for (std::vector<RouteSubregion>::iterator subreg = toLoad.begin(); subreg != toLoad.end(); subreg++) { for (std::vector<RouteSubregion>::iterator subreg = toLoad.begin(); subreg != toLoad.end(); subreg++) {
@ -1357,6 +1389,41 @@ bool closeBinaryMapFile(std::string inputName) {
return false; return false;
} }
bool initMapFilesFromCache(std::string inputName) {
GOOGLE_PROTOBUF_VERIFY_VERSION;
#if defined(_WIN32)
int fileDescriptor = open(inputName.c_str(), O_RDONLY | O_BINARY);
#else
int fileDescriptor = open(inputName.c_str(), O_RDONLY);
#endif
if (fileDescriptor < 0) {
osmand_log_print(LOG_ERROR, "Cache file could not be open to read : %s", inputName.c_str());
return false;
}
FileInputStream input(fileDescriptor);
CodedInputStream cis(&input);
cis.SetTotalBytesLimit(INT_MAX, INT_MAX);
OsmAndStoredIndex* c = new OsmAndStoredIndex();
if(c->MergeFromCodedStream(&cis)){
osmand_log_print(LOG_INFO, "Native Cache file initialized %s", inputName.c_str());
cache = c;
for (int i = 0; i < cache->fileindex_size(); i++) {
FileIndex fi = cache->fileindex(i);
}
return true;
}
return false;
}
bool hasEnding (std::string const &fullString, std::string const &ending)
{
if (fullString.length() >= ending.length()) {
return (0 == fullString.compare (fullString.length() - ending.length(), ending.length(), ending));
} else {
return false;
}
}
BinaryMapFile* initBinaryMapFile(std::string inputName) { BinaryMapFile* initBinaryMapFile(std::string inputName) {
GOOGLE_PROTOBUF_VERIFY_VERSION; GOOGLE_PROTOBUF_VERIFY_VERSION;
std::map<std::string, BinaryMapFile*>::iterator iterator; std::map<std::string, BinaryMapFile*>::iterator iterator;
@ -1378,16 +1445,82 @@ BinaryMapFile* initBinaryMapFile(std::string inputName) {
} }
BinaryMapFile* mapFile = new BinaryMapFile(); BinaryMapFile* mapFile = new BinaryMapFile();
mapFile->fd = fileDescriptor; mapFile->fd = fileDescriptor;
mapFile->routefd = routeDescriptor; struct stat stat;
FileInputStream input(fileDescriptor); fstat(fileDescriptor, &stat);
input.SetCloseOnDelete(false);
CodedInputStream cis(&input);
cis.SetTotalBytesLimit(INT_MAX, INT_MAX);
if (!initMapStructure(&cis, mapFile)) { mapFile->routefd = routeDescriptor;
osmand_log_print(LOG_ERROR, "File not initialised : %s", inputName.c_str()); bool readFromCache = cache != NULL;
delete mapFile; FileIndex* fo = NULL;
return NULL; if (readFromCache) {
for (int i = 0; i < cache->fileindex_size(); i++) {
FileIndex fi = cache->fileindex(i);
if (hasEnding(inputName, fi.filename()) && fi.size() == stat.st_size) {
fo = cache->mutable_fileindex(i);
break;
}
}
}
if (fo != NULL) {
mapFile->version = fo->version();
mapFile->dateCreated = fo->datemodified();
for (int i = 0; i < fo->mapindex_size(); i++) {
MapIndex mi;
MapPart mp = fo->mapindex(i);
mi.filePointer = mp.offset();
mi.length = mp.size();
mi.name = mp.name();
for (int j = 0; j < mp.levels_size(); j++) {
MapLevel ml = mp.levels(j);
MapRoot mr;
mr.bottom = ml.bottom();
mr.left = ml.left();
mr.right = ml.right();
mr.top = ml.top();
mr.maxZoom = ml.maxzoom();
mr.minZoom = ml.minzoom();
mr.filePointer = ml.offset();
mr.length = ml.size();
mi.levels.push_back(mr);
}
mapFile->basemap = mapFile->basemap || mi.name.find("basemap") != string::npos;
mapFile->mapIndexes.push_back(mi);
mapFile->indexes.push_back(&mapFile->mapIndexes.back());
}
for (int i = 0; i < fo->routingindex_size(); i++) {
RoutingIndex mi;
RoutingPart mp = fo->routingindex(i);
mi.filePointer = mp.offset();
mi.length = mp.size();
mi.name = mp.name();
for (int j = 0; j < mp.subregions_size(); j++) {
RoutingSubregion ml = mp.subregions(j);
RouteSubregion mr;
mr.bottom = ml.bottom();
mr.left = ml.left();
mr.right = ml.right();
mr.top = ml.top();
mr.mapDataBlock = ml.shiftodata();
mr.filePointer = ml.offset();
mr.length = ml.size();
osmand_log_print(LOG_DEBUG, "Native file init subregion %d %d %d ", mr.filePointer, mr.length, mr.mapDataBlock);
mi.subregions.push_back(mr);
}
mapFile->routingIndexes.push_back(mi);
mapFile->indexes.push_back(&mapFile->routingIndexes.back());
}
osmand_log_print(LOG_DEBUG, "Native file initialized from cache %s", inputName.c_str());
} else {
FileInputStream input(fileDescriptor);
input.SetCloseOnDelete(false);
CodedInputStream cis(&input);
cis.SetTotalBytesLimit(INT_MAX, INT_MAX);
if (!initMapStructure(&cis, mapFile)) {
osmand_log_print(LOG_ERROR, "File not initialised : %s", inputName.c_str());
delete mapFile;
return NULL;
}
} }
mapFile->inputName = inputName; mapFile->inputName = inputName;
openFiles.insert(std::pair<std::string, BinaryMapFile*>(inputName, mapFile)); openFiles.insert(std::pair<std::string, BinaryMapFile*>(inputName, mapFile));

View file

@ -249,6 +249,8 @@ ResultPublisher* searchObjectsForRendering(SearchQuery* q, bool skipDuplicates,
BinaryMapFile* initBinaryMapFile(std::string inputName); BinaryMapFile* initBinaryMapFile(std::string inputName);
bool initMapFilesFromCache(std::string inputName) ;
bool closeBinaryMapFile(std::string inputName); bool closeBinaryMapFile(std::string inputName);
#endif #endif

View file

@ -52,6 +52,16 @@ extern "C" JNIEXPORT void JNICALL Java_net_osmand_NativeLibrary_closeBinaryMapFi
closeBinaryMapFile(inputName); closeBinaryMapFile(inputName);
} }
extern "C" JNIEXPORT jboolean JNICALL Java_net_osmand_NativeLibrary_initCacheMapFiles(JNIEnv* ienv,
jobject obj,
jobject path) {
const char* utf = ienv->GetStringUTFChars((jstring) path, NULL);
std::string inputName(utf);
ienv->ReleaseStringUTFChars((jstring) path, utf);
return initMapFilesFromCache(inputName);
}
extern "C" JNIEXPORT jboolean JNICALL Java_net_osmand_NativeLibrary_initBinaryMapFile(JNIEnv* ienv, extern "C" JNIEXPORT jboolean JNICALL Java_net_osmand_NativeLibrary_initBinaryMapFile(JNIEnv* ienv,
jobject obj, jobject path) { jobject obj, jobject path) {
// Verify that the version of the library that we linked against is // Verify that the version of the library that we linked against is

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff