Skip to content

Commit

Permalink
Merge pull request #31 from shunsvineyard/thread_safe
Browse files Browse the repository at this point in the history
Add performance example for multithreading.
  • Loading branch information
Shun Huang authored Jan 10, 2022
2 parents 729c298 + ba48ddc commit 8f07a01
Show file tree
Hide file tree
Showing 3 changed files with 269 additions and 1 deletion.
184 changes: 184 additions & 0 deletions diagrams/multithreading_avl.drawio
Original file line number Diff line number Diff line change
@@ -0,0 +1,184 @@
<mxfile host="65bd71144e">
<diagram id="lAOmGaG2XEw7mNDvjgDq" name="Page-1">
<mxGraphModel dx="1292" dy="789" grid="1" gridSize="10" guides="1" tooltips="1" connect="1" arrows="1" fold="1" page="1" pageScale="1" pageWidth="850" pageHeight="1100" math="0" shadow="0">
<root>
<mxCell id="0"/>
<mxCell id="1" parent="0"/>
<mxCell id="2" value="" style="rounded=0;whiteSpace=wrap;html=1;fillColor=#FFFFFF;strokeColor=none;" vertex="1" parent="1">
<mxGeometry x="60" y="190" width="880" height="260" as="geometry"/>
</mxCell>
<mxCell id="3" value="37" style="ellipse;whiteSpace=wrap;html=1;aspect=fixed;strokeColor=#006EAF;strokeWidth=2;fillColor=#1ba1e2;fontColor=#ffffff;" vertex="1" parent="1">
<mxGeometry x="240" y="200" width="40" height="40" as="geometry"/>
</mxCell>
<mxCell id="4" value="23" style="ellipse;whiteSpace=wrap;html=1;aspect=fixed;strokeColor=#006EAF;strokeWidth=2;fillColor=#1ba1e2;fontColor=#ffffff;" vertex="1" parent="1">
<mxGeometry x="160" y="260" width="40" height="40" as="geometry"/>
</mxCell>
<mxCell id="5" value="35" style="ellipse;whiteSpace=wrap;html=1;aspect=fixed;strokeColor=#006EAF;strokeWidth=2;fillColor=#1ba1e2;fontColor=#ffffff;" vertex="1" parent="1">
<mxGeometry x="280" y="390" width="40" height="40" as="geometry"/>
</mxCell>
<mxCell id="6" value="33" style="ellipse;whiteSpace=wrap;html=1;aspect=fixed;strokeColor=#006EAF;strokeWidth=2;fillColor=#1ba1e2;fontColor=#ffffff;" vertex="1" parent="1">
<mxGeometry x="220" y="320" width="40" height="40" as="geometry"/>
</mxCell>
<mxCell id="7" value="17" style="ellipse;whiteSpace=wrap;html=1;aspect=fixed;strokeColor=#006EAF;strokeWidth=2;fillColor=#1ba1e2;fontColor=#ffffff;" vertex="1" parent="1">
<mxGeometry x="100" y="320" width="40" height="40" as="geometry"/>
</mxCell>
<mxCell id="8" value="41" style="ellipse;whiteSpace=wrap;html=1;aspect=fixed;strokeColor=#006EAF;strokeWidth=2;fillColor=#1ba1e2;fontColor=#ffffff;" vertex="1" parent="1">
<mxGeometry x="320" y="260" width="40" height="40" as="geometry"/>
</mxCell>
<mxCell id="9" value="" style="endArrow=none;html=1;strokeColor=#000000;" edge="1" parent="1" source="7" target="4">
<mxGeometry width="50" height="50" relative="1" as="geometry">
<mxPoint x="170" y="520" as="sourcePoint"/>
<mxPoint x="220" y="470" as="targetPoint"/>
</mxGeometry>
</mxCell>
<mxCell id="10" value="" style="endArrow=none;html=1;strokeColor=#000000;" edge="1" parent="1" source="6" target="4">
<mxGeometry width="50" height="50" relative="1" as="geometry">
<mxPoint x="180" y="530" as="sourcePoint"/>
<mxPoint x="230" y="480" as="targetPoint"/>
</mxGeometry>
</mxCell>
<mxCell id="11" value="" style="endArrow=none;html=1;strokeColor=#000000;" edge="1" parent="1" source="8" target="3">
<mxGeometry width="50" height="50" relative="1" as="geometry">
<mxPoint x="190" y="540" as="sourcePoint"/>
<mxPoint x="240" y="490" as="targetPoint"/>
</mxGeometry>
</mxCell>
<mxCell id="12" value="" style="endArrow=none;html=1;strokeColor=#000000;" edge="1" parent="1" source="4" target="3">
<mxGeometry width="50" height="50" relative="1" as="geometry">
<mxPoint x="200" y="550" as="sourcePoint"/>
<mxPoint x="250" y="500" as="targetPoint"/>
</mxGeometry>
</mxCell>
<mxCell id="13" value="" style="endArrow=classic;html=1;strokeColor=#000000;dashed=1;" edge="1" parent="1" source="5">
<mxGeometry width="50" height="50" relative="1" as="geometry">
<mxPoint x="258.9442719099991" y="402.1114561800018" as="sourcePoint"/>
<mxPoint x="260" y="360" as="targetPoint"/>
</mxGeometry>
</mxCell>
<mxCell id="14" value="&lt;font color=&quot;#000000&quot;&gt;2&lt;/font&gt;" style="text;html=1;strokeColor=none;fillColor=none;align=center;verticalAlign=middle;whiteSpace=wrap;rounded=0;" vertex="1" parent="1">
<mxGeometry x="250" y="240" width="20" height="20" as="geometry"/>
</mxCell>
<mxCell id="15" value="&lt;font color=&quot;#000000&quot;&gt;BF: 1&lt;/font&gt;" style="text;html=1;strokeColor=none;fillColor=none;align=center;verticalAlign=middle;whiteSpace=wrap;rounded=0;" vertex="1" parent="1">
<mxGeometry x="200" y="210" width="40" height="20" as="geometry"/>
</mxCell>
<mxCell id="16" value="&lt;font color=&quot;#000000&quot;&gt;BF: 0&lt;/font&gt;" style="text;html=1;strokeColor=none;fillColor=none;align=center;verticalAlign=middle;whiteSpace=wrap;rounded=0;" vertex="1" parent="1">
<mxGeometry x="120" y="270" width="40" height="20" as="geometry"/>
</mxCell>
<mxCell id="17" value="&lt;font color=&quot;#000000&quot;&gt;BF: 0&lt;/font&gt;" style="text;html=1;strokeColor=none;fillColor=none;align=center;verticalAlign=middle;whiteSpace=wrap;rounded=0;" vertex="1" parent="1">
<mxGeometry x="360" y="270" width="40" height="20" as="geometry"/>
</mxCell>
<mxCell id="18" value="&lt;font color=&quot;#000000&quot;&gt;BF: 0&lt;/font&gt;" style="text;html=1;strokeColor=none;fillColor=none;align=center;verticalAlign=middle;whiteSpace=wrap;rounded=0;" vertex="1" parent="1">
<mxGeometry x="260" y="330" width="40" height="20" as="geometry"/>
</mxCell>
<mxCell id="19" value="&lt;font color=&quot;#000000&quot;&gt;BF: 0&lt;/font&gt;" style="text;html=1;strokeColor=none;fillColor=none;align=center;verticalAlign=middle;whiteSpace=wrap;rounded=0;" vertex="1" parent="1">
<mxGeometry x="60" y="330" width="40" height="20" as="geometry"/>
</mxCell>
<mxCell id="20" value="&lt;font color=&quot;#000000&quot;&gt;0&lt;/font&gt;" style="text;html=1;strokeColor=none;fillColor=none;align=center;verticalAlign=middle;whiteSpace=wrap;rounded=0;" vertex="1" parent="1">
<mxGeometry x="330" y="300" width="20" height="20" as="geometry"/>
</mxCell>
<mxCell id="21" value="&lt;font color=&quot;#000000&quot;&gt;1&lt;/font&gt;" style="text;html=1;strokeColor=none;fillColor=none;align=center;verticalAlign=middle;whiteSpace=wrap;rounded=0;" vertex="1" parent="1">
<mxGeometry x="170" y="300" width="20" height="20" as="geometry"/>
</mxCell>
<mxCell id="22" value="&lt;font color=&quot;#000000&quot;&gt;0&lt;/font&gt;" style="text;html=1;strokeColor=none;fillColor=none;align=center;verticalAlign=middle;whiteSpace=wrap;rounded=0;" vertex="1" parent="1">
<mxGeometry x="230" y="360" width="20" height="20" as="geometry"/>
</mxCell>
<mxCell id="23" value="&lt;font color=&quot;#000000&quot;&gt;0&lt;/font&gt;" style="text;html=1;strokeColor=none;fillColor=none;align=center;verticalAlign=middle;whiteSpace=wrap;rounded=0;" vertex="1" parent="1">
<mxGeometry x="110" y="360" width="20" height="20" as="geometry"/>
</mxCell>
<mxCell id="24" value="&lt;font color=&quot;#000000&quot;&gt;0&lt;/font&gt;" style="text;html=1;strokeColor=none;fillColor=none;align=center;verticalAlign=middle;whiteSpace=wrap;rounded=0;" vertex="1" parent="1">
<mxGeometry x="290" y="430" width="20" height="20" as="geometry"/>
</mxCell>
<mxCell id="25" value="&lt;font color=&quot;#000000&quot;&gt;After Insert&lt;/font&gt;" style="html=1;shadow=0;dashed=0;align=center;verticalAlign=middle;shape=mxgraph.arrows2.arrow;dy=0.6;dx=40;notch=0;strokeColor=none;fillColor=#FFD966;" vertex="1" parent="1">
<mxGeometry x="420" y="270" width="100" height="70" as="geometry"/>
</mxCell>
<mxCell id="82" value="37" style="ellipse;whiteSpace=wrap;html=1;aspect=fixed;strokeWidth=2;fillColor=#1ba1e2;fontColor=#ffffff;strokeColor=#FF8000;" vertex="1" parent="1">
<mxGeometry x="800" y="260" width="40" height="40" as="geometry"/>
</mxCell>
<mxCell id="83" value="23" style="ellipse;whiteSpace=wrap;html=1;aspect=fixed;strokeWidth=2;fillColor=#1ba1e2;fontColor=#ffffff;strokeColor=#FF8000;" vertex="1" parent="1">
<mxGeometry x="640" y="260" width="40" height="40" as="geometry"/>
</mxCell>
<mxCell id="84" value="35" style="ellipse;whiteSpace=wrap;html=1;aspect=fixed;strokeColor=#006EAF;strokeWidth=2;fillColor=#1ba1e2;fontColor=#ffffff;" vertex="1" parent="1">
<mxGeometry x="740" y="320" width="40" height="40" as="geometry"/>
</mxCell>
<mxCell id="85" value="33" style="ellipse;whiteSpace=wrap;html=1;aspect=fixed;strokeWidth=2;fillColor=#1ba1e2;fontColor=#ffffff;strokeColor=#FF8000;" vertex="1" parent="1">
<mxGeometry x="720" y="200" width="40" height="40" as="geometry"/>
</mxCell>
<mxCell id="86" value="17" style="ellipse;whiteSpace=wrap;html=1;aspect=fixed;strokeColor=#006EAF;strokeWidth=2;fillColor=#1ba1e2;fontColor=#ffffff;" vertex="1" parent="1">
<mxGeometry x="580" y="320" width="40" height="40" as="geometry"/>
</mxCell>
<mxCell id="87" value="41" style="ellipse;whiteSpace=wrap;html=1;aspect=fixed;strokeColor=#006EAF;strokeWidth=2;fillColor=#1ba1e2;fontColor=#ffffff;" vertex="1" parent="1">
<mxGeometry x="860" y="320" width="40" height="40" as="geometry"/>
</mxCell>
<mxCell id="88" value="" style="endArrow=none;html=1;strokeColor=#000000;" edge="1" parent="1" source="86" target="83">
<mxGeometry width="50" height="50" relative="1" as="geometry">
<mxPoint x="1050" y="960" as="sourcePoint"/>
<mxPoint x="1100" y="910" as="targetPoint"/>
</mxGeometry>
</mxCell>
<mxCell id="89" value="" style="endArrow=none;html=1;strokeColor=#000000;" edge="1" parent="1" source="85" target="83">
<mxGeometry width="50" height="50" relative="1" as="geometry">
<mxPoint x="1060" y="970" as="sourcePoint"/>
<mxPoint x="1110" y="920" as="targetPoint"/>
</mxGeometry>
</mxCell>
<mxCell id="90" value="" style="endArrow=none;html=1;strokeColor=#000000;" edge="1" parent="1" source="87" target="82">
<mxGeometry width="50" height="50" relative="1" as="geometry">
<mxPoint x="1070" y="980" as="sourcePoint"/>
<mxPoint x="1120" y="930" as="targetPoint"/>
</mxGeometry>
</mxCell>
<mxCell id="91" value="" style="endArrow=none;html=1;strokeColor=#000000;" edge="1" parent="1" source="85" target="82">
<mxGeometry width="50" height="50" relative="1" as="geometry">
<mxPoint x="710" y="580" as="sourcePoint"/>
<mxPoint x="1130" y="940" as="targetPoint"/>
</mxGeometry>
</mxCell>
<mxCell id="92" value="" style="endArrow=none;html=1;strokeColor=#000000;endFill=0;" edge="1" parent="1" source="84" target="82">
<mxGeometry width="50" height="50" relative="1" as="geometry">
<mxPoint x="1028.944271909999" y="862.1114561800018" as="sourcePoint"/>
<mxPoint x="1030" y="820" as="targetPoint"/>
</mxGeometry>
</mxCell>
<mxCell id="93" value="&lt;font color=&quot;#97d077&quot;&gt;2&lt;/font&gt;" style="text;html=1;strokeColor=none;fillColor=none;align=center;verticalAlign=middle;whiteSpace=wrap;rounded=0;" vertex="1" parent="1">
<mxGeometry x="730" y="240" width="20" height="20" as="geometry"/>
</mxCell>
<mxCell id="94" value="&lt;font color=&quot;#97d077&quot;&gt;BF: 0&lt;/font&gt;" style="text;html=1;strokeColor=none;fillColor=none;align=center;verticalAlign=middle;whiteSpace=wrap;rounded=0;" vertex="1" parent="1">
<mxGeometry x="680" y="210" width="40" height="20" as="geometry"/>
</mxCell>
<mxCell id="95" value="&lt;font color=&quot;#000000&quot;&gt;BF: 0&lt;/font&gt;" style="text;html=1;strokeColor=none;fillColor=none;align=center;verticalAlign=middle;whiteSpace=wrap;rounded=0;" vertex="1" parent="1">
<mxGeometry x="600" y="270" width="40" height="20" as="geometry"/>
</mxCell>
<mxCell id="96" value="&lt;font color=&quot;#000000&quot;&gt;BF: 0&lt;/font&gt;" style="text;html=1;strokeColor=none;fillColor=none;align=center;verticalAlign=middle;whiteSpace=wrap;rounded=0;" vertex="1" parent="1">
<mxGeometry x="900" y="330" width="40" height="20" as="geometry"/>
</mxCell>
<mxCell id="97" value="&lt;font color=&quot;#97d077&quot;&gt;BF: 0&lt;/font&gt;" style="text;html=1;strokeColor=none;fillColor=none;align=center;verticalAlign=middle;whiteSpace=wrap;rounded=0;" vertex="1" parent="1">
<mxGeometry x="760" y="270" width="40" height="20" as="geometry"/>
</mxCell>
<mxCell id="98" value="&lt;font color=&quot;#000000&quot;&gt;BF: 0&lt;/font&gt;" style="text;html=1;strokeColor=none;fillColor=none;align=center;verticalAlign=middle;whiteSpace=wrap;rounded=0;" vertex="1" parent="1">
<mxGeometry x="540" y="330" width="40" height="20" as="geometry"/>
</mxCell>
<mxCell id="99" value="&lt;font color=&quot;#000000&quot;&gt;0&lt;/font&gt;" style="text;html=1;strokeColor=none;fillColor=none;align=center;verticalAlign=middle;whiteSpace=wrap;rounded=0;" vertex="1" parent="1">
<mxGeometry x="870" y="360" width="20" height="20" as="geometry"/>
</mxCell>
<mxCell id="100" value="&lt;font color=&quot;#97d077&quot;&gt;1&lt;/font&gt;" style="text;html=1;strokeColor=none;fillColor=none;align=center;verticalAlign=middle;whiteSpace=wrap;rounded=0;" vertex="1" parent="1">
<mxGeometry x="810" y="300" width="20" height="20" as="geometry"/>
</mxCell>
<mxCell id="101" value="&lt;font color=&quot;#000000&quot;&gt;1&lt;/font&gt;" style="text;html=1;strokeColor=none;fillColor=none;align=center;verticalAlign=middle;whiteSpace=wrap;rounded=0;" vertex="1" parent="1">
<mxGeometry x="650" y="300" width="20" height="20" as="geometry"/>
</mxCell>
<mxCell id="102" value="&lt;font color=&quot;#000000&quot;&gt;0&lt;/font&gt;" style="text;html=1;strokeColor=none;fillColor=none;align=center;verticalAlign=middle;whiteSpace=wrap;rounded=0;" vertex="1" parent="1">
<mxGeometry x="590" y="360" width="20" height="20" as="geometry"/>
</mxCell>
<mxCell id="103" value="&lt;font color=&quot;#000000&quot;&gt;0&lt;/font&gt;" style="text;html=1;strokeColor=none;fillColor=none;align=center;verticalAlign=middle;whiteSpace=wrap;rounded=0;" vertex="1" parent="1">
<mxGeometry x="750" y="360" width="20" height="20" as="geometry"/>
</mxCell>
<mxCell id="104" value="&lt;font color=&quot;#000000&quot;&gt;BF: 0&lt;/font&gt;" style="text;html=1;strokeColor=none;fillColor=none;align=center;verticalAlign=middle;whiteSpace=wrap;rounded=0;" vertex="1" parent="1">
<mxGeometry x="700" y="330" width="40" height="20" as="geometry"/>
</mxCell>
<mxCell id="106" value="&lt;font color=&quot;#000000&quot;&gt;BF: Balance Factor&lt;/font&gt;" style="text;html=1;strokeColor=none;fillColor=none;align=center;verticalAlign=middle;whiteSpace=wrap;rounded=0;" vertex="1" parent="1">
<mxGeometry x="810" y="410" width="110" height="20" as="geometry"/>
</mxCell>
</root>
</mxGraphModel>
</diagram>
</mxfile>
2 changes: 1 addition & 1 deletion examples/multithreading_not_safe.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@
red_black_tree.RBTree,
]

