Skip to content

Commit 9b65aa4

Browse files
committed
got the presentation in good shape -- added examples, etc.
1 parent 35f0cec commit 9b65aa4

File tree

12 files changed

+1380
-286
lines changed

12 files changed

+1380
-286
lines changed

_downloads/CircularReferenceExample.ipynb

Lines changed: 833 additions & 0 deletions
Large diffs are not rendered by default.

_downloads/circular.py

Lines changed: 89 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,89 @@
1+
#!/usr/bin/env python
2+
# -*- coding: utf-8 -*-
3+
4+
import sys
5+
import weakref
6+
import gc
7+
8+
deleted_object_messages = []
9+
10+
11+
class MyChild(object):
12+
def __init__(self, parent):
13+
self.parent = parent
14+
#self.parent = weakref.ref(parent)
15+
#self.parent = weakref.proxy(parent)
16+
17+
## store some data so it will use appreciable memory
18+
## multiply by 1234 to avoid interning
19+
self.data = [1234*i for i in range(100000)]
20+
21+
def __del__(self):
22+
deleted_object_messages.append( ('MyChild deleted', id(self)) )
23+
24+
25+
class MyParent(object):
26+
def __init__(self):
27+
self.children = []
28+
def addChild(self):
29+
child = MyChild(self)
30+
self.children.append(child)
31+
return child
32+
def __del__(self):
33+
deleted_object_messages.append( ('MyParent deleted', id(self)) )
34+
35+
if __name__ == "__main__":
36+
37+
p = MyParent()
38+
39+
print "refcount for p:", sys.getrefcount(p)
40+
assert sys.getrefcount(p) == 2
41+
42+
a = p.addChild()
43+
a2 = p.addChild()
44+
print "refcount for p after adding an two children:", sys.getrefcount(p)
45+
assert sys.getrefcount(p) == 2
46+
47+
print "p's children:", p.children
48+
assert len(p.children) == 2
49+
50+
print " a is:", a
51+
print "a's parent:", a.parent
52+
print "a's parent's children:", a.parent.children
53+
54+
assert a is a.parent.children[0]
55+
assert a2 is a.parent.children[1]
56+
57+
58+
print "a's refcount:", sys.getrefcount(a)
59+
assert sys.getrefcount(a) == 3
60+
61+
print "a2's refcount:", sys.getrefcount(a2)
62+
assert sys.getrefcount(a2) == 3
63+
64+
del p
65+
print "after deleting p:"
66+
67+
print "a's refcount:", sys.getrefcount(a)
68+
assert sys.getrefcount(a) == 2
69+
70+
print "a2's refcount:", sys.getrefcount(a2)
71+
assert sys.getrefcount(a2) == 2
72+
73+
print "deleting a:"
74+
id_a = id(a)
75+
del a
76+
print deleted_object_messages
77+
assert deleted_object_messages[-1][0] == 'MyChild deleted'
78+
assert deleted_object_messages[-1][1] == id_a
79+
80+
print "deleting a2:"
81+
id_a2 = id(a2)
82+
del a2
83+
print deleted_object_messages
84+
assert deleted_object_messages[-1][0] == 'MyChild deleted'
85+
assert deleted_object_messages[-1][1] == id_a2
86+
87+
88+
89+

_downloads/mem_check.py

