Skip to main content

Performance Tuning

Overview

PlantPulse performance improves by eliminating bottlenecks sequentially through each layer: collection → processing → storage. The key is not to blindly increase all values, but to monitor metrics and adjust only the bottleneck in focus.

Three tuning principles

  1. One variable at a time: If you change multiple parameters simultaneously, you cannot tell which change had an effect.
  2. Based on operational data: Make changes in a stage environment after reproducing real traffic.
  3. Keep records: Document changed values and before/after metrics in GitOps or your operations wiki.
EnvironmentCPUMemoryDiskRecommended PIPELINE_THREADSRecommended PIPELINE_RATELIMIT
Development16 vCPU64 GBSSD1610,000 MPS
Standard32 vCPU128 GBNVMe3640,000 MPS
Large scale48+ vCPU200+ GBNVMe64100,000 MPS

Core tuning variables in env.sh

The most frequently adjusted variables in production are managed in the host's bin/env.sh and compose/docker-compose.ymlEnvironment Variable Reference

VariableDefaultImpact
PP_CLUSTER_CORES30Spark / analytics core allocation
PP_CLUSTER_MEMORY_BY_CORE2GSpark executor memory/core
PP_LANG / PP_TZko / Asia/SeoulJVM locale / timezone
JAVA_TOOL_OPTIONSAuto-generatedAutomatically applied to all child JVMs

For detailed variables, see the env.sh variable index in Properties Reference.

Measurement tools

Tools to compare before and after tuning:

cd /opt/kopens/plantpulse-platform/plantpulse-datalake-cli/bin

./status.sh # 모듈별 CPU / 메모리(PSS) 요약
./ops-check.sh # 헬스 + critical log
./memory-check.sh # 모듈별 메모리 상세
./memory-rank.sh # 메모리 순위
./pd node tpstats # Cassandra 스레드풀
./pd node compactionstats # Cassandra 컴팩션
./pd node table-stats # 테이블별 통계
./pd node proxyhistograms # Cassandra 지연 히스토그램

# Kafka consumer lag
./pd node topic

# JVM Heap / GC (컨테이너 진입 후)
./shell.sh
jcmd <pid> GC.heap_info
jcmd <pid> GC.heap_dump /tmp/heap.hprof

For external monitoring (Grafana / Prometheus), see the System Monitoring page.

Note: Optimal tuning values depend on server specifications, data volume, and usage patterns. We recommend starting with the recommended settings below and adjusting gradually while monitoring results.

Engine Pipeline Tuning

Configuration file: plantpulse-server/config/plantpulse-engine.properties

Note: The engine pipeline is the critical path where data collected from sensors is processed. These settings control the processing speed and capacity of data.

Pipeline core parameters

ParameterDefaultDescriptionTuning guide
engine.pipeline.threads36Number of pipeline worker threads70–80% of host cores recommended (example: 48 cores → 36)
engine.pipeline.ratelimit40000Maximum messages per second (MPS)Adjust to match server capacity
engine.pipeline.queue.size1200000Maximum pipeline queue sizeAdjust to available memory
engine.pipeline.queue.o3.delay50Out-of-Order delay handling (ms)Adjust based on network latency
engine.pipeline.task.modeSINGLEPipeline task modeSINGLE or MULTI
engine.async.parallelism256Async parallelism8–16× CPU cores recommended

Streaming configuration

ParameterDefaultDescription
engine.stream.processorDIRECTStream processing mode
engine.streaming.messaging.warning.ms5000Message delay alert threshold (ms)
engine.streaming.messaging.timeout.ms10000Message timeout (ms)
engine.streaming.messaging.timeout.store.typeFILE_QUEUETimeout message storage method
engine.streaming.messaging.timeout.recovery.typeDBTimeout recovery method

Work threads

ParameterDefaultDescription
engine.job.thread.asset8Asset work thread count
engine.job.thread.point8Point work thread count

