001: /*
002: * GeoTools - OpenSource mapping toolkit
003: * http://geotools.org
004: * (C) 2002-2006, GeoTools Project Managment Committee (PMC)
005: *
006: * This library is free software; you can redistribute it and/or
007: * modify it under the terms of the GNU Lesser General Public
008: * License as published by the Free Software Foundation;
009: * version 2.1 of the License.
010: *
011: * This library is distributed in the hope that it will be useful,
012: * but WITHOUT ANY WARRANTY; without even the implied warranty of
013: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
014: * Lesser General Public License for more details.
015: */
016: package org.geotools.caching;
017:
018: import com.vividsolutions.jts.geom.Coordinate;
019: import com.vividsolutions.jts.geom.Envelope;
020:
021: import junit.framework.Test;
022: import junit.framework.TestCase;
023: import junit.framework.TestSuite;
024:
025: import org.geotools.caching.Generator;
026: import org.geotools.caching.impl.InMemoryDataCache;
027: import org.geotools.caching.impl.SpatialQueryTracker;
028:
029: import org.geotools.data.DataStore;
030: import org.geotools.data.FeatureLocking;
031: import org.geotools.data.Query;
032: import org.geotools.data.memory.MemoryDataStore;
033: import org.geotools.data.shapefile.ShapefileDataStore;
034:
035: import org.geotools.feature.DefaultFeatureCollection;
036: import org.geotools.feature.FeatureCollection;
037: import org.geotools.feature.FeatureIterator;
038: import org.geotools.feature.FeatureType;
039: import org.geotools.feature.SchemaException;
040:
041: import org.geotools.filter.spatial.BBOXImpl;
042:
043: import java.io.File;
044: import java.io.IOException;
045:
046: import java.net.MalformedURLException;
047: import java.net.URI;
048: import java.net.URL;
049:
050: import java.util.ArrayList;
051: import java.util.Collection;
052: import java.util.Iterator;
053: import java.util.List;
054: import java.util.TreeSet;
055:
056: public class CacheTest extends TestCase {
057: private final static short UNCHANGED = 0;
058: private final static short OPTIMIZED = 1;
059: private final static short EMPTYQUERY = 2;
060: private final List querySet = new ArrayList();
061: private Collection data = null;
062: private FeatureType type = null;
063:
064: private void createQuerySet(int numberOfQueries) {
065: System.out.println("=== Creating Query Set");
066:
067: Coordinate p = Generator.pickRandomPoint(new Coordinate(500,
068: 500), 950, 950);
069: Coordinate last = p;
070:
071: for (int i = 0; i < numberOfQueries; i++) {
072: querySet.add(Generator.createBboxQuery(p, 100, 100));
073: p = Generator.pickRandomPoint(p, 50, 50);
074: querySet.add(Generator.createBboxQuery(p, 50, 50));
075: p = Generator.pickRandomPoint(p, 20, 20);
076: querySet.add(Generator.createBboxQuery(p, 20, 20));
077:
078: Coordinate temp = p;
079: p = last;
080: last = temp;
081: }
082: }
083:
084: private void createRandomQuerySet(int numberOfQueries) {
085: System.out.println("=== Creating Query Set");
086:
087: for (int i = 0; i < numberOfQueries; i++) {
088: Coordinate p = Generator.pickRandomPoint(new Coordinate(
089: 500, 500), 950, 950);
090: querySet.add(Generator.createBboxQuery(p, 10, 10));
091: }
092: }
093:
094: private List createDataSet(int numberOfData) {
095: System.out.println("=== Creating Data Set");
096:
097: Generator gen = new Generator(1000, 1000);
098: type = gen.getFeatureType();
099:
100: List ret = new ArrayList();
101:
102: for (int i = 0; i < numberOfData; i++) {
103: ret.add(gen.createFeature(i));
104: }
105:
106: return ret;
107: }
108:
109: protected void setUp() throws Exception {
110: super .setUp();
111: data = createDataSet(2000);
112: }
113:
114: public static Test suite() {
115: return new TestSuite(CacheTest.class);
116: }
117:
118: public void ztestShapefileStore() throws IOException,
119: MalformedURLException {
120: File f = new File("target/test.shp");
121: ShapefileDataStore sds = new ShapefileDataStore(f.toURL(), URI
122: .create("testStore"));
123:
124: if (!f.exists()) {
125: sds.createSchema(type);
126:
127: if (sds.getFeatureSource() instanceof FeatureLocking) {
128: FeatureLocking fl = (FeatureLocking) sds
129: .getFeatureSource();
130: FeatureCollection col = new DefaultFeatureCollection(
131: "testStore", type);
132: col.addAll(data);
133: fl.addFeatures(col);
134: }
135: } else {
136: if (sds.getSchema().equals(type)) {
137: System.out.println("Schema ok");
138: } else {
139: System.out.println(sds.getSchema());
140: System.out.println(type);
141: }
142: }
143: }
144:
145: public void testTracker() {
146: createQuerySet(50);
147:
148: SpatialQueryTracker tracker = new SpatialQueryTracker();
149: int unchanged = 0;
150: int optimized = 0;
151: int empty = 0;
152:
153: for (Iterator i = querySet.iterator(); i.hasNext();) {
154: Query q = (Query) i.next();
155: Query m = tracker.match(q);
156: short comp = compareQuery(q, m);
157:
158: //String msg = "" ;
159: if (comp == UNCHANGED) {
160: //msg = "Unchanged" ;
161: unchanged++;
162: } else if (comp == OPTIMIZED) {
163: //msg = "Optimized" ;
164: optimized++;
165: } else if (comp == EMPTYQUERY) {
166: //msg = "" ;
167: empty++;
168: }
169:
170: //System.out.println(msg) ;
171: tracker.register(m);
172: }
173:
174: System.out.println("Unchanged=" + unchanged + ", Optimized="
175: + optimized + ", Empty=" + empty);
176: assertTrue(unchanged > 0);
177: assertTrue(optimized > 0);
178: assertTrue(empty > ((2 / 3) * querySet.size()));
179:
180: Query control = (Query) querySet.get(0);
181: Query m = tracker.match(control);
182: assertTrue(compareQuery(control, m) == EMPTYQUERY);
183: //Query q = Generator.createBboxQuery(new Coordinate(500,500), 10000, 10000) ;
184: tracker.unregister(control);
185: m = tracker.match(control);
186: assertTrue(compareQuery(control, m) == UNCHANGED);
187: //System.out.println("Clear index");
188: tracker.register(m);
189: m = tracker.match(control);
190: assertTrue(compareQuery(control, m) == EMPTYQUERY);
191: tracker.clear();
192: m = tracker.match(control);
193: assertTrue(compareQuery(control, m) == UNCHANGED);
194: }
195:
196: public void testDataCacheConformance() throws IOException,
197: SchemaException {
198: createRandomQuerySet(50);
199:
200: MemoryDataStore control = new MemoryDataStore();
201: control.createSchema(type);
202: control.addFeatures(data);
203:
204: MemoryDataStore ds = new MemoryDataStore();
205: ds.createSchema(type);
206: ds.addFeatures(data);
207:
208: InMemoryDataCache tested = new InMemoryDataCache(ds);
209: Iterator iter = querySet.iterator();
210:
211: while (iter.hasNext()) {
212: Query q = (Query) iter.next();
213: FeatureCollection controlSet = control.getView(q)
214: .getFeatures();
215: FeatureCollection testedSet = tested.getView(q)
216: .getFeatures();
217: assertTrue(compareFeatureCollectionByHash(controlSet,
218: testedSet));
219: }
220: }
221:
222: public void testDataCachePerformance() throws IOException {
223: createQuerySet(25);
224:
225: MemoryDataStore control = new MemoryDataStore();
226: control.createSchema(type);
227: control.addFeatures(data);
228:
229: MemoryDataStore ds = new MemoryDataStore();
230: ds.createSchema(type);
231: ds.addFeatures(data);
232:
233: InMemoryDataCache tested = new InMemoryDataCache(ds);
234: long diff = compareDataStores(tested, control, querySet);
235: assertTrue(diff < 0);
236: }
237:
238: public void testDataCachePerformanceRandomQueries()
239: throws IOException {
240: createRandomQuerySet(50);
241:
242: MemoryDataStore control = new MemoryDataStore();
243: control.createSchema(type);
244: control.addFeatures(data);
245:
246: MemoryDataStore ds = new MemoryDataStore();
247: ds.createSchema(type);
248: ds.addFeatures(data);
249:
250: InMemoryDataCache tested = new InMemoryDataCache(ds);
251: long diff = compareDataStores(tested, control, querySet);
252: }
253:
254: private short compareQuery(Query q1, Query q2) {
255: if (q1.equals(q2)) {
256: return UNCHANGED;
257: }
258:
259: if ((q1.getFilter() instanceof BBOXImpl)
260: && (q2.getFilter() instanceof BBOXImpl)) {
261: BBOXImpl bb = (BBOXImpl) q1.getFilter();
262: Envelope env1 = new Envelope(bb.getMinX(), bb.getMaxX(), bb
263: .getMinY(), bb.getMaxY());
264: bb = (BBOXImpl) q2.getFilter();
265:
266: Envelope env2 = new Envelope(bb.getMinX(), bb.getMaxX(), bb
267: .getMinY(), bb.getMaxY());
268:
269: if (env1.equals(env2)) {
270: return UNCHANGED;
271: } else {
272: return OPTIMIZED;
273: }
274: } else {
275: return EMPTYQUERY;
276: }
277: }
278:
279: private static QueryStatistics[] runQueries(DataStore ds,
280: List querySet) {
281: QueryStatistics[] stats = new QueryStatistics[querySet.size()];
282: Iterator iter = querySet.iterator();
283: int i = 0;
284:
285: while (iter.hasNext()) {
286: Query q = (Query) iter.next();
287: stats[i] = new QueryStatistics();
288:
289: try {
290: long startTime = System.currentTimeMillis();
291:
292: //System.out.print(".") ;
293: FeatureCollection resultSet = ds.getView(q)
294: .getFeatures();
295: FeatureIterator fiter = resultSet.features();
296:
297: while (fiter.hasNext()) {
298: fiter.next();
299: }
300:
301: resultSet.close(fiter);
302:
303: long endTime = System.currentTimeMillis();
304: stats[i].setNumberOfFeatures(resultSet.size());
305: stats[i].setExecutionTime(endTime - startTime);
306: } catch (IOException e) {
307: // TODO Auto-generated catch block
308: e.printStackTrace();
309: } catch (SchemaException e) {
310: // TODO Auto-generated catch block
311: e.printStackTrace();
312: }
313:
314: i++;
315: }
316:
317: return stats;
318: }
319:
320: protected static long compareDataStores(DataStore ds,
321: DataStore control, List querySet) {
322: QueryStatistics[] ds_stats = runQueries(ds, querySet);
323: QueryStatistics[] control_stats = runQueries(control, querySet);
324: long meanDifference = 0;
325: long meanOverhead = 0;
326: int overheadCount = 0;
327: long meanLeverage = 0;
328: int leverageCount = 0;
329:
330: for (int i = 0; i < querySet.size(); i++) {
331: if (i > 1) {
332: long diff = ds_stats[i].getExecutionTime()
333: - control_stats[i].getExecutionTime();
334: meanDifference += diff;
335:
336: if (diff > 0) {
337: overheadCount++;
338: meanOverhead += diff;
339: } else {
340: leverageCount++;
341: meanLeverage += diff;
342: }
343: }
344:
345: //System.out.println("Test: " + ds_stats[i].getNumberOfFeatures() + " features ; " + ds_stats[i].getExecutionTime() + " ms ; " +
346: // "Control: " + control_stats[i].getNumberOfFeatures() + " features ; " + control_stats[i].getExecutionTime() + " ms ; ");
347: }
348:
349: meanDifference = ((querySet.size() - 2) > 0) ? (meanDifference / (querySet
350: .size() - 2))
351: : 0;
352: meanOverhead = (overheadCount > 0) ? (meanOverhead / overheadCount)
353: : 0;
354: meanLeverage = (leverageCount > 0) ? (meanLeverage / leverageCount)
355: : 0;
356: System.out.println("Mean execution time difference = "
357: + meanDifference + " ms.");
358: System.out
359: .println("Mean overhead = "
360: + meanOverhead
361: + " ms. ("
362: + ((100 * overheadCount) / (overheadCount + leverageCount))
363: + " %)");
364: System.out
365: .println("Mean leverage = "
366: + meanLeverage
367: + " ms. ("
368: + ((100 * leverageCount) / (overheadCount + leverageCount))
369: + " %)");
370:
371: return meanDifference;
372: }
373:
374: protected static boolean compareFeatureCollectionByID(
375: FeatureCollection set1, FeatureCollection set2) {
376: if (set1.size() == set2.size()) {
377: FeatureIterator iter = set1.features();
378: TreeSet ids1 = new TreeSet();
379:
380: while (iter.hasNext()) {
381: ids1.add(iter.next().getID());
382: }
383:
384: set1.close(iter);
385: iter = set2.features();
386:
387: TreeSet ids2 = new TreeSet();
388:
389: while (iter.hasNext()) {
390: ids2.add(iter.next().getID());
391: }
392:
393: set2.close(iter);
394:
395: Iterator i2 = ids2.iterator();
396:
397: for (Iterator i1 = ids1.iterator(); i1.hasNext();) {
398: String id1 = (String) i1.next();
399: String id2 = (String) i2.next();
400:
401: if (!id1.equals(id2)) {
402: return false;
403: }
404: }
405:
406: return true;
407: }
408:
409: return false;
410: }
411:
412: protected static boolean compareFeatureCollectionByHash(
413: FeatureCollection set1, FeatureCollection set2) {
414: if (set1.size() == set2.size()) {
415: FeatureIterator iter = set1.features();
416: TreeSet ids1 = new TreeSet();
417:
418: while (iter.hasNext()) {
419: ids1.add(new Integer(iter.next().hashCode()));
420: }
421:
422: set1.close(iter);
423: iter = set2.features();
424:
425: TreeSet ids2 = new TreeSet();
426:
427: while (iter.hasNext()) {
428: ids2.add(new Integer(iter.next().hashCode()));
429: }
430:
431: set2.close(iter);
432:
433: Iterator i2 = ids2.iterator();
434:
435: for (Iterator i1 = ids1.iterator(); i1.hasNext();) {
436: Integer id1 = (Integer) i1.next();
437: Integer id2 = (Integer) i2.next();
438:
439: if (!id1.equals(id2)) {
440: return false;
441: }
442: }
443:
444: return true;
445: }
446:
447: return false;
448: }
449: }
|