fix performance for hamlets in address inde

git-svn-id: https://osmand.googlecode.com/svn/trunk@627 e29c36b1-1cfa-d876-8d93-3434fc2bb7b8
This commit is contained in:
Victor Shcherb 2010-11-02 23:27:39 +00:00
parent 2c30496c45
commit 0cbabe4bd2
4 changed files with 96 additions and 38 deletions

View file

@ -17,6 +17,7 @@ import net.osmand.data.PostCode;
import net.osmand.data.Street; import net.osmand.data.Street;
import net.osmand.data.City.CityType; import net.osmand.data.City.CityType;
import net.osmand.osm.MapUtils; import net.osmand.osm.MapUtils;
import net.sf.junidecode.Junidecode;
import org.apache.commons.logging.Log; import org.apache.commons.logging.Log;
@ -106,6 +107,9 @@ public class BinaryMapIndexReader {
return; return;
case OsmandOdb.OsmAndAddressIndex.NAME_FIELD_NUMBER : case OsmandOdb.OsmAndAddressIndex.NAME_FIELD_NUMBER :
region.name = codedIS.readString(); region.name = codedIS.readString();
if(region.enName == null){
region.enName = Junidecode.unidecode(region.name);
}
break; break;
case OsmandOdb.OsmAndAddressIndex.NAME_EN_FIELD_NUMBER : case OsmandOdb.OsmAndAddressIndex.NAME_EN_FIELD_NUMBER :
region.enName = codedIS.readString(); region.enName = codedIS.readString();
@ -312,20 +316,23 @@ public class BinaryMapIndexReader {
codedIS.seek(r.citiesOffset); codedIS.seek(r.citiesOffset);
int len = readInt(); int len = readInt();
int old = codedIS.pushLimit(len); int old = codedIS.pushLimit(len);
readCities(cities); readCities(cities, null, false);
codedIS.popLimit(old); codedIS.popLimit(old);
} }
return cities; return cities;
} }
public List<City> getVillages(String region) throws IOException { public List<City> getVillages(String region) throws IOException {
return getVillages(region, null, false);
}
public List<City> getVillages(String region, String nameContains, boolean useEn) throws IOException {
List<City> cities = new ArrayList<City>(); List<City> cities = new ArrayList<City>();
AddressRegion r = getRegionByName(region); AddressRegion r = getRegionByName(region);
if(r.villagesOffset != -1){ if(r.villagesOffset != -1){
codedIS.seek(r.villagesOffset); codedIS.seek(r.villagesOffset);
int len = readInt(); int len = readInt();
int old = codedIS.pushLimit(len); int old = codedIS.pushLimit(len);
readCities(cities); readCities(cities, nameContains, useEn);
codedIS.popLimit(old); codedIS.popLimit(old);
} }
return cities; return cities;
@ -376,7 +383,7 @@ public class BinaryMapIndexReader {
} }
} }
private void readCities(List<City> cities) throws IOException{ private void readCities(List<City> cities, String nameContains, boolean useEn) throws IOException {
while(true){ while(true){
int t = codedIS.readTag(); int t = codedIS.readTag();
int tag = WireFormat.getTagFieldNumber(t); int tag = WireFormat.getTagFieldNumber(t);
@ -388,7 +395,41 @@ public class BinaryMapIndexReader {
int length = codedIS.readRawVarint32(); int length = codedIS.readRawVarint32();
int oldLimit = codedIS.pushLimit(length); int oldLimit = codedIS.pushLimit(length);
cities.add(readCity(null, offset, false)); if(nameContains != null){
String name = null;
int read = 0;
int toRead = useEn ? 3 : 2;
int seek = codedIS.getTotalBytesRead();
while(read++ < toRead){
int ts = codedIS.readTag();
int tags = WireFormat.getTagFieldNumber(ts);
switch (tags) {
case OsmandOdb.CityIndex.NAME_EN_FIELD_NUMBER :
name = codedIS.readString();
break;
case OsmandOdb.CityIndex.NAME_FIELD_NUMBER :
name = codedIS.readString();
if(useEn){
name = Junidecode.unidecode(name);
}
break;
case OsmandOdb.CityIndex.CITY_TYPE_FIELD_NUMBER :
codedIS.readUInt32();
break;
}
}
if(name == null || !name.toLowerCase().contains(nameContains)){
codedIS.skipRawBytes(codedIS.getBytesUntilLimit());
codedIS.popLimit(oldLimit);
break;
}
codedIS.seek(seek);
}
City c = readCity(null, offset, false);
if(c != null){
cities.add(c);
}
codedIS.popLimit(oldLimit); codedIS.popLimit(oldLimit);
break; break;
default: default:
@ -453,7 +494,7 @@ public class BinaryMapIndexReader {
return p; return p;
case OsmandOdb.PostcodeIndex.POSTCODE_FIELD_NUMBER : case OsmandOdb.PostcodeIndex.POSTCODE_FIELD_NUMBER :
String name = codedIS.readString(); String name = codedIS.readString();
if(postcodeFilter != null && postcodeFilter.equalsIgnoreCase(name)){ if(postcodeFilter != null && !postcodeFilter.equalsIgnoreCase(name)){
codedIS.skipRawBytes(codedIS.getBytesUntilLimit()); codedIS.skipRawBytes(codedIS.getBytesUntilLimit());
return null; return null;
} }
@ -515,6 +556,9 @@ public class BinaryMapIndexReader {
break; break;
case OsmandOdb.CityIndex.NAME_FIELD_NUMBER : case OsmandOdb.CityIndex.NAME_FIELD_NUMBER :
c.setName(codedIS.readString()); c.setName(codedIS.readString());
if(c.getEnName() == null){
c.setEnName(Junidecode.unidecode(c.getName()));
}
break; break;
case OsmandOdb.CityIndex.X_FIELD_NUMBER : case OsmandOdb.CityIndex.X_FIELD_NUMBER :
x = codedIS.readFixed32(); x = codedIS.readFixed32();
@ -564,6 +608,9 @@ public class BinaryMapIndexReader {
break; break;
case OsmandOdb.StreetIndex.NAME_FIELD_NUMBER : case OsmandOdb.StreetIndex.NAME_FIELD_NUMBER :
s.setName(codedIS.readString()); s.setName(codedIS.readString());
if(s.getEnName() == null){
s.setEnName(Junidecode.unidecode(s.getName()));
}
break; break;
case OsmandOdb.StreetIndex.X_FIELD_NUMBER : case OsmandOdb.StreetIndex.X_FIELD_NUMBER :
int sx = codedIS.readSInt32(); int sx = codedIS.readSInt32();
@ -622,6 +669,9 @@ public class BinaryMapIndexReader {
break; break;
case OsmandOdb.BuildingIndex.NAME_FIELD_NUMBER : case OsmandOdb.BuildingIndex.NAME_FIELD_NUMBER :
b.setName(codedIS.readString()); b.setName(codedIS.readString());
if(b.getEnName() == null){
b.setEnName(Junidecode.unidecode(b.getName()));
}
break; break;
case OsmandOdb.BuildingIndex.X_FIELD_NUMBER : case OsmandOdb.BuildingIndex.X_FIELD_NUMBER :
x = codedIS.readSInt32() + street24X; x = codedIS.readSInt32() + street24X;
@ -1008,8 +1058,8 @@ public class BinaryMapIndexReader {
} }
public static void main(String[] args) throws IOException { public static void main(String[] args) throws IOException {
RandomAccessFile raf = new RandomAccessFile(new File("e:\\Information\\OSM maps\\osmand\\Minsk.map.pbf"), "r"); // RandomAccessFile raf = new RandomAccessFile(new File("e:\\Information\\OSM maps\\osmand\\Minsk.map.pbf"), "r");
// RandomAccessFile raf = new RandomAccessFile(new File("e:\\Information\\OSM maps\\osmand\\Belarus.map.pbf"), "r"); RandomAccessFile raf = new RandomAccessFile(new File("e:\\Information\\OSM maps\\osmand\\Belarus.map.pbf"), "r");
BinaryMapIndexReader reader = new BinaryMapIndexReader(raf); BinaryMapIndexReader reader = new BinaryMapIndexReader(raf);
System.out.println("VERSION " + reader.getVersion()); System.out.println("VERSION " + reader.getVersion());
@ -1030,22 +1080,25 @@ public class BinaryMapIndexReader {
String reg = reader.getRegionNames().get(0); String reg = reader.getRegionNames().get(0);
long time = System.currentTimeMillis(); long time = System.currentTimeMillis();
List<City> cs = reader.getCities(reg); List<City> cs = reader.getCities(reg);
for(City c : cs){ // for(City c : cs){
reader.preloadStreets(c); // reader.preloadStreets(c);
int buildings = 0; // int buildings = 0;
for(Street s : c.getStreets()){ // for(Street s : c.getStreets()){
reader.preloadBuildings(s); // reader.preloadBuildings(s);
buildings += s.getBuildings().size(); // buildings += s.getBuildings().size();
} // }
System.out.println(c.getName() + " " + c.getLocation() + " " + c.getStreets().size() + " " + buildings); // System.out.println(c.getName() + " " + c.getLocation() + " " + c.getStreets().size() + " " + buildings);
} // }
List<City> villages = reader.getVillages(reg); // List<PostCode> postcodes = reader.getPostcodes(reg);
List<PostCode> postcodes = reader.getPostcodes(reg); // for(PostCode c : postcodes){
for(PostCode c : postcodes){ // reader.preloadStreets(c);
reader.preloadStreets(c); //// System.out.println(c.getName());
// System.out.println(c.getName()); // }
} System.out.println(Runtime.getRuntime().totalMemory() - Runtime.getRuntime().freeMemory());
List<City> villages = reader.getVillages(reg, "кост", false);
System.out.println("Villages " + villages.size()); System.out.println("Villages " + villages.size());
System.out.println(Runtime.getRuntime().totalMemory() - Runtime.getRuntime().freeMemory());
System.out.println("Time " + (System.currentTimeMillis() - time)); System.out.println("Time " + (System.currentTimeMillis() - time));
} }

View file

@ -86,7 +86,9 @@ public class City extends MapObject {
} else { } else {
// try to merge streets // try to merge streets
Street prev = streets.get(name); Street prev = streets.get(name);
if(!street.getWayNodes().isEmpty()){
prev.getWayNodes().addAll(street.getWayNodes()); prev.getWayNodes().addAll(street.getWayNodes());
}
prev.getBuildings().addAll(street.getBuildings()); prev.getBuildings().addAll(street.getBuildings());
return prev; return prev;
} }

View file

@ -95,6 +95,9 @@ public class Street extends MapObject {
public List<Way> getWayNodes() { public List<Way> getWayNodes() {
if(wayNodes == null){
wayNodes = new ArrayList<Way>();
}
return wayNodes; return wayNodes;
} }

View file

@ -3,7 +3,6 @@ package net.osmand;
import java.io.IOException; import java.io.IOException;
import java.text.Collator; import java.text.Collator;
import java.util.Collection; import java.util.Collection;
import java.util.Collections;
import java.util.Comparator; import java.util.Comparator;
import java.util.LinkedHashMap; import java.util.LinkedHashMap;
import java.util.List; import java.util.List;
@ -32,9 +31,6 @@ public class RegionAddressRepositoryBinary implements RegionAddressRepository {
private Map<String, PostCode> postCodes = new TreeMap<String, PostCode>(Collator.getInstance()); private Map<String, PostCode> postCodes = new TreeMap<String, PostCode>(Collator.getInstance());
private boolean useEnglishNames = false; private boolean useEnglishNames = false;
private Comparator<MapObject> comparator = new MapObjectComparator(useEnglishNames);
public RegionAddressRepositoryBinary(BinaryMapIndexReader file, String name) { public RegionAddressRepositoryBinary(BinaryMapIndexReader file, String name) {
this.file = file; this.file = file;
this.region = name; this.region = name;
@ -68,13 +64,13 @@ public class RegionAddressRepositoryBinary implements RegionAddressRepository {
buildingsToFill.add(building); buildingsToFill.add(building);
} }
} }
Collections.sort(buildingsToFill, comparator);
} }
private void preloadBuildings(Street street) { private void preloadBuildings(Street street) {
if(street.getBuildings().isEmpty()){ if(street.getBuildings().isEmpty()){
try { try {
file.preloadBuildings(street); file.preloadBuildings(street);
street.sortBuildings();
} catch (IOException e) { } catch (IOException e) {
log.error("Disk operation failed" , e); //$NON-NLS-1$ log.error("Disk operation failed" , e); //$NON-NLS-1$
} }
@ -87,10 +83,13 @@ public class RegionAddressRepositoryBinary implements RegionAddressRepository {
assert o instanceof PostCode || o instanceof City; assert o instanceof PostCode || o instanceof City;
City city = (City) (o instanceof City ? o : null); City city = (City) (o instanceof City ? o : null);
PostCode post = (PostCode) (o instanceof PostCode ? o : null); PostCode post = (PostCode) (o instanceof PostCode ? o : null);
preloadStreets(o);
name = name.toLowerCase(); name = name.toLowerCase();
Collection<Street> streets = post == null ? city.getStreets() : post.getStreets() ; Collection<Street> streets = post == null ? city.getStreets() : post.getStreets() ;
if(streets.isEmpty()){
preloadStreets(o);
streets = post == null ? city.getStreets() : post.getStreets();
}
if(name.length() == 0){ if(name.length() == 0){
streetsToFill.addAll(streets); streetsToFill.addAll(streets);
@ -107,7 +106,7 @@ public class RegionAddressRepositoryBinary implements RegionAddressRepository {
} }
} }
} }
Collections.sort(streetsToFill, comparator);
} }
@ -175,13 +174,12 @@ public class RegionAddressRepositoryBinary implements RegionAddressRepository {
} }
int initialsize = citiesToFill.size(); int initialsize = citiesToFill.size();
for(City c : file.getVillages(name)){ for(City c : file.getVillages(region, name, useEnglishNames )){
String cName = useEnglishNames ? c.getEnName() : c.getName(); String cName = c.getName(useEnglishNames).toLowerCase();
String lowerCase = cName.toLowerCase(); if (cName.startsWith(name)) {
if (lowerCase.startsWith(name)) {
citiesToFill.add(ind, c); citiesToFill.add(ind, c);
ind++; ind++;
} else if (lowerCase.contains(name)) { } else if (cName.contains(name)) {
citiesToFill.add(c); citiesToFill.add(c);
} }
} }
@ -275,9 +273,12 @@ public class RegionAddressRepositoryBinary implements RegionAddressRepository {
assert o instanceof PostCode || o instanceof City; assert o instanceof PostCode || o instanceof City;
City city = (City) (o instanceof City ? o : null); City city = (City) (o instanceof City ? o : null);
PostCode post = (PostCode) (o instanceof PostCode ? o : null); PostCode post = (PostCode) (o instanceof PostCode ? o : null);
preloadStreets(o);
name = name.toLowerCase(); name = name.toLowerCase();
Collection<Street> streets = post == null ? city.getStreets() : post.getStreets(); Collection<Street> streets = post == null ? city.getStreets() : post.getStreets();
if(streets.isEmpty()){
preloadStreets(o);
streets = post == null ? city.getStreets() : post.getStreets();
}
for (Street s : streets) { for (Street s : streets) {
String sName = useEnglishNames ? s.getEnName() : s.getName(); String sName = useEnglishNames ? s.getEnName() : s.getName();
String lowerCase = sName.toLowerCase(); String lowerCase = sName.toLowerCase();
@ -293,7 +294,6 @@ public class RegionAddressRepositoryBinary implements RegionAddressRepository {
@Override @Override
public void setUseEnglishNames(boolean useEnglishNames) { public void setUseEnglishNames(boolean useEnglishNames) {
this.useEnglishNames = useEnglishNames; this.useEnglishNames = useEnglishNames;
this.comparator = new MapObjectComparator(useEnglishNames);
} }
@Override @Override