The table below shows recommended configuration values based on server specifications. Refer to the column matching your production environment.

ItemSmall (8 cores/64GB)Medium (16 cores/128GB)Large (32 cores/256GB)
pipeline.threads163664
pipeline.ratelimit10,00040,000100,000
pipeline.queue.size300,0001,200,0003,000,000
async.parallelism64256512

Cassandra Tuning

Configuration file: plantpulse-storage/db/cassandra/conf/cassandra.yaml

Note: Cassandra is the core database for storing time series data. As data volume grows, Cassandra tuning has an increasing impact on overall performance, so it is recommended to adjust these settings for your production environment.

Memory settings

ParameterDefaultDescription
memtable_heap_space2GiBMemtable heap memory
memtable_offheap_space2GiBMemtable Off-Heap memory
memtable_allocation_typeoffheap_objectsMemory allocation type
memtable_flush_writers8Memtable flush thread count

Concurrency settings

ParameterDefaultDescriptionTuning guide
concurrent_reads256Concurrent read threadsDisk count × 16 recommended
concurrent_writes256Concurrent write threadsCPU cores × 8 recommended
concurrent_counter_writes256Concurrent counter writesSet equal to concurrent_writes
concurrent_compactors8Concurrent compaction threadsCPU core count ÷ 4 recommended

Commit log

ParameterDefaultDescription
commitlog_syncperiodicSync mode
commitlog_sync_period10000msSync period
commitlog_segment_size320MiBSegment size
commitlog_total_space32GiBTotal commit log space

Timeouts

ParameterDefaultDescription
read_request_timeout10000msRead timeout
write_request_timeout60000msWrite timeout
counter_write_request_timeout10000msCounter write timeout
cas_contention_timeout1000msCAS contention timeout
truncate_request_timeout600000msTruncate timeout

Compaction strategy

PlantPulse uses UCS (Unified Compaction Strategy) optimized for time series data characteristics.

Note: Compaction is the process by which Cassandra organizes and merges data files (SSTables) stored on disk. Using an appropriate compaction strategy saves disk space and improves read performance.

storage.properties configuration:

ParameterDefaultDescription
storage.table.compaction.strategyUCSCompaction strategy (UCS or TWCS)
storage.table.compaction.strategy.ucs.scailing_parameterT8Scaling parameter
storage.table.compaction.strategy.ucs.min_sstable_size128MiBMinimum SSTable size
storage.table.compaction.strategy.ucs.target_sstable_size512MiBTarget SSTable size
storage.table.compaction.strategy.ucs.base_shard_count8Base shard count
storage.table.compaction.strategy.ucs.max_sstables_to_compact6Maximum compaction SSTables

Compression

ZStandard dictionary compression is used:

ParameterDefaultDescription
storage.compression.zstd.typeZstdDictionaryCompressorCompression codec
storage.compression.zstd.level3Compression level (1–22; higher = better compression, slower speed)

TTL (Data retention period)

TTL for each table is configured in storage.properties. Data is automatically deleted when TTL expires, so set it according to your data retention requirements.

ParameterDefaultDescription
storage.tag.point.ttl62 (days)Tag point raw data
storage.tag.point.map.ttl1 (days)Tag point map
storage.tag.point.sampling.ttl93 (days)Sampling data
storage.tag.point.snapshot.ttl93 (days)Snapshot data
storage.tag.point.aggregation.ttl93 (days)Aggregate data
storage.tag.point.archive.ttl365 (days)Archive data
storage.tag.blob.ttl93 (days)BLOB data
storage.asset.data.ttl10 (days)Asset data
storage.asset.data.sampling.ttl31 (days)Asset sampling data

Cassandra performance inspection commands

You can check Cassandra performance status using the following commands:

# 컴팩션 상태 확인
/opt/kopens/plantpulse-platform/plantpulse-datalake-cli/bin/pd node compactionstats