Lines changed: 109 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,109 @@
1+
"""
2+
mem_check.py
3+
4+
functions for getting memoroy use of the current python process
5+
6+
Windows and *nix versions
7+
8+
USAGE:
9+
10+
amount = get_mem_use(units='MB') # options are KB, MB, GB
11+
12+
"""
13+
14+
import sys
15+
16+
div = {'GB': 1024*1024*1024,
17+
'MB': 1024*1024,
18+
'KB': 1024,
19+
}
20+
21+
if sys.platform.startswith('win'):
22+
23+
"""
24+
25+
Functions for getting memory usage of Windows processes.
26+
27+
from:
28+
29+
http://code.activestate.com/recipes/578513-get-memory-usage-of-windows-processes-using-getpro/
30+
31+
get_mem_use(units='MB') is the one to get memory use for the current process.
32+
33+
34+
"""
35+
import ctypes
36+
from ctypes import wintypes
37+
38+
GetCurrentProcess = ctypes.windll.kernel32.GetCurrentProcess
39+
GetCurrentProcess.argtypes = []
40+
GetCurrentProcess.restype = wintypes.HANDLE
41+
42+
SIZE_T = ctypes.c_size_t
43+
44+
class PROCESS_MEMORY_COUNTERS_EX(ctypes.Structure):
45+
_fields_ = [
46+
('cb', wintypes.DWORD),
47+
('PageFaultCount', wintypes.DWORD),
48+
('PeakWorkingSetSize', SIZE_T),
49+
('WorkingSetSize', SIZE_T),
50+
('QuotaPeakPagedPoolUsage', SIZE_T),
51+
('QuotaPagedPoolUsage', SIZE_T),
52+
('QuotaPeakNonPagedPoolUsage', SIZE_T),
53+
('QuotaNonPagedPoolUsage', SIZE_T),
54+
('PagefileUsage', SIZE_T),
55+
('PeakPagefileUsage', SIZE_T),
56+
('PrivateUsage', SIZE_T),
57+
]
58+
59+
GetProcessMemoryInfo = ctypes.windll.psapi.GetProcessMemoryInfo
60+
GetProcessMemoryInfo.argtypes = [
61+
wintypes.HANDLE,
62+
ctypes.POINTER(PROCESS_MEMORY_COUNTERS_EX),
63+
wintypes.DWORD,
64+
]
65+
GetProcessMemoryInfo.restype = wintypes.BOOL
66+
67+
def get_current_process():
68+
"""Return handle to current process."""
69+
return GetCurrentProcess()
70+
71+
def get_memory_info(process=None):
72+
"""Return Win32 process memory counters structure as a dict."""
73+
if process is None:
74+
process = get_current_process()
75+
counters = PROCESS_MEMORY_COUNTERS_EX()
76+
ret = GetProcessMemoryInfo(process, ctypes.byref(counters),
77+
ctypes.sizeof(counters))
78+
if not ret:
79+
raise ctypes.WinError()
80+
info = dict((name, getattr(counters, name))
81+
for name, _ in counters._fields_)
82+
return info
83+
84+
def get_mem_use(units='MB'):
85+
"""
86+
returns the total memory use of the current python process
87+
88+
:param units='MB': the units you want the reslut in. Options are:
89+
'GB', 'MB', 'KB'
90+
"""
91+
info = get_memory_info()
92+
return info['PrivateUsage'] / float(div[units])
93+
94+
95+
else: # for posix systems only tested on OS-X for now
96+
def get_mem_use(units='MB'):
97+
"""
98+
returns the total memory use of the current python process
99+
100+
:param units='MB': the units you want the reslut in. Options are:
101+
'GB', 'MB', 'KB'
102+
"""
103+
import resource
104+
#useage = resource.getrusage(resource.RUSAGE_SELF).ru_maxrss
105+
div = {'GB': 1024*1024*1024,
106+
'MB': 1024*1024,
107+
'KB': 1024,
108+
}
109+
return resource.getrusage(resource.RUSAGE_SELF).ru_maxrss / float(div[units])

