| name | cwl-optimize-performance |
| description | Optimize CWL package performance including resource allocation, Docker image selection, scatter
patterns, and execution strategies. Learn techniques to improve execution speed and resource
efficiency. Use when processes are slow, use too many resources, or need optimization.
|
| license | Apache-2.0 |
| compatibility | Requires Weaver deployment and CWL v1.0+. |
| metadata | {"author":"fmigneault"} |
Optimize CWL Package Performance
Techniques to improve CWL package execution speed and resource efficiency.
When to Use
- Processes take too long to execute
- Docker images are large and slow to pull
- Resource allocation is inefficient
- Parallel processing opportunities exist
- Jobs fail due to resource limits
- Optimizing workflow execution time
Docker Image Optimization
Use Slim/Alpine Variants
DockerRequirement:
dockerPull: python:3.12
DockerRequirement:
dockerPull: python:3.12-slim
DockerRequirement:
dockerPull: python:3.12-alpine
Pin Specific Versions
DockerRequirement:
dockerPull: myimage:latest
DockerRequirement:
dockerPull: myimage:1.2.3
Use Digest for Immutability
DockerRequirement:
dockerPull: python@sha256:abc123...
Pre-pull Images
docker pull python:3.12-slim
docker pull gdal:3.6.0-alpine
Resource Requirements
Right-size Resources
requirements:
ResourceRequirement:
coresMin: 2
coresMax: 4
ramMin: 4096
ramMax: 8192
tmpdirMin: 10240
outdirMin: 20480
Dynamic Resource Allocation
requirements:
InlineJavascriptRequirement: {}
ResourceRequirement:
ramMin: |
${
var sizeMB = inputs.input_file.size / (1024 * 1024);
return Math.max(2048, Math.ceil(sizeMB * 3));
}
coresMin: |
${
return Math.min(8, Math.max(2, inputs.files.length));
}
Avoid Over-allocation
ResourceRequirement:
ramMin: 64000
coresMin: 32
ResourceRequirement:
ramMin: 4096
coresMin: 2
Parallel Processing with Scatter
Basic Scatter
steps:
process:
run: tool.cwl
scatter: input_file
in:
input_file: input_files
out: [output]
Scatter Multiple Inputs
steps:
process:
run: tool.cwl
scatter: [file, parameter]
scatterMethod: dotproduct
in:
file: files
parameter: parameters
out: [output]
Optimal Scatter Size
scatter: tiny_chunks
scatter: reasonable_chunks
scatter: huge_chunks
Input/Output Optimization
Minimize Data Transfer
inputs:
full_dataset:
type: File
inputs:
subset_params:
type: string
Use File References
{
"input_file": {
"class": "File",
"path": "https://example.com/large-file.nc"
}
}
Stream When Possible
baseCommand: [curl, https://example.com/data.txt]
stdout: processed.txt
Efficient Output Patterns
outputs:
results:
type: File[]
outputBinding:
glob: "*.txt"
outputs:
results:
type: File
outputBinding:
glob: "combined-results.tar.gz"
Workflow Structure Optimization
Minimize Steps
steps:
step1: download.cwl
step2: unzip.cwl
step3: validate.cwl
step4: process.cwl
steps:
process:
run: optimized-process.cwl
Parallel Independent Steps
steps:
process_a:
run: tool-a.cwl
in: {input: data}
out: [output_a]
process_b:
run: tool-b.cwl
in: {input: data}
out: [output_b]
combine:
run: merge.cwl
in:
a: process_a/output_a
b: process_b/output_b
out: [merged]
Cache Intermediate Results
outputs:
preprocessed:
type: File
outputSource: preprocess/output
final:
type: File
outputSource: analyze/output
Command Optimization
Efficient Commands
baseCommand: [bash, -c]
arguments:
- "cat file.txt | grep pattern | sort | uniq > output.txt"
baseCommand: [grep, pattern]
stdin: file.txt
stdout: output.txt
Avoid Unnecessary Operations
baseCommand: [python, -c]
arguments:
- "open('huge.txt').read()"
baseCommand: [awk, '{print $1}']
Use Native Tools
DockerRequirement:
dockerPull: python:3.12-slim
baseCommand: [python, -c, "print('hello')"]
DockerRequirement:
dockerPull: alpine:latest
baseCommand: [echo, hello]
Monitoring and Profiling
Track Resource Usage
weaver statistics -u $WEAVER_URL -j $JOB_ID
weaver status -u $WEAVER_URL -j $JOB_ID | jq '.duration'
weaver logs -u $WEAVER_URL -j $JOB_ID
Identify Bottlenecks
steps:
download:
run: download.cwl
process:
run: process.cwl
Profile Locally
time cwltool process.cwl inputs.json
docker stats
Caching Strategies
Docker Image Caching
DockerRequirement:
dockerPull: myimage:1.2.3
Intermediate File Caching
steps:
expensive_preprocess:
run: preprocess.cwl
in: {input: raw_data}
out: [preprocessed]
analyze:
run: analyze.cwl
in: {input: expensive_preprocess/preprocessed}
out: [result]
Common Performance Issues
Issue: Slow Docker Pull
DockerRequirement:
dockerPull: tensorflow/tensorflow:latest-gpu
DockerRequirement:
dockerPull: tensorflow/tensorflow:2.11.0-gpu-slim
Issue: Memory Overflow
ResourceRequirement:
ramMin: 2048
ResourceRequirement:
ramMin: |
${
var dataSizeMB = inputs.data.size / (1024 * 1024);
return Math.max(4096, dataSizeMB * 4);
}
Issue: Slow File I/O
baseCommand: [python, -c]
arguments:
- "data = open('huge.csv').read()"
baseCommand: [python, -c]
arguments:
- |
import sys
for line in sys.stdin:
process(line)
stdin: huge.csv
Issue: Sequential Processing
steps:
process:
run: tool.cwl
steps:
process:
run: tool.cwl
scatter: item
in: {item: items}
out: [output]
Benchmarking
Compare Approaches
time weaver execute -u $WEAVER_URL -p approach1 -I inputs.json
time weaver execute -u $WEAVER_URL -p approach2 -I inputs.json
weaver statistics -u $WEAVER_URL -j $JOB1
weaver statistics -u $WEAVER_URL -j $JOB2
A/B Testing
ResourceRequirement:
ramMin: 4096
coresMin: 2
ResourceRequirement:
ramMin: 8192
coresMin: 4
Best Practices Summary
- ✅ Use slim Docker images
- ✅ Pin image versions for caching
- ✅ Right-size resource allocations
- ✅ Use scatter for parallel processing
- ✅ Minimize data transfer
- ✅ Combine small steps
- ✅ Profile and measure
- ✅ Cache expensive operations
- ✅ Stream large data when possible
- ✅ Use appropriate tools for tasks
Related Skills
Documentation
Measurement
Track these metrics for optimization:
- Execution time: Start to finish duration
- Docker pull time: Image download duration
- Resource usage: CPU, RAM, Disk I/O
- Data transfer: Input/output transfer time
- Queue time: Time waiting for resources
Optimize the biggest bottleneck first!