第15章 - 性能优化与最佳实践
第15章 - 性能优化与最佳实践
15.1 性能优化概述
15.1.1 性能瓶颈
┌─────────────────────────────────────────────────────────────────────┐
│ 常见性能瓶颈 │
├─────────────────────────────────────────────────────────────────────┤
│ │
│ 数据访问 内存管理 │
│ ├── 数据源连接 ├── 几何对象创建 │
│ ├── 要素迭代 ├── 大集合处理 │
│ └── 属性读取 └── 资源泄漏 │
│ │
│ 空间计算 渲染 │
│ ├── 几何操作 ├── 样式解析 │
│ ├── 坐标转换 ├── 图片生成 │
│ └── 空间索引 └── 文本渲染 │
│ │
└─────────────────────────────────────────────────────────────────────┘
15.2 数据访问优化
15.2.1 使用查询优化
public class QueryOptimization {
// 只获取需要的属性
public static void propertySelection(SimpleFeatureSource source) throws Exception {
Query query = new Query(source.getSchema().getTypeName());
// 不好:获取所有属性
// SimpleFeatureCollection all = source.getFeatures();
// 好:只获取需要的属性
query.setPropertyNames("name", "population");
SimpleFeatureCollection selected = source.getFeatures(query);
}
// 使用分页
public static void paginatedQuery(SimpleFeatureSource source,
int pageSize) throws Exception {
int total = source.getCount(Query.ALL);
for (int offset = 0; offset < total; offset += pageSize) {
Query query = new Query(source.getSchema().getTypeName());
query.setStartIndex(offset);
query.setMaxFeatures(pageSize);
SimpleFeatureCollection page = source.getFeatures(query);
processPage(page);
}
}
// 使用空间过滤器缩小范围
public static void spatialFilter(SimpleFeatureSource source,
Envelope bounds) throws Exception {
FilterFactory2 ff = CommonFactoryFinder.getFilterFactory2();
Filter bboxFilter = ff.bbox(
ff.property("the_geom"),
bounds.getMinX(), bounds.getMinY(),
bounds.getMaxX(), bounds.getMaxY(),
"EPSG:4326"
);
Query query = new Query(source.getSchema().getTypeName(), bboxFilter);
SimpleFeatureCollection filtered = source.getFeatures(query);
}
private static void processPage(SimpleFeatureCollection page) {
// 处理分页数据
}
}
15.2.2 连接池配置
public class ConnectionPoolConfig {
public static DataStore createOptimizedPostGIS() throws Exception {
Map<String, Object> params = new HashMap<>();
// 基本连接
params.put("dbtype", "postgis");
params.put("host", "localhost");
params.put("port", 5432);
params.put("database", "gisdb");
params.put("user", "postgres");
params.put("passwd", "password");
// 连接池优化
params.put("max connections", 20); // 根据并发量调整
params.put("min connections", 5); // 保持最小连接
params.put("connection timeout", 10); // 减少等待时间
params.put("validate connections", true);
params.put("Test while idle", true);
// 查询优化
params.put("fetch size", 1000); // 批量获取
params.put("Loose bbox", true); // 宽松边界框
params.put("preparedStatements", true);// 预编译语句
params.put("encode functions", true); // SQL 函数下推
return DataStoreFinder.getDataStore(params);
}
}
15.3 内存管理
15.3.1 资源释放
public class ResourceManagement {
// 正确的资源释放模式
public static void correctResourceHandling(File file) throws Exception {
FileDataStore store = FileDataStoreFinder.getDataStore(file);
try {
SimpleFeatureSource source = store.getFeatureSource();
SimpleFeatureCollection fc = source.getFeatures();
// 使用 try-with-resources 自动关闭迭代器
try (SimpleFeatureIterator iter = fc.features()) {
while (iter.hasNext()) {
SimpleFeature feature = iter.next();
// 处理要素
}
} // 自动关闭
} finally {
store.dispose(); // 确保释放数据源
}
}
// 使用 FeatureVisitor 避免手动管理迭代器
public static void useVisitor(SimpleFeatureCollection fc) throws Exception {
fc.accepts(new FeatureVisitor() {
@Override
public void visit(Feature feature) {
// 处理要素
}
}, null);
}
}
15.3.2 大数据处理
public class LargeDataHandling {
// 流式处理
public static void streamProcessing(SimpleFeatureSource source,
FeatureProcessor processor) throws Exception {
int pageSize = 1000;
int offset = 0;
boolean hasMore = true;
while (hasMore) {
Query query = new Query(source.getSchema().getTypeName());
query.setStartIndex(offset);
query.setMaxFeatures(pageSize);
SimpleFeatureCollection batch = source.getFeatures(query);
int count = 0;
try (SimpleFeatureIterator iter = batch.features()) {
while (iter.hasNext()) {
processor.process(iter.next());
count++;
}
}
hasMore = count == pageSize;
offset += count;
// 可选:显式触发 GC
// System.gc();
}
}
public interface FeatureProcessor {
void process(SimpleFeature feature);
}
}
15.4 空间索引优化
15.4.1 选择合适的索引
public class SpatialIndexOptimization {
// 构建 STRtree(适合静态数据)
public static STRtree buildSTRtree(SimpleFeatureCollection fc) throws Exception {
STRtree index = new STRtree();
try (SimpleFeatureIterator iter = fc.features()) {
while (iter.hasNext()) {
SimpleFeature feature = iter.next();
Geometry geom = (Geometry) feature.getDefaultGeometry();
index.insert(geom.getEnvelopeInternal(), feature);
}
}
index.build(); // 必须调用
return index;
}
// 构建 Quadtree(适合动态数据)
public static Quadtree buildQuadtree(SimpleFeatureCollection fc) throws Exception {
Quadtree index = new Quadtree();
try (SimpleFeatureIterator iter = fc.features()) {
while (iter.hasNext()) {
SimpleFeature feature = iter.next();
Geometry geom = (Geometry) feature.getDefaultGeometry();
index.insert(geom.getEnvelopeInternal(), feature);
}
}
return index;
}
// 使用索引查询
public static List<SimpleFeature> queryWithIndex(STRtree index,
Geometry queryGeom) {
List<?> candidates = index.query(queryGeom.getEnvelopeInternal());
List<SimpleFeature> result = new ArrayList<>();
for (Object obj : candidates) {
SimpleFeature feature = (SimpleFeature) obj;
Geometry geom = (Geometry) feature.getDefaultGeometry();
// 精确检查
if (queryGeom.intersects(geom)) {
result.add(feature);
}
}
return result;
}
}
15.5 渲染优化
15.5.1 渲染参数调优
public class RenderingOptimization {
public static StreamingRenderer createOptimizedRenderer() {
StreamingRenderer renderer = new StreamingRenderer();
Map<Object, Object> hints = new HashMap<>();
// 优化选项
hints.put(StreamingRenderer.OPTIMIZE_FTS_RENDERING_KEY, Boolean.TRUE);
hints.put(StreamingRenderer.SCALE_COMPUTATION_METHOD_KEY,
StreamingRenderer.SCALE_ACCURATE);
hints.put(StreamingRenderer.LINE_WIDTH_OPTIMIZATION_KEY, Boolean.TRUE);
hints.put(StreamingRenderer.LABEL_CACHE_KEY, new LabelCacheImpl());
// 缓冲区
hints.put(StreamingRenderer.RENDERING_BUFFER, 50);
renderer.setRendererHints(hints);
// Java2D 优化
RenderingHints java2dHints = new RenderingHints(null);
java2dHints.put(RenderingHints.KEY_ANTIALIASING,
RenderingHints.VALUE_ANTIALIAS_OFF); // 关闭抗锯齿提高速度
java2dHints.put(RenderingHints.KEY_RENDERING,
RenderingHints.VALUE_RENDER_SPEED);
renderer.setJava2DHints(java2dHints);
return renderer;
}
}
15.5.2 按比例尺控制
public class ScaleBasedRendering {
public static Style createScaleDependentStyle() {
StyleFactory sf = CommonFactoryFinder.getStyleFactory();
FilterFactory2 ff = CommonFactoryFinder.getFilterFactory2();
// 小比例尺(远视)- 简化符号
Rule smallScaleRule = sf.createRule();
smallScaleRule.setMinScaleDenominator(100000);
smallScaleRule.symbolizers().add(createSimpleSymbol());
// 大比例尺(近视)- 详细符号
Rule largeScaleRule = sf.createRule();
largeScaleRule.setMaxScaleDenominator(100000);
largeScaleRule.symbolizers().add(createDetailedSymbol());
FeatureTypeStyle fts = sf.createFeatureTypeStyle();
fts.rules().add(smallScaleRule);
fts.rules().add(largeScaleRule);
Style style = sf.createStyle();
style.featureTypeStyles().add(fts);
return style;
}
private static Symbolizer createSimpleSymbol() {
// 创建简化符号
return SLD.createPointSymbolizer("circle", Color.RED, 4);
}
private static Symbolizer createDetailedSymbol() {
// 创建详细符号
return SLD.createPointSymbolizer("circle", Color.RED, Color.BLACK, 0.5f, 10);
}
}
15.6 最佳实践
15.6.1 代码模式
public class BestPractices {
// 1. 始终关闭资源
public void properResourceHandling(DataStore store) {
try {
// 使用 store
} finally {
store.dispose();
}
}
// 2. 使用批量操作
public void batchOperations(SimpleFeatureStore store,
List<SimpleFeature> features) throws Exception {
Transaction transaction = new DefaultTransaction("batch");
store.setTransaction(transaction);
try {
int batchSize = 1000;
for (int i = 0; i < features.size(); i += batchSize) {
int end = Math.min(i + batchSize, features.size());
List<SimpleFeature> batch = features.subList(i, end);
DefaultFeatureCollection fc = new DefaultFeatureCollection();
fc.addAll(batch);
store.addFeatures(fc);
transaction.commit();
}
} catch (Exception e) {
transaction.rollback();
throw e;
} finally {
transaction.close();
}
}
// 3. 重用工厂实例
private static final GeometryFactory GEOMETRY_FACTORY =
JTSFactoryFinder.getGeometryFactory();
private static final FilterFactory2 FILTER_FACTORY =
CommonFactoryFinder.getFilterFactory2();
private static final StyleFactory STYLE_FACTORY =
CommonFactoryFinder.getStyleFactory();
// 4. 缓存常用对象
private static final Map<String, CoordinateReferenceSystem> CRS_CACHE =
new ConcurrentHashMap<>();
public CoordinateReferenceSystem getCRS(String code) throws Exception {
return CRS_CACHE.computeIfAbsent(code, k -> {
try {
return CRS.decode(k);
} catch (Exception e) {
throw new RuntimeException(e);
}
});
}
}
15.6.2 性能监控
public class PerformanceMonitoring {
public static void timeOperation(String name, Runnable operation) {
long start = System.currentTimeMillis();
operation.run();
long end = System.currentTimeMillis();
System.out.printf("%s: %d ms%n", name, end - start);
}
public static void memoryUsage() {
Runtime runtime = Runtime.getRuntime();
long total = runtime.totalMemory();
long free = runtime.freeMemory();
long used = total - free;
long max = runtime.maxMemory();
System.out.printf("内存使用: %d MB / %d MB (最大 %d MB)%n",
used / 1024 / 1024,
total / 1024 / 1024,
max / 1024 / 1024);
}
}
15.7 本章小结
本章详细介绍了 GeoTools 的性能优化和最佳实践:
-
数据访问优化
- 属性投影
- 分页查询
- 连接池配置
-
内存管理
- 资源释放
- 流式处理
-
空间索引
- STRtree vs Quadtree
- 索引使用
-
渲染优化
- 渲染参数
- 比例尺控制
-
最佳实践
- 代码模式
- 性能监控
关键要点
- 始终正确关闭资源
- 使用空间索引提高查询效率
- 批量操作减少事务开销
- 重用工厂实例
- 按比例尺调整渲染复杂度

浙公网安备 33010602011771号