Skip to main content

A performance testing framework for Django that helps you understand and fix performance issues, not just detect them

Project description

Django Mercury ๐Ÿš€

Python 3.10 Django 5.1 License: GPL v3 Built for: EduLite Values: Open

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: DjangoMercuryAPITestCase and DjangoPerformanceAPITestCase
  • โœ… 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

  1. Try Mercury on your Django project
  2. Report issues and suggestions
  3. Help us build MCP integration
  4. 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


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


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

django_mercury_performance-0.0.1.tar.gz (190.6 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

django_mercury_performance-0.0.1-py3-none-any.whl (203.3 kB view details)

Uploaded Python 3

File details

Details for the file django_mercury_performance-0.0.1.tar.gz.

File metadata

File hashes

Hashes for django_mercury_performance-0.0.1.tar.gz
Algorithm Hash digest
SHA256 51ced0561cf9c5441f1a23110a2b5eac09355901495026eb2f0f2301ddfde40e
MD5 ec7ef67b743673a8fa9f20407c3e78dc
BLAKE2b-256 f7977058a829674bf3c952d9988f28f68710bef3f560287aeca5b011df541f04

See more details on using hashes here.

File details

Details for the file django_mercury_performance-0.0.1-py3-none-any.whl.

File metadata

File hashes

Hashes for django_mercury_performance-0.0.1-py3-none-any.whl
Algorithm Hash digest
SHA256 3f3fedfa781d1358e6bcc01c24500701a0c583c67fd1d99559d41252c048708b
MD5 e7e2bb304fb9a3995c552da36133b646
BLAKE2b-256 54e7038e89f2f68b324bc41d3072a4b55446cbdcb0b8d5cfbd6998498fa40243

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page