The Mechanic 2 🔧
A Rails Engine for benchmarking Ruby code with full access to your application's classes and dependencies.
Features
- Rails Engine Integration: Mount directly into any Rails application
- Full Application Context: Benchmark code with access to all your models, services, and gems
- Side-by-Side Comparison: Compare two code snippets with detailed performance metrics
- Security First: Built-in code validation prevents dangerous operations
- Zero Configuration: Just add the gem and mount the route
- Self-Contained: All assets (CSS & JavaScript) are inlined - no asset pipeline required
- Export Results: Download results as JSON or Markdown
Installation
Add this line to your application's Gemfile:
gem 'the_mechanic_2'
# or from GitHub
gem 'the_mechanic_2', git: 'https://github.com/randyv128/the_mechanic_2'
Then execute:
bundle install
Usage
1. Mount the Engine
Add this to your config/routes.rb
:
Rails.application.routes.draw do
mount TheMechanic2::Engine => '/mechanic'
# Your other routes...
end
2. Start Your Rails Server
rails server
3. Access The Mechanic
Navigate to: http://localhost:3000/mechanic
That's it! No additional setup required.
Note: The engine works with Rails 6.0+ and uses
eager_load_paths
for proper autoloading compatibility.
Example Usage
Basic Comparison
Shared Setup:
arr = (1..1000).to_a
Code A:
arr.sum
Code B:
arr.reduce(:+)
With ActiveRecord Models
Shared Setup:
users = User.limit(100)
Code A:
users.map(&:full_name)
Code B:
users.pluck(:first_name, :last_name).map { |f, l| "#{f} #{l}" }
Configuration (Optional)
Create an initializer at config/initializers/the_mechanic_2.rb
:
TheMechanic2.configure do |config|
# Set custom timeout (default: 30 seconds)
config.timeout = 60
# Enable authentication (default: false)
config.enable_authentication = true
# Set authentication callback
config.authentication_callback = ->(controller) {
controller.current_user&.admin?
}
end
Configuration Options
- timeout: Maximum execution time per benchmark (1-300 seconds, default: 30)
- enable_authentication: Require authentication before allowing benchmarks (default: false)
- authentication_callback: Proc that receives the controller and returns true/false
Security
The Mechanic includes comprehensive security validation:
- ✅ Process Isolation: Each benchmark runs in a separate Rails runner process
- ✅ Code Validation: Blocks dangerous operations before execution
- ✅ Timeout Protection: Automatically terminates long-running code
- ✅ Read-Only Database: Write operations are blocked
- ✅ No File System Access: File operations are forbidden
- ✅ No Network Access: Network operations are blocked
- ✅ No System Calls: System-level operations are prevented
Forbidden Operations
The following operations are automatically blocked:
- System calls (
system
,exec
,spawn
, backticks) - File operations (
File.open
,File.read
,File.write
) - Network operations (
Net::HTTP
,Socket
,URI.open
) - Database writes (
save
,update
,destroy
,create
) - Thread creation (
Thread.new
) - Dangerous evals (
eval
,instance_eval
,class_eval
)
API Endpoints
The engine provides the following endpoints:
-
GET /ask_the_mechanic_2
- Main UI -
POST /ask_the_mechanic_2/validate
- Validate code without executing -
POST /ask_the_mechanic_2/run
- Execute benchmark -
POST /ask_the_mechanic_2/export
- Export results (JSON or Markdown)
Platform Requirements
- Ruby: 2.7.0 or higher
- Rails: 6.0 or higher
- Platform: Linux, macOS, BSD, Unix, Windows
Performance Metrics
The Mechanic measures:
- IPS: Iterations per second
- Standard Deviation: Performance consistency
- Objects Allocated: Memory allocation count
- Memory Usage: Total memory in MB
- Execution Time: Single run duration
Development
Running Tests
cd the_mechanic_2
bundle exec rspec
Test Coverage
- 163 tests covering all services, models, and controllers
- Comprehensive security validation tests
- Integration tests with dummy Rails app
How It Works
- Code Submission: User submits two code snippets via the web interface
- Security Validation: Code is validated for dangerous operations
-
Process Spawning: Each snippet runs in a separate
rails runner
process - Measurement: Performance and memory metrics are collected
- Comparison: Results are compared and a winner is determined
- Display: Results are shown side-by-side with detailed metrics
Architecture
TheMechanic2::Engine
├── BenchmarksController # HTTP endpoints
├── BenchmarkService # Orchestrates benchmarking
├── RailsRunnerService # Spawns isolated processes
├── SecurityService # Validates code safety
├── BenchmarkRequest # Request validation
└── BenchmarkResult # Result formatting & export
Troubleshooting
Benchmarks are slow
- Reduce the timeout value
- Simplify your code snippets
- Check if your Rails app has slow boot time
"Timeout exceeded" errors
- Increase the timeout in configuration
- Simplify your benchmark code
- Check for infinite loops
Can't access my models
- Ensure your Rails app is fully loaded
- Check that models are properly defined
- Verify the engine is mounted correctly
Authentication not working
- Verify
enable_authentication
is set totrue
- Check your authentication callback logic
- Ensure the callback has access to the controller
Contributing
- Fork the repository
- Create your feature branch (
git checkout -b feature/amazing-feature
) - Commit your changes (
git commit -m 'Add amazing feature'
) - Push to the branch (
git push origin feature/amazing-feature
) - Open a Pull Request
License
This project is licensed under the MIT License - see the LICENSE file for details.
Credits
Inspired by the original The Mechanic standalone application.
Built with:
- benchmark-ips - Performance measurement
- memory_profiler - Memory tracking
Support
For issues and questions, please open an issue on GitHub.
Made with ❤️ for the Ruby community