diff --git a/README.rst b/README.rst index 7f8914c..c6bbe0d 100644 --- a/README.rst +++ b/README.rst @@ -224,43 +224,43 @@ You can run this benchmark on your machine with the following command: python3 ./benchmarks/performance_comparison.py -Here are the results obtained on an Intel Core i5-7500U CPU (2.50GHz) with **Python 3.6.4**. +Here are the results obtained on an AMD 5950x with **Python 3.10.2**. -**Addict** 2.2.1:: +**Addict** 2.4.0:: - instantiate:-------- 271,132 ops per second. - get:---------------- 276,090 ops per second. - get through list:--- 293,773 ops per second. - set:---------------- 300,324 ops per second. - set through list:--- 282,149 ops per second. + instantiate:-------- 773,292 ops per second. + get:---------------- 1,197,604,715 ops per second. + get through list:--- 647,249,139 ops per second. + set:---------------- 130,434,783 ops per second. + set through list:--- 91,240,875 ops per second. -**Box** 3.4.2:: +**Box** 6.0.1:: - instantiate:--------- 4,093,439 ops per second. - get:----------------- 957,069 ops per second. - get through list:---- 164,013 ops per second. - set:----------------- 900,466 ops per second. - set through list:---- 165,522 ops per second. + instantiate:--------- 382,330 ops per second. + get:----------------- 57,853,629 ops per second. + get through list:---- 25,509,119 ops per second. + set:----------------- 29,902,815 ops per second. + set through list:---- 18,625,442 ops per second. **Scalpl** latest:: - instantiate:-------- 183,879,865 ops per second. - get:---------------- 14,941,355 ops per second. - get through list:--- 14,175,349 ops per second. - set:---------------- 11,320,968 ops per second. - set through list:--- 11,956,001 ops per second. + instantiate:-------- 367,421,940 ops per second. + get:---------------- 71,882,113 ops per second. + get through list:--- 37,406,484 ops per second. + set:---------------- 68,681,318 ops per second. + set through list:--- 40,647,652 ops per second. **dict**:: - instantiate:--------- 37,816,714 ops per second. - get:----------------- 84,317,032 ops per second. - get through list:---- 62,480,474 ops per second. - set:----------------- 146,484,375 ops per second. - set through list :--- 122,473,974 ops per second. + instantiate:--------- 612,870,255 ops per second. + get:----------------- 1,675,977,835 ops per second. + get through list:---- 746,268,647 ops per second. + set:----------------- 1,388,888,605 ops per second. + set through list :--- 798,934,707 ops per second. As a conclusion and despite being an order of magniture slower than the built-in diff --git a/benchmarks/perfomance_comparison.py b/benchmarks/perfomance_comparison.py index afcd004..a9fa13e 100644 --- a/benchmarks/perfomance_comparison.py +++ b/benchmarks/perfomance_comparison.py @@ -1,5 +1,4 @@ from copy import deepcopy -import json from timeit import timeit import unittest @@ -7,7 +6,56 @@ from addict import Dict from box import Box -import requests + +PYTHON_REDDIT = { + "kind": "Listing", + "data": { + "modhash": "", + "dist": 27, + "children": [ + { + "kind": "t3", + "data": { + "approved_at_utc": None, "subreddit": "Python", + "selftext": "Top Level comments must be **Job Opportunities.**\n\nPlease include **Location** or any other **Requirements** in your comment. If you require people to work on site in San Francisco, *you must note that in your post.* If you require an Engineering degree, *you must note that in your post*.\n\nPlease include as much information as possible.\n\nIf you are looking for jobs, send a PM to the poster.", + "author_fullname": "t2_628u", "saved": False, + "mod_reason_title": None, "gilded": 0, "clicked": False, "title": "r/Python Job Board", + "link_flair_richtext": [], + "subreddit_name_prefixed": "r/Python", "hidden": False, "pwls": 6, "link_flair_css_class": None, + "downs": 0, "hide_score": False, "name": "t3_cmq4jj", + "quarantine": False, "link_flair_text_color": "dark", "author_flair_background_color": "", + "subreddit_type": "public", "ups": 11, "total_awards_received": 0, + "media_embed": {}, "author_flair_template_id": None, "is_original_content": False, + "user_reports": [], "secure_media": None, + "is_reddit_media_domain": False, "is_meta": False, "category": None, "secure_media_embed": {}, + "link_flair_text": None, "can_mod_post": False, + "score": 11, "approved_by": None, "thumbnail": "", "edited": False, "author_flair_css_class": "", + "author_flair_richtext": [], "gildings": {}, + "content_categories": None, "is_self": True, "mod_note": None, "created": 1565124336.0, + "link_flair_type": "text", "wls": 6, "banned_by": None, + "author_flair_type": "text", "domain": "self.Python", + "allow_live_comments": False, + "selftext_html": "<!-- SC_OFF --><div class=\"md\"><p>Top Level comments must be <strong>Job Opportunities.</strong></p>\n\n<p>Please include <strong>Location</strong> or any other <strong>Requirements</strong> in your comment. If you require people to work on site in San Francisco, <em>you must note that in your post.</em> If you require an Engineering degree, <em>you must note that in your post</em>.</p>\n\n<p>Please include as much information as possible.</p>\n\n<p>If you are looking for jobs, send a PM to the poster.</p>\n</div><!-- SC_ON -->", + "likes": None, "suggested_sort": None, "banned_at_utc": None, "view_count": None, "archived": False, + "no_follow": False, "is_crosspostable": False, "pinned": False, + "over_18": False, "all_awardings": [], "media_only": False, "can_gild": False, "spoiler": False, + "locked": False, "author_flair_text": "reticulated", + "visited": False, "num_reports": None, "distinguished": None, "subreddit_id": "t5_2qh0y", + "mod_reason_by": None, "removal_reason": None, "link_flair_background_color": "", + "id": "cmq4jj", "is_robot_indexable": True, "report_reasons": None, "author": "aphoenix", + "num_crossposts": 0, "num_comments": 2, "send_replies": False, "whitelist_status": "all_ads", + "contest_mode": False, "mod_reports": [], "author_patreon_flair": False, + "author_flair_text_color": "dark", + "permalink": "/r/Python/comments/cmq4jj/rpython_job_board/", "parent_whitelist_status": "all_ads", + "stickied": True, + "url": "https://www.reddit.com/r/Python/comments/cmq4jj/rpython_job_board/", + "subreddit_subscribers": 399170, "created_utc": 1565095536.0, + "discussion_type": None, "media": None, "is_video": False + } + } + ] + } +} class TestDictPerformance(unittest.TestCase): @@ -18,48 +66,15 @@ class TestDictPerformance(unittest.TestCase): # We use a portion of the JSON dump of the Python Reddit page. - PYTHON_REDDIT = { - "kind": "Listing", - "data": { - "modhash": "", - "dist": 27, - "children": [ - { - "kind": "t3", - "data": { - "approved_at_utc": None, "subreddit": "Python", - "selftext": "Top Level comments must be **Job Opportunities.**\n\nPlease include **Location** or any other **Requirements** in your comment. If you require people to work on site in San Francisco, *you must note that in your post.* If you require an Engineering degree, *you must note that in your post*.\n\nPlease include as much information as possible.\n\nIf you are looking for jobs, send a PM to the poster.", - "author_fullname": "t2_628u", "saved": False, - "mod_reason_title": None, "gilded": 0, "clicked": False, "title": "r/Python Job Board", "link_flair_richtext": [], - "subreddit_name_prefixed": "r/Python", "hidden": False, "pwls": 6, "link_flair_css_class": None, "downs": 0, "hide_score": False, "name": "t3_cmq4jj", - "quarantine": False, "link_flair_text_color": "dark", "author_flair_background_color": "", "subreddit_type": "public", "ups": 11, "total_awards_received": 0, - "media_embed": {}, "author_flair_template_id": None, "is_original_content": False, "user_reports": [], "secure_media": None, - "is_reddit_media_domain": False, "is_meta": False, "category": None, "secure_media_embed": {}, "link_flair_text": None, "can_mod_post": False, - "score": 11, "approved_by": None, "thumbnail": "", "edited": False, "author_flair_css_class": "", "author_flair_richtext": [], "gildings": {}, - "content_categories": None, "is_self": True, "mod_note": None, "created": 1565124336.0, "link_flair_type": "text", "wls": 6, "banned_by": None, - "author_flair_type": "text", "domain": "self.Python", - "allow_live_comments": False, - "selftext_html": "<!-- SC_OFF --><div class=\"md\"><p>Top Level comments must be <strong>Job Opportunities.</strong></p>\n\n<p>Please include <strong>Location</strong> or any other <strong>Requirements</strong> in your comment. If you require people to work on site in San Francisco, <em>you must note that in your post.</em> If you require an Engineering degree, <em>you must note that in your post</em>.</p>\n\n<p>Please include as much information as possible.</p>\n\n<p>If you are looking for jobs, send a PM to the poster.</p>\n</div><!-- SC_ON -->", - "likes": None, "suggested_sort": None, "banned_at_utc": None, "view_count": None, "archived": False, "no_follow": False, "is_crosspostable": False, "pinned": False, - "over_18": False, "all_awardings": [], "media_only": False, "can_gild": False, "spoiler": False, "locked": False, "author_flair_text": "reticulated", - "visited": False, "num_reports": None, "distinguished": None, "subreddit_id": "t5_2qh0y", "mod_reason_by": None, "removal_reason": None, "link_flair_background_color": "", - "id": "cmq4jj", "is_robot_indexable": True, "report_reasons": None, "author": "aphoenix", "num_crossposts": 0, "num_comments": 2, "send_replies": False, "whitelist_status": "all_ads", - "contest_mode": False, "mod_reports": [], "author_patreon_flair": False, "author_flair_text_color": "dark", - "permalink": "/r/Python/comments/cmq4jj/rpython_job_board/", "parent_whitelist_status": "all_ads", "stickied": True, - "url": "https://www.reddit.com/r/Python/comments/cmq4jj/rpython_job_board/", "subreddit_subscribers": 399170, "created_utc": 1565095536.0, - "discussion_type": None, "media": None, "is_video": False - } - } - ] - } - } + namespace = { - 'Wrapper': dict + 'Wrapper': dict, + 'Built': dict(deepcopy(PYTHON_REDDIT)) } def setUp(self): - self.data = deepcopy(self.PYTHON_REDDIT) + self.data = deepcopy(PYTHON_REDDIT) self.namespace.update(self=self) def execute(self, statement, method): @@ -79,21 +94,21 @@ def test_init(self): self.execute('Wrapper(self.data)', 'instantiate') def test_getitem(self): - self.execute("Wrapper(self.data)['data']['modhash']", 'get') + self.execute("Built['data']['modhash']", 'get') def test_getitem_through_list(self): statement = ( - "Wrapper(self.data)['data']['children'][0]['data']['author']" + "Built['data']['children'][0]['data']['author']" ) self.execute(statement, 'get through list') def test_setitem(self): - statement = "Wrapper(self.data)['data']['modhash'] = 'dunno'" + statement = "Built['data']['modhash'] = 'dunno'" self.execute(statement, 'set') def test_setitem_through_list(self): statement = ( - "Wrapper(self.data)['data']['children'][0]" + "Built['data']['children'][0]" "['data']['author'] = 'Captain Obvious'" ) self.execute(statement, 'set through list') @@ -102,25 +117,26 @@ def test_setitem_through_list(self): class TestCutPerformance(TestDictPerformance): namespace = { - 'Wrapper': Cut + 'Wrapper': Cut, + 'Built': Cut(deepcopy(PYTHON_REDDIT)) } def test_getitem(self): - self.execute("Wrapper(self.data)['data.modhash']", 'get') + self.execute("Built['data.modhash']", 'get') def test_getitem_through_list(self): statement = ( - "Wrapper(self.data)['data.children[0].data.author']" + "Built['data.children[0].data.author']" ) self.execute(statement, 'get through list') def test_setitem(self): - statement = "Wrapper(self.data)['data.modhash'] = 'dunno'" + statement = "Built['data.modhash'] = 'dunno'" self.execute(statement, 'set') def test_setitem_through_list(self): statement = ( - "Wrapper(self.data)['data.children[0]" + "Built['data.children[0]" ".data.author'] = 'Captain Obvious'" ) self.execute(statement, 'set through list') @@ -129,38 +145,36 @@ def test_setitem_through_list(self): class TestBoxPerformance(TestDictPerformance): namespace = { - 'Wrapper': Box + 'Wrapper': Box, + 'Built': Box(deepcopy(PYTHON_REDDIT)) } def test_getitem(self): - self.execute("Wrapper(self.data).data.modhash", 'get - 1st lookup') - self.execute("Wrapper(self.data).data.modhash", 'get - 2nd lookup') + self.execute("Built.data.modhash", 'get') def test_getitem_through_list(self): statement = ( - "Wrapper(self.data).data.children[0].data.author" + "Built.data.children[0].data.author" ) - self.execute(statement, 'get through list - 1st lookup') - self.execute(statement, 'get through list - 2nd lookup') + self.execute(statement, 'get through list') def test_setitem(self): - statement = "Wrapper(self.data).data.modhash = 'dunno'" - self.execute(statement, 'set - 1st lookup') - self.execute(statement, 'set - 2nd lookup') + statement = "Built.data.modhash = 'dunno'" + self.execute(statement, 'set') def test_setitem_through_list(self): statement = ( - "Wrapper(self.data).data.children[0]" + "Built.data.children[0]" ".data.author = 'Captain Obvious'" ) - self.execute(statement, 'set through list - 1st lookup') - self.execute(statement, 'set through list - 2nd lookup') + self.execute(statement, 'set through list') class TestAddictPerformance(TestDictPerformance): namespace = { - 'Wrapper': Dict + 'Wrapper': Dict, + 'Built': Dict(deepcopy(PYTHON_REDDIT)) }