A common cause of Xi-Text and Xi-Batch issues: Shared memory segment exhaustion.
Symptoms appear as:
- Scheduler fails to start
- "Cannot allocate memory" errors
- Jobs or printers suddenly stop being created
- System becomes unresponsive to new operations
Why Shared Memory is Fixed
Xi-Text and Xi-Batch use System V IPC shared memory segments. These segments have fixed sizes that must be allocated when the scheduler starts.
Historical constraint:
In the 1980s-1990s when Xi-Text and Xi-Batch were developed, memory was expensive and scarce. Systems needed to carefully manage memory allocation. Once allocated, shared memory segments could not be easily expanded, especially if other applications had consumed available memory.
Today's systems have gigabytes of RAM. The old constraints are no longer mandatory, but the architecture remains to ensure that the software is fast, efficient and can still run on a variety of platforms including embedded, mobile and IoT devices.
What Gets Stored in Shared Memory
Xi-Text:
- Job queue entries
- Printer definitions
- Buffer space for communications
Xi-Batch:
- Job queue entries
- Variable definitions
- Buffer space for communications
When you run out:
- Cannot add more jobs to queue
- Cannot add more printers (Xi-Text)
- Cannot create more variables (Xi-Batch)
- Scheduler may crash or hang
Default Allocations
Xi-Text default:
bash
spstart # Typically 1000 jobs, 50 printers
Xi-Batch default:
bash
btstart # Typically 1000 jobs, 200 variables
These defaults are far too small for modern production systems.
Setting Appropriate Allocations
Modern systems should allocate generously.
Xi-Text:
bash
spstart 10000 200 # ^jobs ^printers
Xi-Batch:
bash
btstart -j 10000 -v 5000 # ^jobs ^variables
Why allocate more than you need?
On modern systems with gigabytes of RAM, overcommitting shared memory has negligible impact. The memory footprint is minimal compared to total system resources.
Better to allocate too much than too little.
Calculating Your Needs
Xi-Text:
Jobs needed = Peak queue size × 1.5 Printers needed = Number of printers × 1.2
Example calculation:
Peak queue: 2000 jobs Allocation: 2000 × 1.5 = 3000 jobs minimum Recommended: 5000 jobs (generous buffer) Printers: 50 Allocation: 50 × 1.2 = 60 minimum Recommended: 100 (generous buffer)
Xi-Batch:
Jobs needed = Maximum jobs in schedule × 1.5 Variables needed = Total variables × 2.0
Example calculation:
Maximum jobs: 500 Allocation: 500 × 1.5 = 750 minimum Recommended: 2000 (generous buffer) Variables: 150 Allocation: 150 × 2.0 = 300 minimum Recommended: 1000 (generous buffer)
Recommended Modern Allocations
Small installation:
bash
# Xi-Text spstart 5000 100 # Xi-Batch btstart -j 5000 -v 2000
Medium installation:
bash
# Xi-Text spstart 10000 200 # Xi-Batch btstart -j 10000 -v 5000
Large installation:
bash
# Xi-Text spstart 50000 500 # Xi-Batch btstart -j 50000 -v 10000
Very large installation:
bash
# Xi-Text spstart 100000 1000 # Xi-Batch btstart -j 100000 -v 20000
Memory Impact
Typical memory usage per entry:
- Job: ~2-4 KB
- Printer: ~1-2 KB
- Variable: ~1-2 KB
Example: Large allocation memory footprint:
Xi-Batch with 50,000 jobs and 10,000 variables: Jobs: 50,000 × 3 KB = 150 MB Variables: 10,000 × 2 KB = 20 MB Total: ~170 MB
On a system with 8 GB RAM, this is 2% of available memory.
On a system with 64 GB RAM, this is trivial.
Updating Startup Scripts
Find your startup script:
bash
# Common locations /etc/init.d/xitext /etc/init.d/xibatch /usr/lib/systemd/system/xitext.service /usr/lib/systemd/system/xibatch.service
Xi-Text init script:
bash
#!/bin/bash
# /etc/init.d/xitext
case "$1" in
start)
echo "Starting Xi-Text..."
/usr/bin/spstart 10000 200
;;
stop)
echo "Stopping Xi-Text..."
/usr/bin/sstop
;;
esac
Xi-Batch init script:
bash
#!/bin/bash
# /etc/init.d/xibatch
case "$1" in
start)
echo "Starting Xi-Batch..."
/usr/bin/btstart -j 10000 -v 5000
;;
stop)
echo "Stopping Xi-Batch..."
/usr/bin/btquit -y
;;
esac
Systemd service files:
ini
# /usr/lib/systemd/system/xitext.service [Unit] Description=Xi-Text Print Spooler After=network.target [Service] Type=forking ExecStart=/usr/bin/spstart 10000 200 ExecStop=/usr/bin/sstop RemainAfterExit=yes [Install] WantedBy=multi-user.target
ini
# /usr/lib/systemd/system/xibatch.service [Unit] Description=Xi-Batch Job Scheduler After=network.target [Service] Type=forking ExecStart=/usr/bin/btstart -j 10000 -v 5000 ExecStop=/usr/bin/btquit -y RemainAfterExit=yes [Install] WantedBy=multi-user.target
Verifying Current Allocation
Check running process:
bash
# Xi-Text - check startup command ps aux | grep spstart # Xi-Batch - check startup command ps aux | grep btstart
Look at IPC segments:
bash
# Show shared memory segments ipcs -m | grep spooler # Xi-Text ipcs -m | grep batch # Xi-Batch
Check scheduler log:
bash
# Xi-Text grep -i "jobs\|printers" /usr/spool/spd/spshed_reps | head # Xi-Batch grep -i "jobs\|variables" /usr/spool/batch/btsched_reps | head
When to Increase Allocation
Warning signs:
- Seeing errors about memory allocation
- Jobs mysteriously failing to submit
- Queue suddenly stops accepting new jobs
- System becomes sluggish
Check current usage:
bash
# Xi-Text - count current jobs sqlist | wc -l # Xi-Batch - count current jobs and variables btjlist | wc -l btvlist | wc -l
If approaching 80% of allocated space, increase allocation.
Applying New Allocations
Requires scheduler restart:
bash
# Xi-Text sstop spstart 20000 300 # Xi-Batch btquit -y btstart -j 20000 -v 10000
Cannot change allocations while running. Must stop and restart with new values.
Plan for scheduled maintenance window.
Best Practices
Always allocate generously:
Memory is cheap. Exhausting shared memory causes production outages.
Use round numbers:
Easier to remember and document:
- 5000, 10000, 20000, 50000
- Not 3742, 8391
Document your allocation:
Record why you chose specific numbers:
bash
# Allocated 10,000 jobs for peak load of 6,000 + 60% buffer # Allocated 5,000 variables for 2,000 in use + 150% buffer btstart -j 10000 -v 5000
Review quarterly:
Monitor actual usage and adjust allocations as workload grows.
Default to larger allocations:
Would you rather:
- Allocate 50,000 slots and use 5,000 (no problem)
- Allocate 5,000 slots and need 50,000 (production outage)
On modern systems, choose the safe option.
Common Misconceptions
"Won't allocating too much waste memory?"
No. On systems with 8+ GB RAM, even very large allocations (100,000 jobs) use less than 1% of total memory.
"Can't we expand shared memory dynamically?"
Xi-Text and Xi-Batch attempt this, but it often fails if other applications have consumed available shared memory. Better to allocate correctly at startup.
"Our system is small, we don't need much."
Systems grow. Allocate for future growth. The overhead is negligible.
Quick Reference
Recommended starting points:
bash
# Xi-Text - small site spstart 10000 200 # Xi-Text - large site spstart 50000 500 # Xi-Batch - small site btstart -j 10000 -v 5000 # Xi-Batch - large site btstart -j 50000 -v 10000
Check current allocation:
bash
ps aux | grep "spstart\|btstart"
Apply new allocation:
bash
# Stop, restart with new values # Xi-Text sstop && spstart 20000 300 # Xi-Batch btquit -y && btstart -j 20000 -v 8000
Update startup script permanently. Otherwise allocations reset on next reboot.
Bottom line: On modern systems with abundant RAM, generously allocate shared memory. The tiny memory overhead is insignificant compared to the risk of shared memory exhaustion. When in doubt, allocate more.