{"action":"created","issue":{"url":"https://api.github.com/repos/costajob/inci_score.cr/issues/1","repository_url":"https://api.github.com/repos/costajob/inci_score.cr","labels_url":"https://api.github.com/repos/costajob/inci_score.cr/issues/1/labels{/name}","comments_url":"https://api.github.com/repos/costajob/inci_score.cr/issues/1/comments","events_url":"https://api.github.com/repos/costajob/inci_score.cr/issues/1/events","html_url":"https://github.com/costajob/inci_score.cr/pull/1","id":161455067,"number":1,"title":"Optimizations","user":{"login":"asterite","id":209371,"avatar_url":"https://avatars.githubusercontent.com/u/209371?v=3","gravatar_id":"","url":"https://api.github.com/users/asterite","html_url":"https://github.com/asterite","followers_url":"https://api.github.com/users/asterite/followers","following_url":"https://api.github.com/users/asterite/following{/other_user}","gists_url":"https://api.github.com/users/asterite/gists{/gist_id}","starred_url":"https://api.github.com/users/asterite/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/asterite/subscriptions","organizations_url":"https://api.github.com/users/asterite/orgs","repos_url":"https://api.github.com/users/asterite/repos","events_url":"https://api.github.com/users/asterite/events{/privacy}","received_events_url":"https://api.github.com/users/asterite/received_events","type":"User","site_admin":false},"labels":[],"state":"open","locked":false,"assignee":null,"milestone":null,"comments":1,"created_at":"2016-06-21T14:40:52Z","updated_at":"2016-06-21T14:45:54Z","closed_at":null,"pull_request":{"url":"https://api.github.com/repos/costajob/inci_score.cr/pulls/1","html_url":"https://github.com/costajob/inci_score.cr/pull/1","diff_url":"https://github.com/costajob/inci_score.cr/pull/1.diff","patch_url":"https://github.com/costajob/inci_score.cr/pull/1.patch"},"body":"@costajob Hi!\r\n\r\nI saw your tweet (can't find it now) saying that the Crystal version was twice as fast, but you wondered why it wasn't faster. I profiled your app and found some bottlenecks, then I improved them :-)\r\n\r\nIn summary, the changes are:\r\n\r\n1. Calling `@catalog.keys` on every request is slow, as this builds a huge array for the keys. This is not really needed, as the keys are already in `@catalog` and can be traversed with `each`, `reduce` and `find` without allocating extra memory.\r\n2. Use `to_json(io)` to directly write the JSON output to the response. This is the approach the whole standard library takes: `to_s`, `to_json` and `to_yaml` all have an overload that writes directly to an IO. This avoids extra memory allocations (it avoids creating an intermediate string only to dump it to the response and then wait for the GC to collect it)\r\n3. Change some types to structs instead of classes. The many Rules types only define behaviour, no real data, and they are immutable, so it's best to define them as struct. These then will be allocated on the stack, not on the heap, and avoid extra memory allocations.\r\n\r\nAs you can see, the most important point is to avoid extra memory allocations: these are slow, and make the GC have more work to do.\r\n\r\nI plan to write an optimization guide on Crystal's docs soon.\r\n\r\nI ran `wrk` and got better results, but I'm not sure I did it well. Could you try to run the benchmarks again with the changes in this PR?"},"comment":{"url":"https://api.github.com/repos/costajob/inci_score.cr/issues/comments/227462904","html_url":"https://github.com/costajob/inci_score.cr/pull/1#issuecomment-227462904","issue_url":"https://api.github.com/repos/costajob/inci_score.cr/issues/1","id":227462904,"user":{"login":"asterite","id":209371,"avatar_url":"https://avatars.githubusercontent.com/u/209371?v=3","gravatar_id":"","url":"https://api.github.com/users/asterite","html_url":"https://github.com/asterite","followers_url":"https://api.github.com/users/asterite/followers","following_url":"https://api.github.com/users/asterite/following{/other_user}","gists_url":"https://api.github.com/users/asterite/gists{/gist_id}","starred_url":"https://api.github.com/users/asterite/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/asterite/subscriptions","organizations_url":"https://api.github.com/users/asterite/orgs","repos_url":"https://api.github.com/users/asterite/repos","events_url":"https://api.github.com/users/asterite/events{/privacy}","received_events_url":"https://api.github.com/users/asterite/received_events","type":"User","site_admin":false},"created_at":"2016-06-21T14:45:54Z","updated_at":"2016-06-21T14:45:54Z","body":"I just force-pushed some changes, I forgot to use the `to_json(io)` method in app.cr"}}
{"actor":{"display_login":"asterite"}}