# 테이블별 통계 확인
/opt/kopens/plantpulse-platform/plantpulse-datalake-cli/bin/pd node table-stats

# 테이블 히스토그램 (읽기/쓰기 지연)
/opt/kopens/plantpulse-platform/plantpulse-datalake-cli/bin/pd node table-histograms

# SSTable 크기 확인
/opt/kopens/plantpulse-platform/plantpulse-datalake-cli/bin/pd node sstable-size

# 스레드풀 통계
/opt/kopens/plantpulse-platform/plantpulse-datalake-cli/bin/pd node tpstats

Spark Tuning

Configuration file: plantpulse-analytics/spark/conf/spark-defaults.conf

Note: Apache Spark is a distributed processing engine for large-scale data analytics. Refer to the settings below to improve the speed and stability of analysis jobs.

Resource allocation

ParameterDefaultDescription
spark.cores.max16Maximum Spark cores
spark.driver.cores2Driver cores
spark.driver.memory4gDriver memory
spark.executor.cores1Executor cores
spark.executor.memory2GExecutor memory
spark.executor.memoryOverhead2gExecutor overhead memory

Dynamic allocation

ParameterDefaultDescription
spark.dynamicAllocation.enabledtrueDynamic executor allocation
spark.dynamicAllocation.minExecutors2Minimum executor count
spark.dynamicAllocation.maxExecutors16Maximum executor count
spark.dynamicAllocation.executorIdleTimeout30Idle executor timeout (seconds)

Shuffle and parallelism

ParameterDefaultDescription
spark.default.parallelism64Default parallelism
spark.sql.shuffle.partitions128SQL shuffle partitions
spark.sql.adaptive.enabledtrueAdaptive Query Execution
spark.sql.adaptive.coalescePartitions.enabledtruePartition coalescing

JVM configuration

Both Spark driver and executor use ZGC:

-XX:+UseZGC
-XX:+AlwaysPreTouch
-XX:+UseTLAB
-XX:+ResizeTLAB
-XX:+DisableExplicitGC

S3 (MinIO) integration settings

ParameterDefaultDescription
spark.hadoop.fs.s3a.connection.maximum400Maximum S3 connections
spark.hadoop.fs.s3a.threads.max128Maximum S3 threads
spark.hadoop.fs.s3a.max.total.tasks1024Maximum async operations
spark.hadoop.fs.s3a.fast.uploadtrueFast upload enabled
spark.hadoop.fs.s3a.fast.upload.bufferdiskUpload buffer type
spark.hadoop.fs.s3a.block.size128MBS3 block size

Iceberg configuration

ParameterDefaultDescription
spark.sql.iceberg.write.target-file-size-bytes256MBTarget file size
spark.sql.iceberg.column-stats.enabledtrueColumn statistics enabled
spark.sql.iceberg.vectorization.enabledtrueVectorized read enabled
spark.sql.iceberg.manifest.merge.enabledtrueManifest merge
spark.sql.parquet.compression.codeczstdParquet compression codec

Kafka Tuning

Configuration file: plantpulse-messaging/kafka/config/server.properties

Note: Kafka is the message broker that delivers sensor data in real time. As data volume increases, you can improve processing performance by adjusting Kafka settings.

Core settings

ParameterDefaultDescription
num.network.threads3Network processing threads
num.io.threads8I/O processing threads
socket.send.buffer.bytes102400Socket send buffer
socket.receive.buffer.bytes102400Socket receive buffer
socket.request.max.bytes104857600Maximum request size (100MB)
num.partitions1Default partition count
log.retention.hours168Log retention period (7 days)
log.segment.bytes1073741824Log segment size (1GB)

High-volume processing tuning

For handling large amounts of IoT data, refer to the settings below:

# 파티션 수 증가 (메시지 병렬 처리)
num.partitions=4

# I/O 스레드 증가
num.io.threads=16

