{"id":32898437,"url":"https://github.com/amaldevh/py-method-profiler","last_synced_at":"2026-05-16T09:35:13.224Z","repository":{"id":321974573,"uuid":"1087816394","full_name":"amaldevh/py-method-profiler","owner":"amaldevh","description":"Profile Python methods without changing your code","archived":false,"fork":false,"pushed_at":"2025-11-01T18:57:35.000Z","size":15,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":0,"default_branch":"main","last_synced_at":"2026-04-21T09:46:47.390Z","etag":null,"topics":["benchmarking","numpy","performance","performance-analysis","profiling","python","statistics","timing","wrapper"],"latest_commit_sha":null,"homepage":"","language":"Python","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/amaldevh.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2025-11-01T17:48:16.000Z","updated_at":"2025-11-01T18:57:39.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/amaldevh/py-method-profiler","commit_stats":null,"previous_names":["amaldevharidevan/py-method-profiler","amaldevh/py-method-profiler"],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/amaldevh/py-method-profiler","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/amaldevh%2Fpy-method-profiler","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/amaldevh%2Fpy-method-profiler/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/amaldevh%2Fpy-method-profiler/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/amaldevh%2Fpy-method-profiler/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/amaldevh","download_url":"https://codeload.github.com/amaldevh/py-method-profiler/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/amaldevh%2Fpy-method-profiler/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":33097002,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-05-16T04:41:52.686Z","status":"ssl_error","status_checked_at":"2026-05-16T04:41:52.009Z","response_time":115,"last_error":"SSL_connect returned=1 errno=0 peeraddr=140.82.121.5:443 state=error: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["benchmarking","numpy","performance","performance-analysis","profiling","python","statistics","timing","wrapper"],"created_at":"2025-11-10T12:01:10.441Z","updated_at":"2026-05-16T09:35:13.208Z","avatar_url":"https://github.com/amaldevh.png","language":"Python","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Profiling Wrapper\n\nA Python module that provides transparent method profiling for any object through a wrapper class.\n\n## Features\n\n- **Transparent Wrapping**: Wrap any object and use it normally while automatically collecting timing data\n- **Method Timing**: Automatically times every method call with high precision using `time.perf_counter()`\n- **Statistical Analysis**: Built-in statistics including mean, median, std dev, min, max, and total execution time\n- **Class-level Storage**: Timing data stored in a static dictionary accessible across all wrapper instances\n- **NumPy Integration**: Returns timing data as NumPy arrays for easy analysis\n\n## Installation\n\nRequires Python 3.6+ and NumPy:\n\n```bash\npip install numpy\n```\n\n## Quick Start\n\n```python\nfrom profiling_wrapper import ProfilingWrapper\n\n# Your class\nclass Calculator:\n    def add(self, a, b):\n        return a + b\n    \n    def multiply(self, a, b):\n        return a * b\n\n# Wrap the object\ncalc = ProfilingWrapper(Calculator())\n\n# Use it normally\ncalc.add(5, 10)\ncalc.add(3, 7)\ncalc.multiply(4, 6)\n\n# Get profiling data\nadd_times = ProfilingWrapper.get_profiling_data(\"Calculator.add\")\nprint(f\"add() was called {len(add_times)} times\")\nprint(f\"Execution times: {add_times}\")\n\n# Get statistics\nstats = ProfilingWrapper.get_statistics(\"Calculator.add\")\nprint(f\"Mean execution time: {stats['mean']:.6f}s\")\n```\n\n## API Reference\n\n### Constructor\n\n```python\nwrapper = ProfilingWrapper(obj)\n```\n\nCreates a profiling wrapper around any object.\n\n**Parameters:**\n- `obj`: Any object whose methods should be profiled\n\n### Class Methods\n\n#### `get_profiling_data(key: str) -\u003e np.ndarray`\n\nRetrieve timing data for a specific method.\n\n**Parameters:**\n- `key`: Method identifier in format `\"{ClassName}.{method_name}\"`\n\n**Returns:**\n- NumPy array of execution times in seconds (length = number of calls)\n\n**Example:**\n```python\ntimes = ProfilingWrapper.get_profiling_data(\"Calculator.add\")\n```\n\n#### `get_statistics(key: str) -\u003e Dict[str, float]`\n\nGet statistical summary for a method's execution times.\n\n**Parameters:**\n- `key`: Method identifier in format `\"{ClassName}.{method_name}\"`\n\n**Returns:**\n- Dictionary with keys: `count`, `mean`, `median`, `std`, `min`, `max`, `total`\n\n**Example:**\n```python\nstats = ProfilingWrapper.get_statistics(\"Calculator.add\")\nprint(f\"Average time: {stats['mean']:.6f}s\")\nprint(f\"Total calls: {stats['count']}\")\n```\n\n#### `get_all_profiling_data() -\u003e Dict[str, np.ndarray]`\n\nRetrieve timing data for all profiled methods.\n\n**Returns:**\n- Dictionary mapping method keys to NumPy arrays of execution times\n\n**Example:**\n```python\nall_data = ProfilingWrapper.get_all_profiling_data()\nfor method, times in all_data.items():\n    print(f\"{method}: {len(times)} calls\")\n```\n\n#### `clear_profiling_data(key: str = None)`\n\nClear profiling data.\n\n**Parameters:**\n- `key`: Optional method identifier. If provided, clears only that method's data. If `None`, clears all data.\n\n**Example:**\n```python\n# Clear all data\nProfilingWrapper.clear_profiling_data()\n\n# Clear specific method data\nProfilingWrapper.clear_profiling_data(\"Calculator.add\")\n```\n\n## Usage Examples\n\n### Example 1: Basic Profiling\n\n```python\nfrom profiling_wrapper import ProfilingWrapper\n\nclass DataProcessor:\n    def process(self, data):\n        # Some processing\n        return len(data)\n\n# Wrap and use\nprocessor = ProfilingWrapper(DataProcessor())\nprocessor.process([1, 2, 3])\nprocessor.process([4, 5, 6, 7])\n\n# Get results\ntimes = ProfilingWrapper.get_profiling_data(\"DataProcessor.process\")\nprint(f\"Called {len(times)} times with average time {times.mean():.6f}s\")\n```\n\n### Example 2: Multiple Instances\n\n```python\n# Create multiple wrapped instances\ncalc1 = ProfilingWrapper(Calculator())\ncalc2 = ProfilingWrapper(Calculator())\n\n# All calls are tracked together\ncalc1.add(1, 2)\ncalc2.add(3, 4)\n\n# Get combined data\ntimes = ProfilingWrapper.get_profiling_data(\"Calculator.add\")\nprint(f\"Total calls across all instances: {len(times)}\")\n```\n\n### Example 3: Performance Analysis\n\n```python\nimport numpy as np\n\n# Run some operations\nobj = ProfilingWrapper(MyClass())\nfor i in range(100):\n    obj.expensive_operation()\n\n# Analyze performance\nstats = ProfilingWrapper.get_statistics(\"MyClass.expensive_operation\")\nprint(f\"Performance Analysis:\")\nprint(f\"  Calls: {stats['count']}\")\nprint(f\"  Average: {stats['mean']*1000:.2f}ms\")\nprint(f\"  Median: {stats['median']*1000:.2f}ms\")\nprint(f\"  Std Dev: {stats['std']*1000:.2f}ms\")\nprint(f\"  Range: {stats['min']*1000:.2f}ms - {stats['max']*1000:.2f}ms\")\nprint(f\"  Total Time: {stats['total']:.2f}s\")\n```\n\n### Example 4: Comparing Methods\n\n```python\n# Profile multiple methods\nobj = ProfilingWrapper(Calculator())\n\nfor i in range(50):\n    obj.add(i, i+1)\n    obj.multiply(i, 2)\n\n# Compare performance\nall_data = ProfilingWrapper.get_all_profiling_data()\nfor method, times in all_data.items():\n    avg_time = times.mean()\n    print(f\"{method}: {avg_time*1000:.4f}ms average ({len(times)} calls)\")\n```\n\n## How It Works\n\n1. **Wrapping**: When you wrap an object, `ProfilingWrapper` intercepts all attribute access via `__getattr__`\n2. **Method Detection**: When a callable method is accessed, it's wrapped with timing logic\n3. **Timing**: Each method call is timed using `time.perf_counter()` (high-resolution timer)\n4. **Storage**: Execution times are stored in a class-level dictionary with keys like `\"ClassName.method_name\"`\n5. **Retrieval**: Timing data can be retrieved at any time using class methods\n\n## Notes\n\n- The wrapper is transparent - wrapped objects behave exactly like unwrapped ones\n- Only methods are profiled; regular attributes are passed through unchanged\n- Profiling data persists across wrapper instances (class-level storage)\n- Use `clear_profiling_data()` to reset between test runs\n- Timing precision depends on the system's `time.perf_counter()` implementation\n\n## Performance Overhead\n\nThe wrapper adds minimal overhead to each method call:\n- Attribute lookup\n- Function wrapping\n- Two `time.perf_counter()` calls\n- One dictionary append operation\n\nFor most use cases, this overhead is negligible (typically \u003c 1 microsecond).\n\n## License\n\nApache License\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Famaldevh%2Fpy-method-profiler","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Famaldevh%2Fpy-method-profiler","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Famaldevh%2Fpy-method-profiler/lists"}