A performance testing framework for Django that helps you understand and fix performance issues, not just detect them
Project description
Django Mercury ๐
Part of the Human in the Loop ecosystem
A performance testing framework for Django that helps you understand and fix performance issues, not just detect them.
๐ Origin Story
Mercury was born from a real need at EduLite - an open-source education platform designed for students in areas with poor internet connectivity. When we discovered our UserSearchView was making 825 queries for paginated results, we knew we needed better tools.
Instead of just fixing the issue, we built Mercury - a framework that not only catches performance problems but teaches developers how to fix them. This aligns with the Fair, Free, and Open values of EduLite - as we wanted people of all skill levels to be able to contribute and learn!
๐ฏ Current Status: Initial Release
What's Working NOW:
- โ N+1 query detection with severity analysis
- โ Performance grading (F to A+)
- โ
Two test case classes:
DjangoMercuryAPITestCaseandDjangoPerformanceAPITestCase - โ Smart operation type detection
- โ Educational guidance when tests fail
- โ C-powered monitoring for minimal overhead
- โ Comprehensive metrics: response time, queries, memory
What We Actually Found:
๐จ POTENTIAL N+1 QUERY PROBLEM! ๐จ
Severity: CRITICAL (825 queries)
Coming Soon:
- ๐ MCP (Model Context Protocol) integration for AI-assisted optimization
- ๐ Historical performance tracking
- ๐ Standard TestCase for non-API views
- ๐ PyPI package release
- ๐ Performance regression detection
๐ฆ Installation (Current)
Mercury is currently part of the EduLite project. To use it in your Django project:
# Clone and build
git clone https://github.com/ibrahim-sisar/EduLite.git
cd EduLite/backend/performance_testing/c_core
make clean && make
# Add to your Python path in test files
import sys
from pathlib import Path
performance_testing_path = Path(__file__).parent.parent / "performance_testing"
sys.path.insert(0, str(performance_testing_path))
๐ Quick Start
Two Classes, Two Approaches
1. DjangoMercuryAPITestCase - Automatic Monitoring
from python_bindings.django_integration_mercury import DjangoMercuryAPITestCase
class UserSearchPerformanceTest(DjangoMercuryAPITestCase):
"""Mercury automatically monitors every test method."""
def test_user_search(self):
# Just write your test - Mercury handles the rest
response = self.client.get('/api/users/search/?q=test')
self.assertEqual(response.status_code, 200)
# Mercury automatically analyzes and reports performance
2. DjangoPerformanceAPITestCase - Modular Control
from python_bindings.django_integration import DjangoPerformanceAPITestCase
from python_bindings.monitor import monitor_django_view
class AdvancedPerformanceTest(DjangoPerformanceAPITestCase):
"""For when you need specific assertions and control."""
def test_with_assertions(self):
with monitor_django_view("search") as monitor:
response = self.client.get('/api/users/search/')
# Use specific assertions
self.assertResponseTimeLess(monitor, 100)
self.assertQueriesLess(monitor, 10)
self.assertNoNPlusOne(monitor)
๐ Real Output from Mercury
This is actual output from testing EduLite:
๐จ MERCURY PERFORMANCE DASHBOARD - UserSearchPerformanceTest
โญโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโฎ
โ ๐ Overall Status: NEEDS IMPROVEMENT โ
โ ๐ Overall Grade: F (20.5/100) โ
โ ๐ Tests Executed: 12 โ
โ โฑ๏ธ Avg Response Time: 105.6ms โ
โ ๐ง Avg Memory Usage: 91.7MB โ
โ ๐๏ธ Total Queries: 2761 (230.1 avg) โ
โ ๐จ N+1 Issues: 10/12 tests affected โ
โฐโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโฏ
๐ The Philosophy in Action
Mercury embodies the Human in the Loop philosophy:
80% Automation:
- Automatic performance monitoring
- N+1 detection and analysis
- Performance grading
- Threshold management
20% Human Wisdom:
- Understanding WHY performance matters
- Choosing the right optimization strategy
- Learning from the guidance
- Making architectural decisions
Example: Educational Guidance
When a test fails, Mercury doesn't just say "failed" - it teaches:
๐ MERCURY EDUCATIONAL GUIDANCE
============================================================
๐ฏ Test: test_user_list_view
โ ๏ธ Default thresholds exceeded
๐๏ธ Query Count: 230 (limit: 10)
โ 220 extra queries (2200% exceeded)
๐ก SOLUTION: N+1 Query Pattern Detected
Your code is likely missing select_related() or prefetch_related()
Try: User.objects.select_related('profile').prefetch_related('groups')
๐ ๏ธ Quick Fix for Testing:
cls.set_performance_thresholds({'query_count_max': 250})
But the REAL fix is optimizing your queries!
============================================================
๐ ๏ธ Available Assertions
DjangoPerformanceAPITestCase Methods
# Time assertions
self.assertResponseTimeLess(monitor, 100) # < 100ms
self.assertPerformanceFast(monitor) # Predefined "fast"
self.assertPerformanceNotSlow(monitor) # Not "slow"
# Query assertions
self.assertQueriesLess(monitor, 10) # < 10 queries
self.assertNoNPlusOne(monitor) # No N+1 detected
# Memory assertions
self.assertMemoryLess(monitor, 50) # < 50MB
self.assertMemoryEfficient(monitor) # Reasonable memory use
# Cache assertions
self.assertGoodCachePerformance(monitor, 0.8) # 80% hit ratio
๐ง Configuration
class MyTest(DjangoMercuryAPITestCase):
@classmethod
def setUpClass(cls):
super().setUpClass()
# Configure Mercury
cls.configure_mercury(
enabled=True,
auto_scoring=True,
verbose_reporting=False,
educational_guidance=True # Learn while you test!
)
# Set thresholds
cls.set_performance_thresholds({
'response_time_ms': 100,
'query_count_max': 10,
'memory_overhead_mb': 20,
})
๐ฏ Real Impact on EduLite
Before Mercury:
- UserSearchView: 825 queries for pagination
- No visibility into performance issues
- Users in poor connectivity areas suffered
After Mercury:
- Identified the exact problem
- Reduced to 12 queries
- Performance monitoring on every PR
๐ง Roadmap
Phase 1: Current Release โ
- Basic performance monitoring
- N+1 detection
- Educational guidance
Phase 2: MCP Integration (Q1 2025)
- AI-assisted optimization suggestions
- Automated fix generation with human review
- Learning mode for junior developers
Phase 3: Standalone Package (Q2 2025)
- PyPI release as
django-mercury - Comprehensive documentation
- Plugin system for custom analyzers
๐ค Contributing
Mercury is part of both EduLite and the Human in the Loop ecosystem. We believe in:
- Education First: Tools should teach, not just detect
- Human Understanding: Keep humans in control of their code
- Open Source: Built by the community, for the community
How to Contribute
- Try Mercury on your Django project
- Report issues and suggestions
- Help us build MCP integration
- Share your performance optimization stories
๐ซ Built for Education
Mercury was created for EduLite, an education platform serving students in challenging conditions. Every feature is designed to:
- Work with limited resources
- Teach while testing
- Build developer skills
- Ensure quality for end users
๐ License
This project is licensed under the GNU General Public License v3.0 (GPL-3.0).
Why GPL-3.0?
We chose GPL-3.0 because it enforces the same standards and values we believe in:
- ๐ Open: The source code must remain open and accessible to everyone
- ๐ Free: Free as in freedom - you can use, study, share, and improve the software
- โ๏ธ Fair: Any improvements or derivatives must be shared back with the community
- ๐ค Copyleft: Ensures the software and its derivatives remain free forever
This means if you create and distribute a modified version, you must:
- Make your source code available
- License it under GPL-3.0
- Preserve all copyright and license notices
- Document your changes
This aligns perfectly with the Human in the Loop philosophy of keeping knowledge open and accessible.
For the full license text, see LICENSE or visit GNU GPL v3.0.
๐ Acknowledgments
- EduLite Team - For the real-world use case
- Human in the Loop - For the philosophy
- Django/DRF Community - For the foundation
Mercury: Because finding N+1 queries shouldn't require a PhD in database optimization.
Built with โค๏ธ by developers who believe in human understanding, not just automation.
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file django_mercury_performance-0.0.1.tar.gz.
File metadata
- Download URL: django_mercury_performance-0.0.1.tar.gz
- Upload date:
- Size: 190.6 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.1.0 CPython/3.10.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
51ced0561cf9c5441f1a23110a2b5eac09355901495026eb2f0f2301ddfde40e
|
|
| MD5 |
ec7ef67b743673a8fa9f20407c3e78dc
|
|
| BLAKE2b-256 |
f7977058a829674bf3c952d9988f28f68710bef3f560287aeca5b011df541f04
|
File details
Details for the file django_mercury_performance-0.0.1-py3-none-any.whl.
File metadata
- Download URL: django_mercury_performance-0.0.1-py3-none-any.whl
- Upload date:
- Size: 203.3 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.1.0 CPython/3.10.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
3f3fedfa781d1358e6bcc01c24500701a0c583c67fd1d99559d41252c048708b
|
|
| MD5 |
e7e2bb304fb9a3995c552da36133b646
|
|
| BLAKE2b-256 |
54e7038e89f2f68b324bc41d3072a4b55446cbdcb0b8d5cfbd6998498fa40243
|