{"id":18489994,"url":"https://github.com/pocke/majo","last_synced_at":"2025-04-08T21:30:50.184Z","repository":{"id":249617649,"uuid":"825836964","full_name":"pocke/majo","owner":"pocke","description":"A memory profiler focusing on long-lived objects.","archived":false,"fork":false,"pushed_at":"2024-10-27T01:23:35.000Z","size":67,"stargazers_count":11,"open_issues_count":1,"forks_count":0,"subscribers_count":1,"default_branch":"master","last_synced_at":"2025-04-02T16:06:35.746Z","etag":null,"topics":["memory","profiler","ruby"],"latest_commit_sha":null,"homepage":"","language":"C","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"bsd-2-clause","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/pocke.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","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}},"created_at":"2024-07-08T15:39:27.000Z","updated_at":"2024-10-27T01:23:38.000Z","dependencies_parsed_at":"2024-10-27T02:38:28.448Z","dependency_job_id":null,"html_url":"https://github.com/pocke/majo","commit_stats":null,"previous_names":["pocke/majo"],"tags_count":7,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/pocke%2Fmajo","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/pocke%2Fmajo/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/pocke%2Fmajo/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/pocke%2Fmajo/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/pocke","download_url":"https://codeload.github.com/pocke/majo/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":247875701,"owners_count":21010975,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","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":["memory","profiler","ruby"],"created_at":"2024-11-06T12:58:41.219Z","updated_at":"2025-04-08T21:30:49.649Z","avatar_url":"https://github.com/pocke.png","language":"C","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Majo🧙‍♀️\n\nA memory profiler focusing on long-lived objects.\n\n## Motivation\n\nI created this gem because I wanted to reduce the maximum memory usage of a Ruby program.\n\nThe existing memory profiler, `memory_profiler` gem, focuses on allocated and retained memory. This tool is useful to reduce allocations and retain memory, but it is not suitable for reducing the maximum memory usage.\n\nThis gem solves this problem by focusing on long-lived objects. Long-lived objects are objects that are not garbage collected for a long time. These objects are the main cause of the maximum memory usage.\n\n## NOTE: Performance\n\nThis gem slows down the target program because it hooks all object allocations and `free`. Also, it uses a lot of memory to store the object information. Therefore, it is not suitable in a production environment.\n\n## Installation\n\nInstall the gem and add to the application's Gemfile by executing:\n\n    $ bundle add majo --group development\n\nIf bundler is not being used to manage dependencies, install the gem by executing:\n\n    $ gem install majo\n\n## Usage\n\nWrap the code you want to profile with `Majo.run`.\nThen, call `report` method to display the result.\n\n```ruby\nresult = Majo.run do\n  code_to_profile\nend\n\nresult.report\n```\n\n### Options\n\nYou can pass the following options to `report` method.\n\n| Name        | Description              | Default                  | Type                                                                     |\n| ----------- | ------------------------ | ------------------------ | ------------------------------------------------------------------------ |\n| `out`       | Output file or IO        | `$stdout`                | `IO`, `String` or an object having `to_path` method (such as `Pathname`) |\n| `formatter` | The format of the result | `:color` or `monochrome` | `:color`, `:monochrome`, or `:csv`                                       |\n\nFor example:\n\n```ruby\nresult = Majo.run do\n  code_to_profile\nend\n\nresult.report(out: \"majo-result.csv\", formatter: :csv)\n```\n\n### Result Example\n\nThe result contains only long-lived objects, which are collected by the major GC or retained.\n\nThe example is as follows:\n\n```\nTotal 15055372 bytes (159976 objects)\n\nMemory by file\n-----------------------------------\n10431760  /path/to/gems/rbs-3.5.1/lib/rbs/parser_aux.rb\n 1966348  /path/to/gems/rbs-3.5.1/lib/rbs/environment_loader.rb\n  980344  /path/to/gems/rbs-3.5.1/lib/rbs/types.rb\n(snip)\n\nMemory by location\n-----------------------------------\n10431760  /path/to/gems/rbs-3.5.1/lib/rbs/parser_aux.rb:20\n 1942812  /path/to/gems/rbs-3.5.1/lib/rbs/environment_loader.rb:159\n  249920  /path/to/gems/rbs-3.5.1/lib/rbs/types.rb:994\n(snip)\n\nMemory by class\n-----------------------------------\n4274028  String\n3556632  RBS::Location\n2197840  Array\n(snip)\n\nObjects by file\n-----------------------------------\n109126  /path/to/gems/rbs-3.5.1/lib/rbs/parser_aux.rb\n 20813  /path/to/gems/rbs-3.5.1/lib/rbs/types.rb\n 12236  /path/to/gems/rbs-3.5.1/lib/rbs/environment.rb\n(snip)\n\nObjects by location\n-----------------------------------\n109126  /path/to/gems/rbs-3.5.1/lib/rbs/parser_aux.rb:20\n  4458  /path/to/gems/rbs-3.5.1/lib/rbs/namespace.rb:24\n  4132  /path/to/gems/rbs-3.5.1/lib/rbs/types.rb:374\n(snip)\n\nObjects by class\n-----------------------------------\n52495  Array\n22435  RBS::Location\n11144  RBS::TypeName\n(snip)\n\nRetained Memory by file\n-----------------------------------\n7040  /path/to/gems/3.3.0/gems/rbs-3.5.1/lib/rbs/parser_aux.rb\n 256  /path/to/gems/3.3.0/gems/rbs-3.5.1/lib/rbs/resolver/type_name_resolver.rb\n(snip)\n\nRetained Memory by location\n-----------------------------------\n7040  /path/to/gems/3.3.0/gems/rbs-3.5.1/lib/rbs/parser_aux.rb:20\n 256  /path/to/gems/3.3.0/gems/rbs-3.5.1/lib/rbs/resolver/type_name_resolver.rb:22\n(snip)\n\nRetained Memory by class\n-----------------------------------\n6920  String\n 256  Hash\n 120  Symbol\n(snip)\n\nRetained Objects by file\n-----------------------------------\n160  /path/to/gems/3.3.0/gems/rbs-3.5.1/lib/rbs/parser_aux.rb\n  1  /path/to/gems/3.3.0/gems/rbs-3.5.1/lib/rbs/resolver/type_name_resolver.rb\n(snip)\n\nRetained Objects by location\n-----------------------------------\n160  /path/to/gems/3.3.0/gems/rbs-3.5.1/lib/rbs/parser_aux.rb:20\n  1  /path/to/gems/3.3.0/gems/rbs-3.5.1/lib/rbs/resolver/type_name_resolver.rb:22\n(snip)\n\nRetained Objects by class\n-----------------------------------\n157  String\n  3  Symbol\n  1  Hash\n(snip)\n```\n\nThe CSV format is as follows:\n\n```csv\nObject class path,Class path,Method ID,Singleton method,Path,Line,Alloc generation,Free generation,Memsize,Count\nHash,RBS::Parser,_parse_signature,true,/path/to/gems/rbs-3.5.1/lib/rbs/parser_aux.rb,20,20,22,160,3\nHash,RBS::EnvironmentLoader,each_signature,false,/path/to/gems/rbs-3.5.1/lib/rbs/environment_loader.rb,159,20,22,160,1\nHash,RBS::Parser,_parse_signature,true,/path/to/gems/rbs-3.5.1/lib/rbs/parser_aux.rb,20,21,23,160,1\n(snip)\n```\n\nYou can find the raw data in the CSV format. It is useful for further analysis. For example: [A spreadsheet for Majo result](https://docs.google.com/spreadsheets/d/1Qe6ZSJ58bNfLbA_eSuL9FJy89taNPt325qAJnLDorOE/edit?gid=533761210#gid=533761210)\n\nThe columns are as follows:\n\n| Column name         | Description                                                                         |\n| ------------------- | ----------------------------------------------------------------------------------- |\n| `Object class path` | The class name of the allocated object                                              |\n| `Class path`        | The class name of the receiver of the method allocating the object                  |\n| `Method ID`         | The method name allocating the object                                               |\n| `Singleton method`  | `true` if the method call is for a singleton method                                 |\n| `Path`              | The file path of the method allocating the object                                   |\n| `Line`              | The line number of the method allocating the object                                 |\n| `Alloc generation`  | The GC generation number when the object is allocated                               |\n| `Free generation`   | The GC generation number when the object is freed. It's empty for retained objects. |\n| `Memsize`           | The memory size of the object in bytes                                              |\n| `Count`             | Number of objects allocated with the same conditions                                |\n\n## Name\n\nThe name \"Majo\" is a Japanese word `魔女` that means \"witch\". It is a wordplay on the word \"major\" in \"major GC\".\n\n## Thanks\n\nThis gem is inspired by [memory_profiler](https://github.com/SamSaffron/memory_profiler) gem.\n\n## Development\n\nAfter checking out the repo, run `bin/setup` to install dependencies. Then, run `rake spec` to run the tests. You can also run `bin/console` for an interactive prompt that will allow you to experiment.\n\nTo install this gem onto your local machine, run `bundle exec rake install`. To release a new version, update the version number in `version.rb`, and then run `bundle exec rake release`, which will create a git tag for the version, push git commits and the created tag, and push the `.gem` file to [rubygems.org](https://rubygems.org).\n\n## Contributing\n\nBug reports and pull requests are welcome on GitHub at https://github.com/pocke/majo.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fpocke%2Fmajo","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fpocke%2Fmajo","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fpocke%2Fmajo/lists"}