Skip to content

Conversation

@lauraneto
Copy link
Contributor

@lauraneto lauraneto commented Dec 9, 2025

Summary

  • Re-enables lazy locking in LockingMechanism by switching ReadLock and WriteLock to use their lazy implementations instead of eager ones

Background

The codebase already had the concept of lazy vs eager locks, but locks were always being acquired eagerly. This caused unnecessary database queries even when the actual data was already cached at the repository level.

The typical pattern:

using ICoreScope scope = ScopeProvider.CreateCoreScope(autoComplete: true);
scope.ReadLock(Constants.Locks.MediaTree);
return _mediaRepository.Get(id);

Even if the media is cached, the eager lock still hits the database. With lazy locks, the lock is only acquired if and when the database is actually accessed.

Benefits

  • Reduces database round-trips when data is served from repository cache
  • Improves performance especially with latency between web server and database
  • Makes better use of existing repository caches instead of requiring additional request-level caching workarounds

Load Test Results

All tests performed after rebasing on PR #21105 (deadlock fix). Each configuration was tested 5 times to ensure consistency.

Test 1: Cache-Hit Stress Test (50 VUs, 1000 iterations, 100% reads)

Tests performance when serving cached data - the ideal scenario for lazy locks to shine.

Database Lazy Locks Eager Locks Improvement
SQL Server 19.93ms avg 28.15ms avg 29% faster
SQLite ~same ~same No significant difference

SQL Server Detail:

  • Lazy: avg 19.93ms, p95 69.28ms
  • Eager: avg 28.15ms, p95 131.51ms
  • Lazy locks skip lock acquisition on cache hits, reducing database round-trips

Test 2: Write-Heavy Stress Test (50 VUs, 200 iterations, mixed workload)

Tests high-concurrency write operations (create content type → GET → create content → GET → publish).

Database Lazy Locks Eager Locks Improvement
SQL Server 1.22s avg 1.36s avg 10% faster
SQLite 623ms avg 731ms avg 15% faster

SQL Server Detail:

  • Lazy: 1.22s avg, 35.4 req/s throughput, 0% failure rate
  • Eager: 1.36s avg, 32.6 req/s throughput, 0.06% failure rate

SQLite Detail:

  • Lazy: 623ms avg, 63.6 req/s throughput
  • Eager: 731ms avg, 55.4 req/s throughput

Key Findings

  1. SQL Server sees consistent improvement - Both read-heavy (29% faster) and write-heavy (10% faster) scenarios benefit from lazy locks under high concurrency.

  2. Performance gap increases under load - Higher VU counts (50 vs 20) showed more pronounced benefits from lazy locks.

  3. SQLite benefits from writes, not reads - SQLite's single-writer lock model means cache-hit scenarios don't benefit as much, but write-heavy workloads still see 15% improvement.

  4. Both configurations are stable - No deadlocks observed with either approach after the PR Content Publishing: Fix deadlocks by acquiring WriteLock at outer scope #21105 fix.

Test plan

…blishing

Acquire a write lock on ContentTree at the start of PublishAsync to prevent
deadlocks. Previously, inner scopes would acquire read locks first (via
repository operations), then attempt to upgrade to write locks, causing
deadlocks when multiple transactions tried this simultaneously.

By acquiring the write lock at the outer scope, we ensure consistent lock
ordering and prevent the deadlock scenario.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <[email protected]>
@lauraneto lauraneto force-pushed the v17/feature/re-introduce-lazy-locks branch from c638d77 to 631b3db Compare December 10, 2025 17:13
@lauraneto lauraneto changed the base branch from main to v17/bugfix/deadlock-fix-content-publishing December 10, 2025 17:14
Base automatically changed from v17/bugfix/deadlock-fix-content-publishing to main December 10, 2025 19:59
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants