One of the interesting things Andrea contributed to this conversation was 
benchmarks.

The conversation goes outside of the SimpleFeatureCollection proposal and 
should involve Ben and anyone interested in rendering a generic 
FeatureCollection.

Andrea since it is clear that there is a performance difference between 
SimpleFeature and Feature (and that the renderer is *not* the place to pay a 
performance difference!) how should we go about rendering generic feature 
content?

The obvious one for me is to perform an instance of check (once 
SimpleFeatureCollection is introduced); making sure to perform the instanceof 
check outside of any FeatureIterator loop.

The same solution can be done with a visitor - break out a FeatureVisitor and 
SimpleFeatureVisitor and perform the check once in the feature collection 
accepts method; the renderer is still on the hook however for implementing the 
inside of the loop twice in order to take advantage of any performance 
differences :-(

Is there another way we could do this one?
Jody

>> It is not really an issue until we get more generic feature collections; 
>> there is a small number of places where SimpleFeature was assumed in the 
>> rendering code.
>> With respect to performance I think that if SimpleFeatures are passed in the 
>> performance will be the same?
> 
> Performance will definitely not be the same.
> SimpleFeatureImpl.getAttribute(name) returns the actual value,
> Feature.getProperty(name) returns a "Property" object, a
> wrapper around the value which has to be built.
> The SLD handling code uses property
> accessors, which are slower than direct access but make the code
> portable.
> 
> I made a little benchmark for different property access styles
> (attached):
> - using the simple feature getAttribute()
> - using Feature getProperty().getValue()
> - dynamically looking up property accessors
> - caching property accessors
> 
> The timings on Java 6 are:
> 
> Building features...
> Building features: 2.759
> Testing SimpleFeature access...
> Direct access: 0.081
> Testing Feature access...
> Feature access: 0.468
> Testing property accessors...
> Property accessors: 2.438
> Testing cached accessors...
> Cached property accessors: 0.105
> 
> As you can see using Feature is 8 times slower,
> and using dynamically found accessors takes as much time
> as actually building the features.
> The only way to get decent performance is to use
> accessors and reuse them.
> I can have a look into doing that.
> 
> Btw, a curiosity: in this test the difference between
> Java 5 and Java 6 is massive. Look at the results
> with Java 1.5.0_22:
> 
> Building features...
> Building features: 18.702
> Testing SimpleFeature access...
> Direct access: 0.085
> Testing Feature access...
> Feature access: 0.474
> Testing property accessors...
> Property accessors: 1.898
> Testing cached accessors...
> Cached property accessors: 0.141
> 
> With a Java 7 recent build the results are actually odd
> in another way:
> 
> Building features...
> Building features: 2.131
> Testing SimpleFeature access...
> Direct access: 0.138
> Testing Feature access...
> Feature access: 1.008
> Testing property accessors...
> Property accessors: 1.524
> Testing cached accessors...
> Cached property accessors: 0.091
> 
> As you can see... cached property accessors are fast than direct
> access??? :-) And Feature access is actually twice as slow as Java 6,
> ugh. Not sure what to make of the Java 7 numbers, but it's also
> just a preview build.
> 
> 
>>> To sum up, maybe clean up a little the proposal. I feel good about the 
>>> change, I should just get some time to actually try to apply the patch
>>> (will try to do that soon)
>> Thanks Andrea; I would like the feedback of yourself and Micheal if possible.
> 
> Basic feedback is that I prefer to have everything happen on trunk only.
> This will make for a few months of hard to port forward patches btw...
> probably late July would have been a better time for this patch.
> However I also understand that if we delay you'll have to start over.
> 
> Cheers
> Andrea
> 
> -- 
> Andrea Aime
> OpenGeo - http://opengeo.org
> Expert service straight from the developers.
> import java.util.ArrayList;
> import java.util.List;
> 
> import org.geotools.feature.simple.SimpleFeatureBuilder;
> import org.geotools.feature.simple.SimpleFeatureTypeBuilder;
> import org.geotools.filter.expression.PropertyAccessor;
> import org.geotools.filter.expression.PropertyAccessors;
> import org.opengis.feature.Feature;
> import org.opengis.feature.simple.SimpleFeature;
> import org.opengis.feature.simple.SimpleFeatureType;
> 
> import com.vividsolutions.jts.geom.Polygon;
> import com.vividsolutions.jts.io.WKTReader;
> 
> 
> public class PropertyAccessTest {
> 
>    public static void main(String[] args) throws Exception {
>        SimpleFeatureTypeBuilder ftb = new SimpleFeatureTypeBuilder();
>        ftb.add("geom", Polygon.class, "EPSG:4326");
>        ftb.add("name", String.class);
>        ftb.add("persons", Long.class);
>        ftb.setName("testFeature");
>        SimpleFeatureType ft = ftb.buildFeatureType();
> 
>        // building features
>        System.out.println("Building features...");
>        long start = System.currentTimeMillis();
>        List features = new ArrayList();
>        SimpleFeatureBuilder fb = new SimpleFeatureBuilder(ft);
>        Polygon geom = (Polygon) new WKTReader().read("POLYGON((0 0, 0 10, 10 
> 10, 10 0, 0 0))");
>        for (int i = 0; i < 1000000; i++) {
>            fb.add(geom);
>            fb.add("feature" + i);
>            fb.add(i);
>            features.add(fb.buildFeature(null));
>        }
>        long end = System.currentTimeMillis();
>        System.out.println("Building features: " + (end - start) / 1000.0);
> 
>        System.out.println("Testing SimpleFeature access...");
>        start = System.currentTimeMillis();
>        testDirectAccess(features);
>        end = System.currentTimeMillis();
>        System.out.println("Direct access: " + (end - start) / 1000.0);
> 
>        System.out.println("Testing Feature access...");
>        start = System.currentTimeMillis();
>        testFeatureAccess(features);
>        end = System.currentTimeMillis();
>        System.out.println("Feature access: " + (end - start) / 1000.0);
> 
>        System.out.println("Testing property accessors...");
>        start = System.currentTimeMillis();
>        testAccessors(features);
>        end = System.currentTimeMillis();
>        System.out.println("Property accessors: " + (end - start) / 1000.0);
> 
>        System.out.println("Testing cached accessors...");
>        start = System.currentTimeMillis();
>        testCachedAccessors(features);
>        end = System.currentTimeMillis();
>        System.out.println("Cached property accessors: " + (end - start) / 
> 1000.0);
>    }
> 
>    private static void testFeatureAccess(List<Feature> features) {
>        for (Feature feature : features) {
>            feature.getProperty("geom").getValue();
>            feature.getProperty("name").getValue();
>            feature.getProperty("persons").getValue();
>        }
>    }
> 
>    private static void testDirectAccess(List<SimpleFeature> features) {
>        for (SimpleFeature feature : features) {
>            feature.getAttribute("geom");
>            feature.getAttribute("name");
>            feature.getAttribute("persons");
>        }
>    }
> 
>    private static void testAccessors(List features) {
>        for (Object feature : features) {
>            PropertyAccessors.findPropertyAccessor(feature, "geom", 
> Polygon.class, null).get(feature, "geom", Polygon.class);
>            PropertyAccessors.findPropertyAccessor(feature, "name", 
> String.class, null).get(feature, "geom", String.class);
>            PropertyAccessors.findPropertyAccessor(feature, "persons", 
> Integer.class, null).get(feature, "geom", Integer.class);
>        }
>    }
> 
>    private static void testCachedAccessors(List features) {
>        PropertyAccessor geomAccessor = 
> PropertyAccessors.findPropertyAccessor(features.get(0), "geom", 
> Polygon.class, null);
>        PropertyAccessor nameAccessor = 
> PropertyAccessors.findPropertyAccessor(features.get(0), "name", String.class, 
> null);
>        PropertyAccessor personsAccessor = 
> PropertyAccessors.findPropertyAccessor(features.get(0), "persons", 
> Integer.class, null);
>        for (Object feature : features) {
>            geomAccessor.get(feature, "geom", Polygon.class);
>            nameAccessor.get(feature, "geom", String.class);
>            personsAccessor.get(feature, "geom", Integer.class);
>        }
>    }
> }


------------------------------------------------------------------------------
_______________________________________________
Geotools-devel mailing list
Geotools-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/geotools-devel

Reply via email to