# Use a very ssmall thread switch interval to increase the chance that
# Use a very small thread switch interval to increase the chance that
# we can reveal the multithreading issue easily.
sys.setswitchinterval(0.0000001)

Expand Down
84 changes: 84 additions & 0 deletions examples/multithreading_performance.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
"""Module to measure the performance using multithreading."""
import threading
import time

from typing import Any, List, Optional
from forest.binary_trees import avl_tree


class TestAVLTree(avl_tree.AVLTree):
"""Test AVL Tree with an unnecessary lock."""

def __init__(self) -> None:
avl_tree.AVLTree.__init__(self)
self._lock = threading.Lock()

def search(self, key: Any) -> Optional[avl_tree.Node]:
"""Query a node with an unnecessary lock."""
with self._lock:
return avl_tree.AVLTree.search(self, key=key)


def query_data(tree: avl_tree.AVLTree, data: List) -> None:
"""Query nodes from a tree."""
for key in data:
tree.search(key=key)


def multithreading_simulator(tree: avl_tree.AVLTree, total_nodes: int) -> float:
"""Use two threads to query nodes with different ranges."""
thread1 = threading.Thread(
target=query_data, args=(tree, [item for item in range(total_nodes // 2)])
)

thread2 = threading.Thread(
target=query_data,
args=(tree, [item for item in range(total_nodes // 2, total_nodes)]),
)

start = time.time()
thread1.start()
thread2.start()

thread1.join()
thread2.join()
end = time.time()

return end - start


if __name__ == "__main__":

total_nodes = 200000

original_avl_tree = avl_tree.AVLTree()

# Single thread case
for key in range(total_nodes):
original_avl_tree.insert(key=key, data=str(key))

data = [item for item in range(total_nodes)]
start = time.time()
query_data(tree=original_avl_tree, data=data)
end = time.time()
delta = end - start
print("Single Thread Case")
print(f"Time in seconds: {delta}")

# Multithreads case
delta_with_threads = multithreading_simulator(
tree=original_avl_tree, total_nodes=total_nodes
)
print("Multithread Case")
print(f"Time in seconds: {delta_with_threads}")

# Multithread with lock case
avl_tree_with_lock = TestAVLTree()
for key in range(total_nodes):
avl_tree_with_lock.insert(key=key, data=str(key))

delta_with_lock = multithreading_simulator(
tree=avl_tree_with_lock, total_nodes=total_nodes
)
print("Multithread with Lock Case")
print(f"Time in seconds: {delta_with_lock}")

0 comments on commit 8f07a01

Please sign in to comment.