Created
April 17, 2021 23:52
-
-
Save kfsone/26101a25339aaf0d3a1ed2b159eb1b21 to your computer and use it in GitHub Desktop.
Optimizations in Python
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
{ | |
"cells": [ | |
{ | |
"cell_type": "markdown", | |
"metadata": {}, | |
"source": [ | |
"The original hubris-constructed version." | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": 1, | |
"metadata": {}, | |
"outputs": [], | |
"source": [ | |
"def to_str(s: str) -> str:\n", | |
" return str(\"%s\" % str(s))" | |
] | |
}, | |
{ | |
"cell_type": "markdown", | |
"metadata": {}, | |
"source": [ | |
"The first 'fix' by the last-person-to-touch-it." | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": 2, | |
"metadata": {}, | |
"outputs": [], | |
"source": [ | |
"def just_str(s: str) -> str:\n", | |
" return str(s) # protect against someone passing a non-string in future." | |
] | |
}, | |
{ | |
"cell_type": "markdown", | |
"metadata": {}, | |
"source": [ | |
"When it was asserted \"it's always a string\"..." | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": 3, | |
"metadata": {}, | |
"outputs": [], | |
"source": [ | |
"def its_a_str(s: str) -> str:\n", | |
" return s" | |
] | |
}, | |
{ | |
"cell_type": "markdown", | |
"metadata": {}, | |
"source": [ | |
"Benchmark tests" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": 4, | |
"metadata": {}, | |
"outputs": [], | |
"source": [ | |
"def f1(s: str) -> bool:\n", | |
" s = to_str(s)\n", | |
" if \"OK\" in s: return True\n", | |
" return False \n", | |
"\n", | |
"def f2(s: str) -> bool:\n", | |
" if \"OK\" in just_str(s): return True\n", | |
" return False\n", | |
"\n", | |
"def f3(s: str) -> bool:\n", | |
" if \"OK\" in its_a_str(s): return True\n", | |
" \n", | |
"def f4(s: str) -> bool:\n", | |
" return \"OK\" in s" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": 5, | |
"metadata": {}, | |
"outputs": [ | |
{ | |
"name": "stdout", | |
"output_type": "stream", | |
"text": [ | |
"319 ns ± 18.6 ns per loop (mean ± std. dev. of 7 runs, 1000000 loops each)\n", | |
"205 ns ± 13.8 ns per loop (mean ± std. dev. of 7 runs, 10000000 loops each)\n", | |
"140 ns ± 9.88 ns per loop (mean ± std. dev. of 7 runs, 10000000 loops each)\n", | |
"and f4\n", | |
"93.9 ns ± 8.62 ns per loop (mean ± std. dev. of 7 runs, 10000000 loops each)\n" | |
] | |
} | |
], | |
"source": [ | |
"# Pathological cases\n", | |
"%timeit f1(\"feature set 32 is BROKEN\")\n", | |
"%timeit f2(\"feature set 32 is BROKEN\")\n", | |
"%timeit f3(\"feature set 32 is BROKEN\")\n", | |
"print(\"and f4\")\n", | |
"%timeit f4(\"feature set 32 is BROKEN\")" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": 6, | |
"metadata": {}, | |
"outputs": [ | |
{ | |
"name": "stdout", | |
"output_type": "stream", | |
"text": [ | |
"43.2 ns ± 5.82 ns per loop (mean ± std. dev. of 7 runs, 10000000 loops each)\n" | |
] | |
} | |
], | |
"source": [ | |
"# But, you know, it's only ever used in one place, so: what if...\n", | |
"%timeit \"OK\" in \"feature set 32 is BROKEN\"" | |
] | |
}, | |
{ | |
"cell_type": "markdown", | |
"metadata": {}, | |
"source": [ | |
"Lets look under the hood." | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": 7, | |
"metadata": {}, | |
"outputs": [ | |
{ | |
"name": "stdout", | |
"output_type": "stream", | |
"text": [ | |
" 2 0 LOAD_GLOBAL 0 (str)\n", | |
" 2 LOAD_CONST 1 ('%s')\n", | |
" 4 LOAD_GLOBAL 0 (str)\n", | |
" 6 LOAD_FAST 0 (s)\n", | |
" 8 CALL_FUNCTION 1\n", | |
" 10 BINARY_MODULO\n", | |
" 12 CALL_FUNCTION 1\n", | |
" 14 RETURN_VALUE\n", | |
"---\n", | |
" 2 0 LOAD_GLOBAL 0 (to_str)\n", | |
" 2 LOAD_FAST 0 (s)\n", | |
" 4 CALL_FUNCTION 1\n", | |
" 6 STORE_FAST 0 (s)\n", | |
"\n", | |
" 3 8 LOAD_CONST 1 ('OK')\n", | |
" 10 LOAD_FAST 0 (s)\n", | |
" 12 CONTAINS_OP 0\n", | |
" 14 POP_JUMP_IF_FALSE 20\n", | |
" 16 LOAD_CONST 2 (True)\n", | |
" 18 RETURN_VALUE\n", | |
"\n", | |
" 4 >> 20 LOAD_CONST 3 (False)\n", | |
" 22 RETURN_VALUE\n" | |
] | |
} | |
], | |
"source": [ | |
"import dis # part of python's standard library\n", | |
"dis.dis(to_str)\n", | |
"print(\"---\")\n", | |
"dis.dis(f1)" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": 8, | |
"metadata": {}, | |
"outputs": [ | |
{ | |
"name": "stdout", | |
"output_type": "stream", | |
"text": [ | |
" 2 0 LOAD_GLOBAL 0 (str)\n", | |
" 2 LOAD_FAST 0 (s)\n", | |
" 4 CALL_FUNCTION 1\n", | |
" 6 RETURN_VALUE\n", | |
"---\n", | |
" 7 0 LOAD_CONST 1 ('OK')\n", | |
" 2 LOAD_GLOBAL 0 (just_str)\n", | |
" 4 LOAD_FAST 0 (s)\n", | |
" 6 CALL_FUNCTION 1\n", | |
" 8 CONTAINS_OP 0\n", | |
" 10 POP_JUMP_IF_FALSE 16\n", | |
" 12 LOAD_CONST 2 (True)\n", | |
" 14 RETURN_VALUE\n", | |
"\n", | |
" 8 >> 16 LOAD_CONST 3 (False)\n", | |
" 18 RETURN_VALUE\n" | |
] | |
} | |
], | |
"source": [ | |
"dis.dis(just_str)\n", | |
"print(\"---\")\n", | |
"dis.dis(f2)" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": 9, | |
"metadata": {}, | |
"outputs": [ | |
{ | |
"name": "stdout", | |
"output_type": "stream", | |
"text": [ | |
" 2 0 LOAD_FAST 0 (s)\n", | |
" 2 RETURN_VALUE\n", | |
"---\n", | |
" 11 0 LOAD_CONST 1 ('OK')\n", | |
" 2 LOAD_GLOBAL 0 (its_a_str)\n", | |
" 4 LOAD_FAST 0 (s)\n", | |
" 6 CALL_FUNCTION 1\n", | |
" 8 CONTAINS_OP 0\n", | |
" 10 POP_JUMP_IF_FALSE 16\n", | |
" 12 LOAD_CONST 2 (True)\n", | |
" 14 RETURN_VALUE\n", | |
" >> 16 LOAD_CONST 0 (None)\n", | |
" 18 RETURN_VALUE\n" | |
] | |
} | |
], | |
"source": [ | |
"dis.dis(its_a_str)\n", | |
"print(\"---\")\n", | |
"dis.dis(f3)" | |
] | |
}, | |
{ | |
"cell_type": "markdown", | |
"metadata": {}, | |
"source": [ | |
"The last function, `f4` makes no function call" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": 10, | |
"metadata": {}, | |
"outputs": [ | |
{ | |
"name": "stdout", | |
"output_type": "stream", | |
"text": [ | |
" 14 0 LOAD_CONST 1 ('OK')\n", | |
" 2 LOAD_FAST 0 (s)\n", | |
" 4 CONTAINS_OP 0\n", | |
" 6 RETURN_VALUE\n" | |
] | |
} | |
], | |
"source": [ | |
"dis.dis(f4)" | |
] | |
}, | |
{ | |
"cell_type": "markdown", | |
"metadata": {}, | |
"source": [ | |
"*However* it is worth noting the delta `f3(s)`->`f4(s)` and `f4(s)`->`\"OK\" in s` is ~40ns, and the commonality between the two is primarily the elision of a function call." | |
] | |
} | |
], | |
"metadata": { | |
"kernelspec": { | |
"display_name": "Python 3", | |
"language": "python", | |
"name": "python3" | |
}, | |
"language_info": { | |
"codemirror_mode": { | |
"name": "ipython", | |
"version": 3 | |
}, | |
"file_extension": ".py", | |
"mimetype": "text/x-python", | |
"name": "python", | |
"nbconvert_exporter": "python", | |
"pygments_lexer": "ipython3", | |
"version": "3.9.2" | |
} | |
}, | |
"nbformat": 4, | |
"nbformat_minor": 4 | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment