Skip to content

Commit 9f8bc85

Browse files
authored
FEATURE: Add more control over io management (#564)
1 parent f91191c commit 9f8bc85

File tree

2 files changed

+81
-19
lines changed

2 files changed

+81
-19
lines changed

src/ansys/edb/core/utility/io_manager.py

Lines changed: 33 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
import abc
33
from collections import defaultdict
44
from contextlib import contextmanager
5-
from enum import Enum, auto
5+
from enum import Enum, Flag, auto
66
from sys import modules
77

88
from ansys.api.edb.v1.edb_messages_pb2 import EDBObjCollectionMessage, EDBObjMessage
@@ -77,6 +77,7 @@ def __init__(self):
7777
self._response_cache = {}
7878
self._msg_type_cache = {}
7979
self._cached_edb_objs = {}
80+
self._allow_invalidation = True
8081

8182
def _extract_msg_from_any_module_msg(self, any_module_msg):
8283
msg_type_name = any_module_msg.any.TypeName()
@@ -126,7 +127,7 @@ def _hijack_request(self, service_name, rpc_name, request):
126127
return self._response_cache.get(self._generate_cache_key(service_name, rpc_name, request))
127128

128129
def invalidate(self):
129-
if not self._response_cache:
130+
if not self._response_cache or not self.allow_invalidation:
130131
return
131132
self._response_cache.clear()
132133
self._cached_edb_objs = self._cached_edb_objs.fromkeys(self._cached_edb_objs, False)
@@ -153,6 +154,14 @@ def refresh_for_request(self):
153154
for msg in response.items:
154155
self.add_from_cache_msg(msg)
155156

157+
@property
158+
def allow_invalidation(self):
159+
return self._allow_invalidation
160+
161+
@allow_invalidation.setter
162+
def allow_invalidation(self, allow):
163+
self._allow_invalidation = allow
164+
156165

157166
class _Buffer(_IOOptimizer):
158167
class _BufferEntry:
@@ -181,6 +190,7 @@ def _reset(self):
181190
self._buffer = []
182191
self._futures = defaultdict(list)
183192
self._invalidate_cache = False
193+
self._allow_flushing = True
184194

185195
def _hijack_request(self, service_name, rpc_name, request):
186196
if (rpc_info := get_rpc_info(service_name, rpc_name)) is None or rpc_info.is_read:
@@ -203,7 +213,7 @@ def _buffer_request_iterator(buffer):
203213
)
204214

205215
def flush(self):
206-
if not self._buffer:
216+
if not self._buffer or not self.allow_flushing:
207217
return
208218
with self.block():
209219
if (cache := get_cache()) is not None and self._invalidate_cache:
@@ -225,6 +235,14 @@ def add_future_ref(self, future):
225235
def _reset_after_block(self):
226236
self._reset()
227237

238+
@property
239+
def allow_flushing(self):
240+
return self._allow_flushing
241+
242+
@allow_flushing.setter
243+
def allow_flushing(self, allow):
244+
self._allow_flushing = allow
245+
228246

229247
class ServerNotification(Enum):
230248
"""Provides an enum representing the types of server notifications."""
@@ -234,12 +252,15 @@ class ServerNotification(Enum):
234252
RESET_FUTURE_TRACKING = auto()
235253

236254

237-
class IOMangementType(Enum):
255+
class IOMangementType(Flag):
238256
"""Provides an enum representing the types of IO management modes."""
239257

240258
READ = auto()
241259
WRITE = auto()
242-
READ_AND_WRITE = auto()
260+
READ_AND_WRITE = READ | WRITE
261+
NO_CACHE_INVALIDATION = auto()
262+
NO_BUFFER_FLUSHING = auto()
263+
NO_CACHE_INVALIDATION_NO_BUFFER_FLUSHING = NO_CACHE_INVALIDATION | NO_BUFFER_FLUSHING
243264

244265

245266
class _ActiveRequestEdbObjMsgMgr:
@@ -286,16 +307,21 @@ def _enable_caching(enable):
286307
_get_io_manager_stub().EnableCache(bool_message(enable))
287308