_downloads/memcount.py

Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
#!/usr/bin/env python
2+
# -*- coding: utf-8 -*-
3+
4+
"""
5+
a simple test of a circular reference that gc.collect() will not clean up.
6+
7+
And watch the memory grow!
8+
9+
"""
10+
11+
12+
import sys
13+
import gc
14+
import weakref
15+
16+
import mem_check
17+
18+
19+
class MyChild(object):
20+
def __init__(self, parent):
21+
self.parent = parent
22+
# if a weak ref is used, then no memory leak.
23+
#self.parent = weakref.proxy(parent)
24+
25+
## store some data so it will use appreciable memory
26+
## multiply by 1234 to reduce interning
27+
self.data = [1234*i for i in range(100000)]
28+
29+
def __del__(self):
30+
""" __del__ defined to defeat GC"""
31+
print 'MyChild deleted', id(self)
32+
33+
34+
class MyParent(object):
35+
def __init__(self):
36+
self.children = []
37+
def addChild(self):
38+
child = MyChild(self)
39+
self.children.append(child)
40+
return child
41+
def __del__(self):
42+
""" __del__ defined to defeat GC"""
43+
print 'MyParent deleted', id(self)
44+
45+
46+
if __name__ == "__main__":
47+
48+
# create a bunch in a loop:
49+
for i in range(50):
50+
print "iteration:", i
51+
p = MyParent()
52+
p.addChild()
53+
p.addChild()
54+
p.addChild()
55+
print "ref count:", sys.getrefcount(p)
56+
print "mem_use: %f MB"%mem_check.get_mem_use()
57+
del p
58+
gc.collect()

_downloads/simple_circular.py

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
#!/usr/bin/env python
2+
3+
"""
4+
Simple contrived example of circular reference counting
5+
"""
6+
7+
import sys
8+
import di
9+
import gc
10+
11+
l1 = [1,]
12+
l2 = [2,]
13+
14+
l1_id = id(l1)
15+
l2_id = id(l2)
16+
17+
print "initial ref counts:"
18+
print "l1:", sys.getrefcount(l1)
19+
print "l2:", sys.getrefcount(l2)
20+
21+
print "now add the circular references:"
22+
l1.append(l2)
23+
l2.append(l1)
24+
25+
print "ref counts after the circular reference is added"
26+
print "l1:", sys.getrefcount(l1)
27+
print "l2:", sys.getrefcount(l2)
28+
29+
print "delete one"
30+
del l1
31+
print "l1:", sys.getrefcount(l2)
32+
33+
print "delete the other"
34+
del l2
35+
36+
print "are they still there?"
37+
print "l1's refcount:", di.ref_by_id(l1_id)
38+
print "l2's refcount:", di.ref_by_id(l2_id)
39+
print "-- yes they are!"
40+
41+
print "now run the garbage collector"
42+
print "It collected:", gc.collect(), "objects"
43+
44+
print "ref counts now???"
45+
print "l1's refcount:", di.ref_by_id(l1_id)
46+
print "l2's refcount:", di.ref_by_id(l2_id)
47+
48+
print "yup -- they'll get cleaned up"
49+
50+
51+
52+

_sources/index.txt

Lines changed: 9 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -3,21 +3,14 @@ In This Collection
33

44
.. ifslides::
55

6-
+----------------------+-----------------------+
7-
| Topics: | Materials: |
8-
+======================+=======================+
9-
| .. toctree:: | .. toctree:: |
10-
| :maxdepth: 1 | :maxdepth: 1 |
11-
| | |
12-
| session01 | supplements/index |
13-
| session02 | |
14-
| session03 | |
15-
| session04 | |
16-
| session05 | |
17-
| session06 | |
18-
| session07 | |
19-
| session08 | |
20-
+----------------------+-----------------------+
6+
+----------------------+
7+
| Topics: |
8+
+======================+
9+
| .. toctree:: |
10+
| :maxdepth: 1 |
11+
| |
12+
| weak_references |
13+
+----------------------+
2114

2215
.. ifnotslides::
2316

@@ -29,19 +22,11 @@ In This Collection
2922

3023
weak_references
3124

32-
Materials:
33-
----------
34-
35-
.. toctree::
36-
:maxdepth: 2
37-
38-
supplements/index
39-
4025
.. rst-class:: credit
4126

4227
These materials copyright Christopher H. Barker
4328

44-
Licenced under the Creative Commons Attribution-ShareAlike 4.0 International Public License.
29+
Licensed under the Creative Commons Attribution-ShareAlike 4.0 International Public License.
4530

4631
https://creativecommons.org/licenses/by-sa/4.0/legalcode
4732

0 commit comments

Comments
 (0)