import json
import sys
import time
from pathlib import Path
try:
import denet
except ImportError:
print("Error: denet package not found.")
print("Make sure it's installed or PYTHONPATH is set correctly.")
sys.exit(1)
def create_child_process_script():
script_content = """
import os
import sys
import time
import multiprocessing
def cpu_intensive_work(duration):
# CPU-intensive computation.
start_time = time.time()
while time.time() - start_time < duration:
# Perform intensive calculation
for _ in range(500000):
x = 123.456
for i in range(20):
x = (x ** 1.1) % 10000
def main():
print(f"Parent process PID: {os.getpid()}")
# Create multiple child processes doing CPU-intensive work
children = []
for i in range(3):
# Each child runs for a different duration
duration = 2.0 + i * 0.5
pid = os.fork()
if pid == 0: # Child process
print(f"Child {i+1} PID: {os.getpid()} (running for {duration}s)")
cpu_intensive_work(duration)
print(f"Child {i+1} completed")
sys.exit(0)
else:
children.append(pid)
# Parent does some light work while waiting for children
print(f"Parent waiting for {len(children)} children to complete...")
# Do some light work while waiting
for _ in range(10):
time.sleep(0.2)
# Wait for all children to finish
for pid in children:
os.waitpid(pid, 0)
print("All children completed")
return 0
if __name__ == "__main__":
sys.exit(main())
"""
script_path = Path("child_processes.py")
script_path.write_text(script_content)
return script_path
def print_section(title):
print("\n" + "=" * 50)
print(f" {title}")
print("=" * 50)
def format_metrics(metrics):
if isinstance(metrics, str):
try:
metrics = json.loads(metrics)
except json.JSONDecodeError:
return "Invalid JSON"
result = {}
if "aggregated" in metrics:
result["process_count"] = metrics["aggregated"].get("process_count", 1)
result["cpu_usage"] = metrics["aggregated"].get("cpu_usage", 0)
result["mem_rss_kb"] = metrics["aggregated"].get("mem_rss_kb", 0)
result["thread_count"] = metrics["aggregated"].get("thread_count", 0)
children_count = len(metrics.get("children", []))
result["children_count"] = children_count
if metrics.get("parent"):
result["parent_cpu"] = metrics["parent"].get("cpu_usage", 0)
result["parent_mem_kb"] = metrics["parent"].get("mem_rss_kb", 0)
elif "cpu_usage" in metrics:
result["process_count"] = 1
result["cpu_usage"] = metrics.get("cpu_usage", 0)
result["mem_rss_kb"] = metrics.get("mem_rss_kb", 0)
result["thread_count"] = metrics.get("thread_count", 0)
result["children_count"] = 0
result["parent_cpu"] = metrics.get("cpu_usage", 0)
result["parent_mem_kb"] = metrics.get("mem_rss_kb", 0)
return result
def run_with_monitoring(script_path, include_children=True):
mode = "WITH" if include_children else "WITHOUT"
print_section(f"Running {mode} child process monitoring")
output_file = f"monitoring_{mode.lower()}_children.jsonl"
print(f"Starting monitoring (include_children={include_children})...")
start_time = time.time()
exit_code, monitor = denet.execute_with_monitoring(
cmd=["python", str(script_path)],
base_interval_ms=100, max_interval_ms=500, store_in_memory=True, output_file=output_file, include_children=include_children, )
elapsed = time.time() - start_time
print(f"Script completed in {elapsed:.2f}s with exit code: {exit_code}")
samples = monitor.get_samples()
print(f"Collected {len(samples)} samples")
parsed_samples = []
for sample in samples:
if isinstance(sample, str):
try:
sample_data = format_metrics(sample)
parsed_samples.append(sample_data)
except json.JSONDecodeError:
continue
if parsed_samples:
max_cpu = max(s.get("cpu_usage", 0) for s in parsed_samples)
max_processes = max(s.get("process_count", 1) for s in parsed_samples)
max_mem = max(s.get("mem_rss_kb", 0) for s in parsed_samples)
print("\nMonitoring Results:")
print(f"- Maximum processes detected: {max_processes}")
print(f"- Maximum CPU usage: {max_cpu:.2f}%")
print(f"- Maximum memory usage: {max_mem / 1024:.2f} MB")
print("\nProcess counts over time:")
for i, sample in enumerate(parsed_samples):
if i < 5 or i >= len(parsed_samples) - 5: proc_count = sample.get("process_count", 1)
children = sample.get("children_count", 0)
cpu = sample.get("cpu_usage", 0)
print(f" Sample {i + 1}: {proc_count} processes ({children} children), {cpu:.2f}% CPU")
summary_json = monitor.get_summary()
summary = json.loads(summary_json)
print("\nSummary Statistics:")
print(f"- Total time: {summary.get('total_time_secs', 0):.2f}s")
print(f"- Average CPU usage: {summary.get('avg_cpu_usage', 0):.2f}%")
print(f"- Peak memory usage: {summary.get('peak_mem_rss_kb', 0) / 1024:.2f} MB")
print(f"- Maximum processes: {summary.get('max_processes', 1)}")
print(f"- Sample count: {summary.get('sample_count', 0)}")
print(f"\nDetailed monitoring data written to: {output_file}")
return summary, parsed_samples
def main():
print("Denet Child Process Monitoring Example")
print(f"Using denet version: {getattr(denet, '__version__', 'unknown')}")
script_path = create_child_process_script()
try:
with_summary, with_samples = run_with_monitoring(script_path, include_children=True)
without_summary, without_samples = run_with_monitoring(script_path, include_children=False)
print_section("Comparison")
with_processes = with_summary.get("max_processes", 1)
without_processes = without_summary.get("max_processes", 1)
print("Process Count:")
print(f"- WITH child monitoring: {with_processes}")
print(f"- WITHOUT child monitoring: {without_processes}")
if with_processes > without_processes:
print("✅ Child monitoring correctly detected multiple processes")
else:
print("❌ Child monitoring didn't detect additional processes")
with_cpu = with_summary.get("avg_cpu_usage", 0)
without_cpu = without_summary.get("avg_cpu_usage", 0)
print("\nCPU Usage:")
print(f"- WITH child monitoring: {with_cpu:.2f}%")
print(f"- WITHOUT child monitoring: {without_cpu:.2f}%")
if with_cpu > without_cpu * 1.2: print("✅ Child monitoring captured more CPU usage")
else:
print("❌ Child monitoring didn't capture significantly more CPU usage")
with_mem = with_summary.get("peak_mem_rss_kb", 0)
without_mem = without_summary.get("peak_mem_rss_kb", 0)
print("\nMemory Usage:")
print(f"- WITH child monitoring: {with_mem / 1024:.2f} MB")
print(f"- WITHOUT child monitoring: {without_mem / 1024:.2f} MB")
if with_mem > without_mem * 1.2: print("✅ Child monitoring captured more memory usage")
else:
print("❌ Child monitoring didn't capture significantly more memory usage")
print("\nExample complete.")
print("For more information, check the output JSONL files for detailed metrics.")
finally:
if script_path.exists():
script_path.unlink()
if __name__ == "__main__":
main()