# 네트워크 스레드 증가
num.network.threads=8

# 소켓 버퍼 증가
socket.send.buffer.bytes=1048576
socket.receive.buffer.bytes=1048576

Messaging Configuration

Configuration file: plantpulse-server/config/plantpulse-mq.properties

Kafka DDS topics

ParameterDefaultPurpose
mq.dds.kafka.topic.tag.pointpp-tag-pointTag point values
mq.dds.kafka.topic.tag.alarmpp-tag-alarmTag alarms
mq.dds.kafka.topic.asset.datapp-asset-dataAsset data
mq.dds.kafka.topic.asset.alarmpp-asset-alarmAsset alarms
mq.dds.kafka.topic.asset.eventpp-asset-eventAsset events
mq.dds.kafka.topic.asset.aggregationpp-asset-aggregationAsset aggregates
mq.dds.kafka.topic.domain.changed.eventpp-domain-changed-eventMetadata changes

MQTT DDS topics

ParameterDefaultPurpose
mq.dds.mqtt.topic.tag.pointtag/point/{tag_id}Per-tag point values
mq.dds.mqtt.topic.tag.alarmtag/alarm/{tag_id}Per-tag alarms
mq.dds.mqtt.topic.asset.dataasset/data/{asset_id}Per-asset data
mq.dds.mqtt.topic.asset.commandasset/command/{asset_id}Asset control commands

Scheduler Configuration

Configuration file: quartz.properties (web app internal classpath resource — not externalized)

ParameterDefaultDescription
org.quartz.threadPool.threadCount8Scheduler thread count
org.quartz.threadPool.threadPriority5Thread priority

Mail / Notification Configuration

Configuration file: plantpulse-server/config/plantpulse-mail.properties

ParameterDefaultDescription
mail.smtp.host192.168.0.41SMTP server address
mail.smtp.port25SMTP port
mail.smtp.authfalseAuthentication required
mail.smtp.starttls.enablefalseTLS enabled

Application Configuration

The application.properties file was removed in 2026.06. Console behavior settings such as theme and home page are now managed in the console's System > Settings (PostgreSQL mm_config table), and alarm.duplicate.check.minutes (duplicate alarm check interval in minutes) has been moved to plantpulse-server/config/plantpulse-engine.properties.


Performance bottleneck diagnosis

When performance issues occur, refer to the diagnosis methods and solutions for each symptom below.

1. Pipeline queue backlog

Symptom: The pipeline wait queue grows continuously

# Grafana 대시보드에서 "파이프라인 대기 큐" 패널을 확인해 주세요
# 또는 JMX: pipeline.queue.size 값을 확인해 주세요

Solution:

  • Increase the engine.pipeline.threads value
  • Adjust the engine.pipeline.ratelimit value upward
  • Check Cassandra write performance

2. Cassandra write delay

Symptom: Write timeouts or WriteTimeoutException occurs

# 컴팩션 상태 확인
/opt/kopens/plantpulse-platform/plantpulse-datalake-cli/bin/pd node compactionstats

# Memtable 플러시
/opt/kopens/plantpulse-platform/plantpulse-datalake-cli/bin/pd node flush

Solution:

  • Increase the concurrent_writes value
  • Increase the compaction_throughput value
  • Check disk I/O performance (SSD use is recommended)

3. Memory shortage

Symptom: JVM GC occurs frequently or OutOfMemoryError occurs

Solution:

  • Increase the bin/start.sh value in the service module's -Xmx
  • Reduce the engine.pipeline.queue.size value to save memory usage
  • Disable unnecessary caches

4. Network latency

Symptom: Data reception latency increases (check in the Grafana "network latency" panel)

Solution:

  • Check the network status between the OPC server and PlantPulse
  • Adjust the engine.streaming.messaging.timeout.ms value
  • Check the MQTT QoS level

Technical support

For performance tuning inquiries: webmaster@kopens.com