11# Test for memory leaks surrounding deletion of values.
2- # SEE: https://github.com/aio-libs/multidict/issues/1232
3- # We want to make sure that bad predictions or bougus claims
4- # can be prevented in the future.
2+ # SEE: https://github.com/aio-libs/multidict/issues/1232
3+ # We want to make sure that bad predictions or bougus claims
4+ # of memory leaks can be prevented in the future.
55
66import gc
77import sys
88import psutil
99import os
1010import ctypes
1111from multidict import MultiDict
12+ from typing import Optional
1213
13- # Code was borrowed for testing with windows
14+
15+ # Code was borrowed for testing with windows and other operating systems respectively.
1416# SEE: https://stackoverflow.com/a/79150440
1517
16- def trim_windows_process_memory (pid : int = None ) -> bool :
18+
19+ def trim_windows_process_memory (pid : Optional [int ] = None ) -> bool :
1720 """Causes effect similar to malloc_trim on -nix."""
1821
1922 SIZE_T = ctypes .c_uint32 if ctypes .sizeof (ctypes .c_void_p ) == 4 else ctypes .c_uint64
@@ -22,9 +25,9 @@ def trim_windows_process_memory(pid: int = None) -> bool:
2225 if not pid :
2326 pid = ctypes .windll .kernel32 .GetCurrentProcess ()
2427
25- # Sometimes FileNotFoundError can appear so the code was
28+ # Sometimes FileNotFoundError can appear so the code was
2629 # changed to handle that workaround.
27-
30+
2831 ctypes .windll .kernel32 .SetProcessWorkingSetSizeEx .argtypes = [
2932 ctypes .c_void_p , # Process handle
3033 SIZE_T , # Minimum working set size
@@ -37,14 +40,15 @@ def trim_windows_process_memory(pid: int = None) -> bool:
3740 QUOTA_LIMITS_HARDWS_MIN_DISABLE = 0x00000002
3841
3942 # Attempt to set the working set size
40- if not ctypes .windll .kernel32 .SetProcessWorkingSetSizeEx (pid , SIZE_T (- 1 ), SIZE_T (- 1 ), QUOTA_LIMITS_HARDWS_MIN_DISABLE ):
43+ if not ctypes .windll .kernel32 .SetProcessWorkingSetSizeEx (
44+ pid , SIZE_T (- 1 ), SIZE_T (- 1 ), QUOTA_LIMITS_HARDWS_MIN_DISABLE
45+ ):
4146 # Retrieve the error code
4247 error_code = ctypes .windll .kernel32 .GetLastError ()
4348 # let's print it since we aren't using a logger...
4449 print (f"SetProcessWorkingSetSizeEx failed with error code: { error_code } " )
4550 return False
4651 return True
47-
4852
4953
5054def trim_ram () -> None :
@@ -60,63 +64,69 @@ def trim_ram() -> None:
6064 except Exception as e :
6165 print (" attempt failed" )
6266 raise e
63-
64- def get_memory_usage ():
67+
68+
69+ def get_memory_usage () -> int :
6570 process = psutil .Process (os .getpid ())
6671 memory_info = process .memory_info ()
67- return memory_info .rss / (1024 * 1024 )
72+ return memory_info .rss / (1024 * 1024 ) # type: ignore[no-any-return]
73+
6874
6975keys = [f"X-Any-{ i } " for i in range (1000 )]
7076headers = {key : key * 2 for key in keys }
7177
7278
73- def check_for_leak ():
79+ def check_for_leak () -> None :
7480 trim_ram ()
7581 usage = get_memory_usage ()
7682 # We should never go over 100MB
7783 if usage > 100 :
7884 sys .exit (1 )
7985
8086
81- def _test_pop ():
87+ def _test_pop () -> None :
8288 for _ in range (10 ):
8389 for _ in range (1000 ):
8490 result = MultiDict (headers )
8591 for k in keys :
8692 result .pop (k )
8793 check_for_leak ()
8894
89- def _test_popall ():
95+
96+ def _test_popall () -> None :
9097 for _ in range (10 ):
9198 for _ in range (1000 ):
9299 result = MultiDict (headers )
93100 for k in keys :
94101 result .popall (k )
95102 check_for_leak ()
96103
97- def _test_popone ():
104+
105+ def _test_popone () -> None :
98106 for _ in range (10 ):
99107 for _ in range (1000 ):
100108 result = MultiDict (headers )
101109 for k in keys :
102110 result .popone (k )
103111 check_for_leak ()
104112
105- def _test_del ():
113+
114+ def _test_del () -> None :
106115 for _ in range (10 ):
107116 for _ in range (1000 ):
108117 result = MultiDict (headers )
109118 for k in keys :
110119 del result [k ]
111120 check_for_leak ()
112121
122+
113123def _run_isolated_case () -> None :
114124 _test_pop ()
115125 _test_popall ()
116126 _test_popone ()
117127 _test_del ()
118128 sys .exit (0 )
119129
130+
120131if __name__ == "__main__" :
121132 _run_isolated_case ()
122-
0 commit comments