GeoHazardWatch

Page Actions


Performance Optimization

This page documents GeoHazardWatch's performance characteristics, known bottlenecks, and optimization strategies.

Server Startup Performance

Server startup time is critical for developer experience and production deployments. The following optimizations have been implemented.

Baseline Measurements

Initial testing with ~2,800 pages revealed significant startup delays:

MetricBeforeAfterImprovement
Total startup time48+ seconds~3 seconds16x faster
Link graph build54 seconds0.15 seconds360x faster
Page count2,8343,225(more pages, faster startup)

Root Causes Identified

Triple Page Scan on Startup

All pages were read from disk three separate times during initialization:

PassComponentPurposeOriginal Time
1FileSystemProvider.refreshPageList()Build page cache~0.4s
2LunrSearchProvider.buildIndex()Build search index~1.5s
3RenderingManager.buildLinkGraph()Build link graph~41s

RenderingManager.buildLinkGraph() exhibited quadratic complexity:

  • Read all pages sequentially with await pageManager.getPage()
  • For each page link, called pageNameMatcher.findMatch() with linear search
  • With ~10 links per page average = 28,340 searches × 2,834 iterations

Sequential Async Reads

All three passes used a slow sequential pattern instead of parallel operations.

Benchmark results for different read patterns:

PatternTime (2,834 files)
Sync reads71ms
Parallel async122ms
Sequential async268ms
Sequential + YAML parse411ms

Optimizations Implemented

Content Caching in FileSystemProvider

  • Page content is now cached during refreshPageList()
  • Eliminates 2 of 3 disk passes during startup
  • Files modified: src/providers/FileSystemProvider.ts

PageNameMatcher Index

  • Added buildIndex() method for O(1) lookups instead of O(n)
  • Hash-based index replaces linear search through all page names
  • Files modified: src/utils/PageNameMatcher.ts

Parallel Page Loading

  • RenderingManager.buildLinkGraph() now uses Promise.all() for parallel loading
  • Batch processing instead of sequential await in loops
  • Files modified: src/managers/RenderingManager.ts

Metadata-Only Operations

  • Replaced getPage() with getPageMetadata() where only metadata is needed
  • getPageMetadata() is synchronous and requires no disk I/O
  • Affected files: WikiRoutes.ts, UserManager.ts, ImportManager.ts

Storage Performance

Performance varies significantly based on storage type:

Storage TypePer-file latencyEstimated Startup (3 passes)
Local SSD0.03ms2-3 seconds
NAS (1Gbps)2-5ms30-60 seconds
Cloud (S3)50-100ms10-15 minutes

Content caching is particularly important for NAS and cloud storage where per-file latency is high.

Markup Parser Performance

The markup parser includes built-in performance monitoring for parsing operations.

Configuration Options

{
  "amdwiki": {
    "markup": {
      "performance": {
        "monitoring": true,
        "alertThresholds": {
          "parseTime": 100
        }
      },
      "cache": {
        "metricsEnabled": true
      }
    }
  }
}

Available Metrics

  • Parse time per page
  • Cache hit/miss ratios
  • Alert thresholds for slow operations

Best Practices

  • Use SSD storage for the data directory when possible
  • Avoid network storage for large instances (>1000 pages)
  • Monitor startup time after configuration changes
  • Use getPageMetadata() instead of getPage() when only metadata is needed

Future Optimizations

Potential improvements not yet implemented:

  • Incremental link graph updates instead of full rebuild
  • Startup timing metrics in logs for monitoring

For instances with 10,000+ pages: switch to ElasticsearchSearchProvider — persistent indexing means no cold rebuild on restart, and each page save is a single-document upsert rather than a full in-memory rebuild. See Configuration Properties Reference for the config keys.

See also Configuration for configuration options and System Settings for server settings.

  • GitHub Issue #250 - Original performance analysis

No pages currently refer to this page.

No footnotes on this page.

No comments yet.