{"action":"closed","number":5172,"pull_request":{"url":"https://api.github.com/repos/composer/composer/pulls/5172","id":65904679,"html_url":"https://github.com/composer/composer/pull/5172","diff_url":"https://github.com/composer/composer/pull/5172.diff","patch_url":"https://github.com/composer/composer/pull/5172.patch","issue_url":"https://api.github.com/repos/composer/composer/issues/5172","number":5172,"state":"closed","locked":false,"title":"Speedup autoloading with APCu class loader","user":{"login":"nicolas-grekas","id":243674,"avatar_url":"https://avatars.githubusercontent.com/u/243674?v=3","gravatar_id":"","url":"https://api.github.com/users/nicolas-grekas","html_url":"https://github.com/nicolas-grekas","followers_url":"https://api.github.com/users/nicolas-grekas/followers","following_url":"https://api.github.com/users/nicolas-grekas/following{/other_user}","gists_url":"https://api.github.com/users/nicolas-grekas/gists{/gist_id}","starred_url":"https://api.github.com/users/nicolas-grekas/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/nicolas-grekas/subscriptions","organizations_url":"https://api.github.com/users/nicolas-grekas/orgs","repos_url":"https://api.github.com/users/nicolas-grekas/repos","events_url":"https://api.github.com/users/nicolas-grekas/events{/privacy}","received_events_url":"https://api.github.com/users/nicolas-grekas/received_events","type":"User","site_admin":false},"body":"The fastest autoloader we can currently get with composer is when dumping the class map in authoritative mode: this reduces autoloading to an `isset()` check, one of the fastest in PHP.\r\nBut this autoloader has one drawback: it doesn't scale with the number of classes. Even with opcache enabled, the generated class map being a php array, it becomes slower when you add more classes to it. It also consumes more memory.\r\n\r\nThat made me wonder if using APCu could help build an even better autoloader.\r\n\r\nThis PR adds an ApcuClassLoader that wraps the regular ClassLoader by inheritance so that only APCu is used when the cache is warm, and the regular autoloader is lazily initialized when needed to warm up the APCu cache.\r\n\r\nI did not yet wire any on/off way to configure which loader to use. Just change yourself the `$apcuLoader` property if you want to try the patch for now.\r\n\r\nStill, I wanted to share with you the following Blackfire profile:\r\nhttps://blackfire.io/profiles/compare/ace900a5-4936-4998-871d-680bbf744177/graph\r\n\r\nThis profile has been generated by taking the blackfire classmap (~8300 lines) and loading ~430 classes from it, this number being quite typical for rendering a single page/response in a Symfony app.\r\n\r\nThe results are quite interesting:\r\n- loading the classmap goes from 2.66 ms and 2.56 MB to zero\r\n- overall loading time is reduced by 1.59 ms and 2.54 MB!\r\n\r\nOn the memory side, we have a clear win.\r\nOn the time side, 2.66 ms removal from not-loading the classmap are turned into a lower 1.59 ms general perf increase. Logically, this could mean that *once the classmap is loaded*, using it is faster that calling apcu_fetch, but since we have to load this classmap anyway, the win is still a clear win in the typical web request use case where only a short excerpt of all existing classes are loaded at once.\r\n\r\nThe only remaining question to me now is: how should we plug this into composer configuration system.\r\nSome ideas:\r\n- add a command line option?\r\n- `ext-apcu` must-be in the dependencies?\r\n- both? Other way?","created_at":"2016-04-10T08:36:19Z","updated_at":"2016-04-11T11:05:10Z","closed_at":"2016-04-11T11:05:10Z","merged_at":null,"merge_commit_sha":"adbd9ac2c1b53ea4ac5cfc65a794df53ae76befd","assignee":null,"milestone":null,"commits_url":"https://api.github.com/repos/composer/composer/pulls/5172/commits","review_comments_url":"https://api.github.com/repos/composer/composer/pulls/5172/comments","review_comment_url":"https://api.github.com/repos/composer/composer/pulls/comments{/number}","comments_url":"https://api.github.com/repos/composer/composer/issues/5172/comments","statuses_url":"https://api.github.com/repos/composer/composer/statuses/4ca4c24399498ebf0eee5d067137416eac509ac9","head":{"label":"nicolas-grekas:apcu","ref":"apcu","sha":"4ca4c24399498ebf0eee5d067137416eac509ac9","user":{"login":"nicolas-grekas","id":243674,"avatar_url":"https://avatars.githubusercontent.com/u/243674?v=3","gravatar_id":"","url":"https://api.github.com/users/nicolas-grekas","html_url":"https://github.com/nicolas-grekas","followers_url":"https://api.github.com/users/nicolas-grekas/followers","following_url":"https://api.github.com/users/nicolas-grekas/following{/other_user}","gists_url":"https://api.github.com/users/nicolas-grekas/gists{/gist_id}","starred_url":"https://api.github.com/users/nicolas-grekas/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/nicolas-grekas/subscriptions","organizations_url":"https://api.github.com/users/nicolas-grekas/orgs","repos_url":"https://api.github.com/users/nicolas-grekas/repos","events_url":"https://api.github.com/users/nicolas-grekas/events{/privacy}","received_events_url":"https://api.github.com/users/nicolas-grekas/received_events","type":"User","site_admin":false},"repo":{"id":16522834,"name":"composer","full_name":"nicolas-grekas/composer","owner":{"login":"nicolas-grekas","id":243674,"avatar_url":"https://avatars.githubusercontent.com/u/243674?v=3","gravatar_id":"","url":"https://api.github.com/users/nicolas-grekas","html_url":"https://github.com/nicolas-grekas","followers_url":"https://api.github.com/users/nicolas-grekas/followers","following_url":"https://api.github.com/users/nicolas-grekas/following{/other_user}","gists_url":"https://api.github.com/users/nicolas-grekas/gists{/gist_id}","starred_url":"https://api.github.com/users/nicolas-grekas/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/nicolas-grekas/subscriptions","organizations_url":"https://api.github.com/users/nicolas-grekas/orgs","repos_url":"https://api.github.com/users/nicolas-grekas/repos","events_url":"https://api.github.com/users/nicolas-grekas/events{/privacy}","received_events_url":"https://api.github.com/users/nicolas-grekas/received_events","type":"User","site_admin":false},"private":false,"html_url":"https://github.com/nicolas-grekas/composer","description":"Dependency Manager for PHP","fork":true,"url":"https://api.github.com/repos/nicolas-grekas/composer","forks_url":"https://api.github.com/repos/nicolas-grekas/composer/forks","keys_url":"https://api.github.com/repos/nicolas-grekas/composer/keys{/key_id}","collaborators_url":"https://api.github.com/repos/nicolas-grekas/composer/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/nicolas-grekas/composer/teams","hooks_url":"https://api.github.com/repos/nicolas-grekas/composer/hooks","issue_events_url":"https://api.github.com/repos/nicolas-grekas/composer/issues/events{/number}","events_url":"https://api.github.com/repos/nicolas-grekas/composer/events","assignees_url":"https://api.github.com/repos/nicolas-grekas/composer/assignees{/user}","branches_url":"https://api.github.com/repos/nicolas-grekas/composer/branches{/branch}","tags_url":"https://api.github.com/repos/nicolas-grekas/composer/tags","blobs_url":"https://api.github.com/repos/nicolas-grekas/composer/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/nicolas-grekas/composer/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/nicolas-grekas/composer/git/refs{/sha}","trees_url":"https://api.github.com/repos/nicolas-grekas/composer/git/trees{/sha}","statuses_url":"https://api.github.com/repos/nicolas-grekas/composer/statuses/{sha}","languages_url":"https://api.github.com/repos/nicolas-grekas/composer/languages","stargazers_url":"https://api.github.com/repos/nicolas-grekas/composer/stargazers","contributors_url":"https://api.github.com/repos/nicolas-grekas/composer/contributors","subscribers_url":"https://api.github.com/repos/nicolas-grekas/composer/subscribers","subscription_url":"https://api.github.com/repos/nicolas-grekas/composer/subscription","commits_url":"https://api.github.com/repos/nicolas-grekas/composer/commits{/sha}","git_commits_url":"https://api.github.com/repos/nicolas-grekas/composer/git/commits{/sha}","comments_url":"https://api.github.com/repos/nicolas-grekas/composer/comments{/number}","issue_comment_url":"https://api.github.com/repos/nicolas-grekas/composer/issues/comments{/number}","contents_url":"https://api.github.com/repos/nicolas-grekas/composer/contents/{+path}","compare_url":"https://api.github.com/repos/nicolas-grekas/composer/compare/{base}...{head}","merges_url":"https://api.github.com/repos/nicolas-grekas/composer/merges","archive_url":"https://api.github.com/repos/nicolas-grekas/composer/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/nicolas-grekas/composer/downloads","issues_url":"https://api.github.com/repos/nicolas-grekas/composer/issues{/number}","pulls_url":"https://api.github.com/repos/nicolas-grekas/composer/pulls{/number}","milestones_url":"https://api.github.com/repos/nicolas-grekas/composer/milestones{/number}","notifications_url":"https://api.github.com/repos/nicolas-grekas/composer/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/nicolas-grekas/composer/labels{/name}","releases_url":"https://api.github.com/repos/nicolas-grekas/composer/releases{/id}","deployments_url":"https://api.github.com/repos/nicolas-grekas/composer/deployments","created_at":"2014-02-04T19:26:50Z","updated_at":"2015-03-03T10:35:01Z","pushed_at":"2016-04-11T10:45:46Z","git_url":"git://github.com/nicolas-grekas/composer.git","ssh_url":"git@github.com:nicolas-grekas/composer.git","clone_url":"https://github.com/nicolas-grekas/composer.git","svn_url":"https://github.com/nicolas-grekas/composer","homepage":"http://getcomposer.org/","size":12173,"stargazers_count":0,"watchers_count":0,"language":"PHP","has_issues":false,"has_downloads":true,"has_wiki":false,"has_pages":false,"forks_count":0,"mirror_url":null,"open_issues_count":0,"forks":0,"open_issues":0,"watchers":0,"default_branch":"master"}},"base":{"label":"composer:master","ref":"master","sha":"40c14709f79f9d7ea35ac969cfbd7f41beb525bb","user":{"login":"composer","id":837015,"avatar_url":"https://avatars.githubusercontent.com/u/837015?v=3","gravatar_id":"","url":"https://api.github.com/users/composer","html_url":"https://github.com/composer","followers_url":"https://api.github.com/users/composer/followers","following_url":"https://api.github.com/users/composer/following{/other_user}","gists_url":"https://api.github.com/users/composer/gists{/gist_id}","starred_url":"https://api.github.com/users/composer/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/composer/subscriptions","organizations_url":"https://api.github.com/users/composer/orgs","repos_url":"https://api.github.com/users/composer/repos","events_url":"https://api.github.com/users/composer/events{/privacy}","received_events_url":"https://api.github.com/users/composer/received_events","type":"Organization","site_admin":false},"repo":{"id":1864363,"name":"composer","full_name":"composer/composer","owner":{"login":"composer","id":837015,"avatar_url":"https://avatars.githubusercontent.com/u/837015?v=3","gravatar_id":"","url":"https://api.github.com/users/composer","html_url":"https://github.com/composer","followers_url":"https://api.github.com/users/composer/followers","following_url":"https://api.github.com/users/composer/following{/other_user}","gists_url":"https://api.github.com/users/composer/gists{/gist_id}","starred_url":"https://api.github.com/users/composer/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/composer/subscriptions","organizations_url":"https://api.github.com/users/composer/orgs","repos_url":"https://api.github.com/users/composer/repos","events_url":"https://api.github.com/users/composer/events{/privacy}","received_events_url":"https://api.github.com/users/composer/received_events","type":"Organization","site_admin":false},"private":false,"html_url":"https://github.com/composer/composer","description":"Dependency Manager for PHP","fork":false,"url":"https://api.github.com/repos/composer/composer","forks_url":"https://api.github.com/repos/composer/composer/forks","keys_url":"https://api.github.com/repos/composer/composer/keys{/key_id}","collaborators_url":"https://api.github.com/repos/composer/composer/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/composer/composer/teams","hooks_url":"https://api.github.com/repos/composer/composer/hooks","issue_events_url":"https://api.github.com/repos/composer/composer/issues/events{/number}","events_url":"https://api.github.com/repos/composer/composer/events","assignees_url":"https://api.github.com/repos/composer/composer/assignees{/user}","branches_url":"https://api.github.com/repos/composer/composer/branches{/branch}","tags_url":"https://api.github.com/repos/composer/composer/tags","blobs_url":"https://api.github.com/repos/composer/composer/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/composer/composer/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/composer/composer/git/refs{/sha}","trees_url":"https://api.github.com/repos/composer/composer/git/trees{/sha}","statuses_url":"https://api.github.com/repos/composer/composer/statuses/{sha}","languages_url":"https://api.github.com/repos/composer/composer/languages","stargazers_url":"https://api.github.com/repos/composer/composer/stargazers","contributors_url":"https://api.github.com/repos/composer/composer/contributors","subscribers_url":"https://api.github.com/repos/composer/composer/subscribers","subscription_url":"https://api.github.com/repos/composer/composer/subscription","commits_url":"https://api.github.com/repos/composer/composer/commits{/sha}","git_commits_url":"https://api.github.com/repos/composer/composer/git/commits{/sha}","comments_url":"https://api.github.com/repos/composer/composer/comments{/number}","issue_comment_url":"https://api.github.com/repos/composer/composer/issues/comments{/number}","contents_url":"https://api.github.com/repos/composer/composer/contents/{+path}","compare_url":"https://api.github.com/repos/composer/composer/compare/{base}...{head}","merges_url":"https://api.github.com/repos/composer/composer/merges","archive_url":"https://api.github.com/repos/composer/composer/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/composer/composer/downloads","issues_url":"https://api.github.com/repos/composer/composer/issues{/number}","pulls_url":"https://api.github.com/repos/composer/composer/pulls{/number}","milestones_url":"https://api.github.com/repos/composer/composer/milestones{/number}","notifications_url":"https://api.github.com/repos/composer/composer/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/composer/composer/labels{/name}","releases_url":"https://api.github.com/repos/composer/composer/releases{/id}","deployments_url":"https://api.github.com/repos/composer/composer/deployments","created_at":"2011-06-08T08:53:00Z","updated_at":"2016-04-11T10:34:53Z","pushed_at":"2016-04-11T11:03:19Z","git_url":"git://github.com/composer/composer.git","ssh_url":"git@github.com:composer/composer.git","clone_url":"https://github.com/composer/composer.git","svn_url":"https://github.com/composer/composer","homepage":"https://getcomposer.org/","size":18596,"stargazers_count":7484,"watchers_count":7484,"language":"PHP","has_issues":true,"has_downloads":true,"has_wiki":false,"has_pages":false,"forks_count":2054,"mirror_url":null,"open_issues_count":325,"forks":2054,"open_issues":325,"watchers":7484,"default_branch":"master"}},"_links":{"self":{"href":"https://api.github.com/repos/composer/composer/pulls/5172"},"html":{"href":"https://github.com/composer/composer/pull/5172"},"issue":{"href":"https://api.github.com/repos/composer/composer/issues/5172"},"comments":{"href":"https://api.github.com/repos/composer/composer/issues/5172/comments"},"review_comments":{"href":"https://api.github.com/repos/composer/composer/pulls/5172/comments"},"review_comment":{"href":"https://api.github.com/repos/composer/composer/pulls/comments{/number}"},"commits":{"href":"https://api.github.com/repos/composer/composer/pulls/5172/commits"},"statuses":{"href":"https://api.github.com/repos/composer/composer/statuses/4ca4c24399498ebf0eee5d067137416eac509ac9"}},"merged":false,"mergeable":true,"mergeable_state":"unstable","merged_by":null,"comments":9,"review_comments":1,"commits":1,"additions":281,"deletions":12,"changed_files":8}}