{"action":"created","comment":{"url":"https://api.github.com/repos/Kinto/kinto/pulls/comments/156626153","pull_request_review_id":83132617,"id":156626153,"diff_hunk":"@@ -15,8 +30,12 @@ def account_check(username, password, request):\n \n     hashed = existing['password'].encode(encoding='utf-8')\n     pwd_str = password.encode(encoding='utf-8')\n-    if hashed == bcrypt.hashpw(pwd_str, hashed):\n-        return True  # Match! Return anything but None.\n+    # Check if password is valid (it is a very expensive computation)\n+    if bcrypt.checkpw(pwd_str, hashed):  # Match!\n+        # Remember result so we don't have to calculate bcrypt hash next time.\n+        cache.set(cache_key, \"1\", ttl=30)  # Time to live: 30 seconds","path":"kinto/plugins/accounts/authentication.py","position":35,"original_position":35,"commit_id":"95a4df00514bcf6717a34df2d7a5887dbda76913","original_commit_id":"95a4df00514bcf6717a34df2d7a5887dbda76913","user":{"login":"Stanley","id":41941,"avatar_url":"https://avatars1.githubusercontent.com/u/41941?v=4","gravatar_id":"","url":"https://api.github.com/users/Stanley","html_url":"https://github.com/Stanley","followers_url":"https://api.github.com/users/Stanley/followers","following_url":"https://api.github.com/users/Stanley/following{/other_user}","gists_url":"https://api.github.com/users/Stanley/gists{/gist_id}","starred_url":"https://api.github.com/users/Stanley/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/Stanley/subscriptions","organizations_url":"https://api.github.com/users/Stanley/orgs","repos_url":"https://api.github.com/users/Stanley/repos","events_url":"https://api.github.com/users/Stanley/events{/privacy}","received_events_url":"https://api.github.com/users/Stanley/received_events","type":"User","site_admin":false},"body":"Thought about it too, but couldn't figure out how to implement cache that would expire after one request. Any ideas?","created_at":"2017-12-13T11:04:16Z","updated_at":"2017-12-13T11:04:16Z","html_url":"https://github.com/Kinto/kinto/pull/1413#discussion_r156626153","pull_request_url":"https://api.github.com/repos/Kinto/kinto/pulls/1413","author_association":"NONE","_links":{"self":{"href":"https://api.github.com/repos/Kinto/kinto/pulls/comments/156626153"},"html":{"href":"https://github.com/Kinto/kinto/pull/1413#discussion_r156626153"},"pull_request":{"href":"https://api.github.com/repos/Kinto/kinto/pulls/1413"}},"in_reply_to_id":156234159},"pull_request":{"url":"https://api.github.com/repos/Kinto/kinto/pulls/1413","id":156661933,"html_url":"https://github.com/Kinto/kinto/pull/1413","diff_url":"https://github.com/Kinto/kinto/pull/1413.diff","patch_url":"https://github.com/Kinto/kinto/pull/1413.patch","issue_url":"https://api.github.com/repos/Kinto/kinto/issues/1413","number":1413,"state":"open","locked":false,"title":"[Account plugin] add cache to authentication method","user":{"login":"Stanley","id":41941,"avatar_url":"https://avatars1.githubusercontent.com/u/41941?v=4","gravatar_id":"","url":"https://api.github.com/users/Stanley","html_url":"https://github.com/Stanley","followers_url":"https://api.github.com/users/Stanley/followers","following_url":"https://api.github.com/users/Stanley/following{/other_user}","gists_url":"https://api.github.com/users/Stanley/gists{/gist_id}","starred_url":"https://api.github.com/users/Stanley/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/Stanley/subscriptions","organizations_url":"https://api.github.com/users/Stanley/orgs","repos_url":"https://api.github.com/users/Stanley/repos","events_url":"https://api.github.com/users/Stanley/events{/privacy}","received_events_url":"https://api.github.com/users/Stanley/received_events","type":"User","site_admin":false},"body":"When debugging my application, I've noticed very poor performance when logged in using account plugin. It turns out that the biggest bottle neck is bcrypt and its `hashpw` method (https://github.com/Kinto/kinto/blob/master/kinto/plugins/accounts/authentication.py#L18). Making sure it is executed no more than once per request drastically reduces response times.\r\n\r\n### Before:\r\n```\r\n> ab -n 100 -A admin:admin 127.0.0.1:8888/v1/\r\nThis is ApacheBench, Version 2.3 <$Revision: 1807734 $>\r\nCopyright 1996 Adam Twiss, Zeus Technology Ltd, http://www.zeustech.net/\r\nLicensed to The Apache Software Foundation, http://www.apache.org/\r\n\r\nBenchmarking 127.0.0.1 (be patient).....done\r\n\r\n\r\nServer Software:        waitress\r\nServer Hostname:        127.0.0.1\r\nServer Port:            8888\r\n\r\nDocument Path:          /v1/\r\nDocument Length:        697 bytes\r\n\r\nConcurrency Level:      1\r\nTime taken for tests:   39.127 seconds\r\nComplete requests:      100\r\nFailed requests:        0\r\nTotal transferred:      95200 bytes\r\nHTML transferred:       69700 bytes\r\nRequests per second:    2.56 [#/sec] (mean)\r\nTime per request:       391.272 [ms] (mean)\r\nTime per request:       391.272 [ms] (mean, across all concurrent requests)\r\nTransfer rate:          2.38 [Kbytes/sec] received\r\n\r\nConnection Times (ms)\r\n              min  mean[+/-sd] median   max\r\nConnect:        0    0   0.0      0       0\r\nProcessing:   387  391   4.8    390     427\r\nWaiting:      386  391   4.8    390     427\r\nTotal:        387  391   4.8    390     427\r\n\r\nPercentage of the requests served within a certain time (ms)\r\n  50%    390\r\n  66%    391\r\n  75%    392\r\n  80%    393\r\n  90%    395\r\n  95%    399\r\n  98%    402\r\n  99%    427\r\n 100%    427 (longest request)\r\n```\r\n![image](https://user-images.githubusercontent.com/41941/33650408-2ad2cec2-da62-11e7-942f-14a7168be1b8.png)\r\n\r\n### After:\r\n```\r\n> ab -n 100 -A admin:admin 127.0.0.1:8888/v1/\r\nThis is ApacheBench, Version 2.3 <$Revision: 1807734 $>\r\nCopyright 1996 Adam Twiss, Zeus Technology Ltd, http://www.zeustech.net/\r\nLicensed to The Apache Software Foundation, http://www.apache.org/\r\n\r\nBenchmarking 127.0.0.1 (be patient).....done\r\n\r\n\r\nServer Software:        waitress\r\nServer Hostname:        127.0.0.1\r\nServer Port:            8888\r\n\r\nDocument Path:          /v1/\r\nDocument Length:        697 bytes\r\n\r\nConcurrency Level:      1\r\nTime taken for tests:   0.392 seconds\r\nComplete requests:      100\r\nFailed requests:        0\r\nTotal transferred:      95200 bytes\r\nHTML transferred:       69700 bytes\r\nRequests per second:    255.05 [#/sec] (mean)\r\nTime per request:       3.921 [ms] (mean)\r\nTime per request:       3.921 [ms] (mean, across all concurrent requests)\r\nTransfer rate:          237.11 [Kbytes/sec] received\r\n\r\nConnection Times (ms)\r\n              min  mean[+/-sd] median   max\r\nConnect:        0    0   0.0      0       0\r\nProcessing:     2    4   4.1      3      43\r\nWaiting:        2    4   4.1      3      43\r\nTotal:          2    4   4.1      3      43\r\n\r\nPercentage of the requests served within a certain time (ms)\r\n  50%      3\r\n  66%      4\r\n  75%      4\r\n  80%      4\r\n  90%      5\r\n  95%      5\r\n  98%      6\r\n  99%     43\r\n 100%     43 (longest request)\r\n```\r\n\r\n![screenshot_20171206_084711](https://user-images.githubusercontent.com/41941/33650434-42cae8ac-da62-11e7-825d-592b32693369.png)\r\n\r\n- [ ] Add documentation.\r\n- [ ] Add tests.\r\n- [ ] Add a changelog entry.\r\n- [ ] Add your name in the contributors file.\r\n- [ ] If you changed the HTTP API, update the [API_VERSION](https://github.com/Kinto/kinto/blob/master/kinto/__init__.py#L15) constant and add an API changelog entry [in the docs](https://github.com/Kinto/kinto/blob/master/docs/api/index.rst)\r\n- [ ] If you added a new configuration setting, update the [`kinto.tpl`](https://github.com/Kinto/kinto/blob/master/kinto/config/kinto.tpl) file with it.\r\n","created_at":"2017-12-06T07:49:47Z","updated_at":"2017-12-13T11:04:16Z","closed_at":null,"merged_at":null,"merge_commit_sha":"c7f6459586d546f1f14a63dac6de4f0886e614d3","assignee":null,"assignees":[],"requested_reviewers":[],"milestone":null,"commits_url":"https://api.github.com/repos/Kinto/kinto/pulls/1413/commits","review_comments_url":"https://api.github.com/repos/Kinto/kinto/pulls/1413/comments","review_comment_url":"https://api.github.com/repos/Kinto/kinto/pulls/comments{/number}","comments_url":"https://api.github.com/repos/Kinto/kinto/issues/1413/comments","statuses_url":"https://api.github.com/repos/Kinto/kinto/statuses/95a4df00514bcf6717a34df2d7a5887dbda76913","head":{"label":"Stanley:master","ref":"master","sha":"95a4df00514bcf6717a34df2d7a5887dbda76913","user":{"login":"Stanley","id":41941,"avatar_url":"https://avatars1.githubusercontent.com/u/41941?v=4","gravatar_id":"","url":"https://api.github.com/users/Stanley","html_url":"https://github.com/Stanley","followers_url":"https://api.github.com/users/Stanley/followers","following_url":"https://api.github.com/users/Stanley/following{/other_user}","gists_url":"https://api.github.com/users/Stanley/gists{/gist_id}","starred_url":"https://api.github.com/users/Stanley/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/Stanley/subscriptions","organizations_url":"https://api.github.com/users/Stanley/orgs","repos_url":"https://api.github.com/users/Stanley/repos","events_url":"https://api.github.com/users/Stanley/events{/privacy}","received_events_url":"https://api.github.com/users/Stanley/received_events","type":"User","site_admin":false},"repo":{"id":113282738,"name":"kinto","full_name":"Stanley/kinto","owner":{"login":"Stanley","id":41941,"avatar_url":"https://avatars1.githubusercontent.com/u/41941?v=4","gravatar_id":"","url":"https://api.github.com/users/Stanley","html_url":"https://github.com/Stanley","followers_url":"https://api.github.com/users/Stanley/followers","following_url":"https://api.github.com/users/Stanley/following{/other_user}","gists_url":"https://api.github.com/users/Stanley/gists{/gist_id}","starred_url":"https://api.github.com/users/Stanley/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/Stanley/subscriptions","organizations_url":"https://api.github.com/users/Stanley/orgs","repos_url":"https://api.github.com/users/Stanley/repos","events_url":"https://api.github.com/users/Stanley/events{/privacy}","received_events_url":"https://api.github.com/users/Stanley/received_events","type":"User","site_admin":false},"private":false,"html_url":"https://github.com/Stanley/kinto","description":"A generic JSON document store with sharing and synchronisation capabilities.","fork":true,"url":"https://api.github.com/repos/Stanley/kinto","forks_url":"https://api.github.com/repos/Stanley/kinto/forks","keys_url":"https://api.github.com/repos/Stanley/kinto/keys{/key_id}","collaborators_url":"https://api.github.com/repos/Stanley/kinto/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/Stanley/kinto/teams","hooks_url":"https://api.github.com/repos/Stanley/kinto/hooks","issue_events_url":"https://api.github.com/repos/Stanley/kinto/issues/events{/number}","events_url":"https://api.github.com/repos/Stanley/kinto/events","assignees_url":"https://api.github.com/repos/Stanley/kinto/assignees{/user}","branches_url":"https://api.github.com/repos/Stanley/kinto/branches{/branch}","tags_url":"https://api.github.com/repos/Stanley/kinto/tags","blobs_url":"https://api.github.com/repos/Stanley/kinto/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/Stanley/kinto/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/Stanley/kinto/git/refs{/sha}","trees_url":"https://api.github.com/repos/Stanley/kinto/git/trees{/sha}","statuses_url":"https://api.github.com/repos/Stanley/kinto/statuses/{sha}","languages_url":"https://api.github.com/repos/Stanley/kinto/languages","stargazers_url":"https://api.github.com/repos/Stanley/kinto/stargazers","contributors_url":"https://api.github.com/repos/Stanley/kinto/contributors","subscribers_url":"https://api.github.com/repos/Stanley/kinto/subscribers","subscription_url":"https://api.github.com/repos/Stanley/kinto/subscription","commits_url":"https://api.github.com/repos/Stanley/kinto/commits{/sha}","git_commits_url":"https://api.github.com/repos/Stanley/kinto/git/commits{/sha}","comments_url":"https://api.github.com/repos/Stanley/kinto/comments{/number}","issue_comment_url":"https://api.github.com/repos/Stanley/kinto/issues/comments{/number}","contents_url":"https://api.github.com/repos/Stanley/kinto/contents/{+path}","compare_url":"https://api.github.com/repos/Stanley/kinto/compare/{base}...{head}","merges_url":"https://api.github.com/repos/Stanley/kinto/merges","archive_url":"https://api.github.com/repos/Stanley/kinto/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/Stanley/kinto/downloads","issues_url":"https://api.github.com/repos/Stanley/kinto/issues{/number}","pulls_url":"https://api.github.com/repos/Stanley/kinto/pulls{/number}","milestones_url":"https://api.github.com/repos/Stanley/kinto/milestones{/number}","notifications_url":"https://api.github.com/repos/Stanley/kinto/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/Stanley/kinto/labels{/name}","releases_url":"https://api.github.com/repos/Stanley/kinto/releases{/id}","deployments_url":"https://api.github.com/repos/Stanley/kinto/deployments","created_at":"2017-12-06T07:19:56Z","updated_at":"2017-12-06T07:19:59Z","pushed_at":"2017-12-11T07:32:08Z","git_url":"git://github.com/Stanley/kinto.git","ssh_url":"git@github.com:Stanley/kinto.git","clone_url":"https://github.com/Stanley/kinto.git","svn_url":"https://github.com/Stanley/kinto","homepage":"http://docs.kinto-storage.org/","size":22023,"stargazers_count":0,"watchers_count":0,"language":"Python","has_issues":false,"has_projects":true,"has_downloads":true,"has_wiki":true,"has_pages":false,"forks_count":0,"mirror_url":null,"archived":false,"open_issues_count":0,"license":null,"forks":0,"open_issues":0,"watchers":0,"default_branch":"master"}},"base":{"label":"Kinto:master","ref":"master","sha":"cc60c56ec5e3481db7c7be241441895591ec6459","user":{"login":"Kinto","id":13413813,"avatar_url":"https://avatars2.githubusercontent.com/u/13413813?v=4","gravatar_id":"","url":"https://api.github.com/users/Kinto","html_url":"https://github.com/Kinto","followers_url":"https://api.github.com/users/Kinto/followers","following_url":"https://api.github.com/users/Kinto/following{/other_user}","gists_url":"https://api.github.com/users/Kinto/gists{/gist_id}","starred_url":"https://api.github.com/users/Kinto/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/Kinto/subscriptions","organizations_url":"https://api.github.com/users/Kinto/orgs","repos_url":"https://api.github.com/users/Kinto/repos","events_url":"https://api.github.com/users/Kinto/events{/privacy}","received_events_url":"https://api.github.com/users/Kinto/received_events","type":"Organization","site_admin":false},"repo":{"id":31315021,"name":"kinto","full_name":"Kinto/kinto","owner":{"login":"Kinto","id":13413813,"avatar_url":"https://avatars2.githubusercontent.com/u/13413813?v=4","gravatar_id":"","url":"https://api.github.com/users/Kinto","html_url":"https://github.com/Kinto","followers_url":"https://api.github.com/users/Kinto/followers","following_url":"https://api.github.com/users/Kinto/following{/other_user}","gists_url":"https://api.github.com/users/Kinto/gists{/gist_id}","starred_url":"https://api.github.com/users/Kinto/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/Kinto/subscriptions","organizations_url":"https://api.github.com/users/Kinto/orgs","repos_url":"https://api.github.com/users/Kinto/repos","events_url":"https://api.github.com/users/Kinto/events{/privacy}","received_events_url":"https://api.github.com/users/Kinto/received_events","type":"Organization","site_admin":false},"private":false,"html_url":"https://github.com/Kinto/kinto","description":"A generic JSON document store with sharing and synchronisation capabilities.","fork":false,"url":"https://api.github.com/repos/Kinto/kinto","forks_url":"https://api.github.com/repos/Kinto/kinto/forks","keys_url":"https://api.github.com/repos/Kinto/kinto/keys{/key_id}","collaborators_url":"https://api.github.com/repos/Kinto/kinto/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/Kinto/kinto/teams","hooks_url":"https://api.github.com/repos/Kinto/kinto/hooks","issue_events_url":"https://api.github.com/repos/Kinto/kinto/issues/events{/number}","events_url":"https://api.github.com/repos/Kinto/kinto/events","assignees_url":"https://api.github.com/repos/Kinto/kinto/assignees{/user}","branches_url":"https://api.github.com/repos/Kinto/kinto/branches{/branch}","tags_url":"https://api.github.com/repos/Kinto/kinto/tags","blobs_url":"https://api.github.com/repos/Kinto/kinto/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/Kinto/kinto/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/Kinto/kinto/git/refs{/sha}","trees_url":"https://api.github.com/repos/Kinto/kinto/git/trees{/sha}","statuses_url":"https://api.github.com/repos/Kinto/kinto/statuses/{sha}","languages_url":"https://api.github.com/repos/Kinto/kinto/languages","stargazers_url":"https://api.github.com/repos/Kinto/kinto/stargazers","contributors_url":"https://api.github.com/repos/Kinto/kinto/contributors","subscribers_url":"https://api.github.com/repos/Kinto/kinto/subscribers","subscription_url":"https://api.github.com/repos/Kinto/kinto/subscription","commits_url":"https://api.github.com/repos/Kinto/kinto/commits{/sha}","git_commits_url":"https://api.github.com/repos/Kinto/kinto/git/commits{/sha}","comments_url":"https://api.github.com/repos/Kinto/kinto/comments{/number}","issue_comment_url":"https://api.github.com/repos/Kinto/kinto/issues/comments{/number}","contents_url":"https://api.github.com/repos/Kinto/kinto/contents/{+path}","compare_url":"https://api.github.com/repos/Kinto/kinto/compare/{base}...{head}","merges_url":"https://api.github.com/repos/Kinto/kinto/merges","archive_url":"https://api.github.com/repos/Kinto/kinto/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/Kinto/kinto/downloads","issues_url":"https://api.github.com/repos/Kinto/kinto/issues{/number}","pulls_url":"https://api.github.com/repos/Kinto/kinto/pulls{/number}","milestones_url":"https://api.github.com/repos/Kinto/kinto/milestones{/number}","notifications_url":"https://api.github.com/repos/Kinto/kinto/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/Kinto/kinto/labels{/name}","releases_url":"https://api.github.com/repos/Kinto/kinto/releases{/id}","deployments_url":"https://api.github.com/repos/Kinto/kinto/deployments","created_at":"2015-02-25T13:34:23Z","updated_at":"2017-12-13T03:33:30Z","pushed_at":"2017-12-12T06:36:14Z","git_url":"git://github.com/Kinto/kinto.git","ssh_url":"git@github.com:Kinto/kinto.git","clone_url":"https://github.com/Kinto/kinto.git","svn_url":"https://github.com/Kinto/kinto","homepage":"http://docs.kinto-storage.org/","size":22074,"stargazers_count":3344,"watchers_count":3344,"language":"Python","has_issues":true,"has_projects":true,"has_downloads":true,"has_wiki":true,"has_pages":false,"forks_count":252,"mirror_url":null,"archived":false,"open_issues_count":76,"license":{"key":"other","name":"Other","spdx_id":null,"url":null},"forks":252,"open_issues":76,"watchers":3344,"default_branch":"master"}},"_links":{"self":{"href":"https://api.github.com/repos/Kinto/kinto/pulls/1413"},"html":{"href":"https://github.com/Kinto/kinto/pull/1413"},"issue":{"href":"https://api.github.com/repos/Kinto/kinto/issues/1413"},"comments":{"href":"https://api.github.com/repos/Kinto/kinto/issues/1413/comments"},"review_comments":{"href":"https://api.github.com/repos/Kinto/kinto/pulls/1413/comments"},"review_comment":{"href":"https://api.github.com/repos/Kinto/kinto/pulls/comments{/number}"},"commits":{"href":"https://api.github.com/repos/Kinto/kinto/pulls/1413/commits"},"statuses":{"href":"https://api.github.com/repos/Kinto/kinto/statuses/95a4df00514bcf6717a34df2d7a5887dbda76913"}},"author_association":"NONE"}}
{"actor":{"display_login":"Stanley"}}