288309
def start_managing(self, mode):
289-
if mode == IOMangementType.READ or mode == IOMangementType.READ_AND_WRITE:
310+
if IOMangementType.READ in mode:
290311
self._cache = _Cache()
291312
self._enable_caching(True)
292-
if mode == IOMangementType.WRITE or mode == IOMangementType.READ_AND_WRITE:
313+
if IOMangementType.WRITE in mode:
293314
self._buffer = _Buffer()
315+
if IOMangementType.NO_CACHE_INVALIDATION in mode:
316+
self._cache.allow_invalidation = False
317+
if IOMangementType.NO_BUFFER_FLUSHING in mode:
318+
self._buffer.allow_flushing = False
294319

295320
def end_managing(self):
296321
if self._cache is not None:
297322
self._enable_caching(False)
298323
if self._buffer is not None:
324+
self._buffer.allow_flushing = True
299325
self._buffer.flush()
300326
self._reset()
301327

tests/e2e/scratch/io_performance_scratch.py

Lines changed: 48 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -6,16 +6,18 @@
66
from ansys.edb.core.layer.layer import LayerType
77
from ansys.edb.core.layer.stackup_layer import StackupLayer
88
from ansys.edb.core.layout.cell import Cell, CellType
9+
from ansys.edb.core.layout.layout import Layout
910
from ansys.edb.core.net.net import Net
1011
from ansys.edb.core.primitive.rectangle import Rectangle, RectangleRepresentationType
1112
from ansys.edb.core.session import session
1213
from ansys.edb.core.utility.io_manager import IOMangementType, enable_io_manager
14+
import tests.e2e.settings as settings
1315

1416
db_name = "io_performance_test.aedb"
1517
lyr_name = "signal_1"
1618
net_name = "net_1"
1719
db = None
18-
lyt = None
20+
lyt: Layout = None
1921

2022

2123
def query_prims():
@@ -31,7 +33,7 @@ def query_prims():
3133

3234

3335
def create_prims():
34-
num_prims = 10000
36+
num_prims = 1000
3537
for i in range(num_prims):
3638
rect = Rectangle.create(
3739
lyt,
@@ -103,18 +105,52 @@ def teardown():
103105
Database.delete(db_name)
104106

105107

108+
def caching_flushing_blocking_test():
109+
blocking_start = time()
110+
with enable_io_manager(
111+
IOMangementType.READ_AND_WRITE | IOMangementType.NO_CACHE_INVALIDATION_NO_BUFFER_FLUSHING
112+
):
113+
for prim in lyt.primitives:
114+
rect: Rectangle = prim
115+
geom = rect.polygon_data
116+
ll = geom.points[3]
117+
ur = geom.points[1]
118+
scaled_geom = geom.scale(2, (((ur.x - ll.x) / 2) + ll.x, ((ur.y - ll.y) / 2) + ll.y))
119+
scaled_ll = scaled_geom.points[3]
120+
scaled_ur = scaled_geom.points[1]
121+
rect.set_parameters(
122+
RectangleRepresentationType.LOWER_LEFT_UPPER_RIGHT,
123+
scaled_ll.x,
124+
scaled_ll.y,
125+
scaled_ur.x,
126+
scaled_ur.y,
127+
0,
128+
0,
129+
)
130+
blocking_end = time()
131+
print(f"total blocking time: {blocking_end - blocking_start} seconds")
132+
133+
134+
def read_write_test():
135+
rw_start = time()
136+
num_created_prims = write_test()
137+
num_queried_prims = read_test()
138+
prim_io_op_counts = read_and_write_test()
139+
rw_end = time()
140+
total_created_prims = num_created_prims + prim_io_op_counts[0]
141+
total_queried_prims = num_queried_prims + prim_io_op_counts[1]
142+
print(
143+
f"total rw time: {rw_end - rw_start} seconds (created {total_queried_prims} primitives, "
144+
f"queried {total_created_prims} primitives)"
145+
)
146+
147+
106148
if __name__ == "__main__":
107-
with session(settings.server_exe_dir(), 50051):
149+
with session(settings.server_exe_dir()):
108150
setup()
109151
start = time()
110-
num_created_prims = write_test()
111-
num_queried_prims = read_test()
112-
prim_io_op_counts = read_and_write_test()
152+
read_write_test()
153+
caching_flushing_blocking_test()
113154
end = time()
114-
total_created_prims = num_created_prims + prim_io_op_counts[0]
115-
total_queried_prims = num_queried_prims + prim_io_op_counts[1]
116-
print(
117-
f"total time: {end - start} seconds (created {total_queried_prims} primitives, "
118-
f"queried {total_created_prims} primitives)"
119-
)
155+
print(f"total time: {end - start} seconds")
120156
teardown()

0 commit comments

Comments
 (0)