Skip to content

Performance Optimization

Performance optimization provides advanced techniques and tools to maximize the efficiency of your InjectQ dependency injection container.

🚀 Performance Optimization Techniques

Container Configuration Optimization

This page shows realistic, supported ways to optimize InjectQ performance using the real public APIs in the codebase.

Sections cover: - constructor-time options on InjectQ - pre-compiling resolution plans with container.compile() - profiling with DependencyProfiler from injectq.diagnostics.profiling - thread-safety guidance using the thread_safe flag and HybridLock

Container-level optimizations

The container is configured at construction time. There is no ContainerConfig class in the codebase — instead use InjectQ constructor flags.

from injectq import InjectQ

# Create a container with thread-safety enabled and async-scope support
container = InjectQ(use_async_scopes=True, thread_safe=True)

# Pre-compile resolution plans to reduce runtime overhead
container.compile()

Pre-compilation (via container.compile()) builds internal resolution plans ahead of time and can reduce per-request overhead in hot paths.

Profiling and diagnostics

Use the built-in profiler in injectq.diagnostics.profiling to measure resolution times and find bottlenecks.

from injectq.diagnostics.profiling import DependencyProfiler, get_global_profiler

# Create a profiler and profile a block of code
with DependencyProfiler() as profiler:
    # perform resolutions
    svc = container.get(SomeService)
    other = container.get(OtherService)

# Query metrics
metrics = profiler.get_metrics()
print(metrics)

# Or use the global profiler (useful during tests or app startup)
global_profiler = get_global_profiler()
global_profiler.start()
# ... do work
global_profiler.stop()
print(global_profiler.report())

# Export results for later analysis
profiler.export_json("di_profile.json")

Helpful profiler methods: profile_resolution() (context manager), profile_method() (decorator), get_metrics(), get_aggregated_metrics(), report(), export_json() and export_csv().

Thread-safety guidance

There is no ThreadSafetyLevel enum or container.set_thread_safety() in the codebase. Thread-safety is handled either by constructing the container with thread_safe=True or by using the locking primitives directly.

from injectq import InjectQ
from injectq.core.thread_safety import HybridLock, thread_safe

container = InjectQ(thread_safe=False)  # lower overhead when you know you are single-threaded

# Example: a function-level synchronization helper
lock = HybridLock()

@thread_safe
def critical_section():
    # function protected by the library-provided decorator
    pass

async def async_example():
    async with lock.async_lock():
        # safe async-critical section
        ...

with lock.sync_lock():
    # safe synchronous-critical section
    ...

If your application is single-threaded or uses its own concurrency model, prefer thread_safe=False to avoid locking overhead; enable thread_safe=True when concurrent access from multiple threads is expected.

Practical tips

  • Precompile resolution plans in startup paths (call container.compile()).
  • Profile with DependencyProfiler to find slow resolutions and cache/memoize where appropriate.
  • Avoid unnecessary object construction in factories used by the container; use lightweight factories or pooling for heavy objects.
  • Choose thread_safe appropriately for your deployment (disable in single-threaded scenarios).

Ready to read more about thread safety? See the thread-safety guide: thread-safety.md.