Skip to content

Commit 279f944

Browse files
authored
Reduce proto CopyFrom for deeply nested structures (#440)
Replaces it with populate_x, which is more efficient. CopyFrom with a ref_map (or any other kind of dict) remains, the data there tends to be small so it's probably the least worst option. Negligible effect on performance in practice. Resolves #18
1 parent b3985dd commit 279f944

File tree

8 files changed

+107
-168
lines changed

8 files changed

+107
-168
lines changed

edg/core/Array.py

Lines changed: 7 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -29,13 +29,10 @@ def get_subexprs(self) -> Iterable[Union[ConstraintExpr, BasePort]]:
2929
return [self.container]
3030

3131
@override
32-
def expr_to_proto(self, expr: ConstraintExpr, ref_map: Refable.RefMapType) -> edgir.ValueExpr:
32+
def populate_expr_proto(self, pb: edgir.ValueExpr, expr: ConstraintExpr, ref_map: Refable.RefMapType) -> None:
3333
contained_map = self.container._get_elt_sample()._create_ref_map(edgir.LocalPath())
34-
35-
pb = edgir.ValueExpr()
3634
pb.map_extract.container.ref.CopyFrom(ref_map[self.container]) # TODO support arbitrary refs
3735
pb.map_extract.path.CopyFrom(contained_map[self.elt])
38-
return pb
3936

4037

4138
class FlattenBinding(Binding):
@@ -48,11 +45,9 @@ def get_subexprs(self) -> Iterable[Union[ConstraintExpr, BasePort]]:
4845
return [self.elts]
4946

5047
@override
51-
def expr_to_proto(self, expr: ConstraintExpr, ref_map: Refable.RefMapType) -> edgir.ValueExpr:
52-
pb = edgir.ValueExpr()
48+
def populate_expr_proto(self, pb: edgir.ValueExpr, expr: ConstraintExpr, ref_map: Refable.RefMapType) -> None:
5349
pb.unary_set.op = edgir.UnarySetExpr.Op.FLATTEN
54-
pb.unary_set.vals.CopyFrom(self.elts._expr_to_proto(ref_map))
55-
return pb
50+
self.elts._populate_expr_proto(pb.unary_set.vals, ref_map)
5651

5752

5853
@non_library
@@ -91,8 +86,8 @@ def _get_elt_sample(self) -> BasePort:
9186
return self.target
9287

9388
@override
94-
def _instance_to_proto(self) -> edgir.PortLike:
95-
raise RuntimeError() # this doesn't generate into a library element
89+
def _populate_portlike_proto(self, pb: edgir.PortLike) -> None:
90+
raise RuntimeError() # this can't be a block's port
9691

9792
@override
9893
def _def_to_proto(self) -> edgir.PortTypes:
@@ -184,14 +179,12 @@ def _get_def_name(self) -> str:
184179
raise RuntimeError() # this doesn't generate into a library element
185180

186181
@override
187-
def _instance_to_proto(self) -> edgir.PortLike:
188-
pb = edgir.PortLike()
182+
def _populate_portlike_proto(self, pb: edgir.PortLike) -> None:
189183
pb.array.self_class.target.name = self._elt_sample._get_def_name()
190184
if self._elts is not None:
191185
pb.array.ports.SetInParent() # mark as defined, even if empty
192186
for name, elt in self._elts.items():
193-
edgir.add_pair(pb.array.ports.ports, name).CopyFrom(elt._instance_to_proto())
194-
return pb
187+
elt._populate_portlike_proto(edgir.add_pair(pb.array.ports.ports, name))
195188

196189
@override
197190
def _def_to_proto(self) -> edgir.PortTypes:

edg/core/ArrayExpr.py

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ def get_subexprs(self) -> Iterable[Union[ConstraintExpr, BasePort]]: # element
2323
return []
2424

2525
@override
26-
def expr_to_proto(self, expr: ConstraintExpr, ref_map: Refable.RefMapType) -> edgir.ValueExpr:
26+
def populate_expr_proto(self, pb: edgir.ValueExpr, expr: ConstraintExpr, ref_map: Refable.RefMapType) -> None:
2727
raise ValueError # can't be used directly
2828

2929

@@ -61,10 +61,8 @@ def _to_expr_type(cls: Type[SelfType], input: ArrayCastableType) -> SelfType:
6161

6262
@classmethod
6363
@override
64-
def _decl_to_proto(cls) -> edgir.ValInit:
65-
pb = edgir.ValInit()
66-
pb.array.CopyFrom(cls._elt_type._decl_to_proto())
67-
return pb
64+
def _populate_decl_proto(cls, pb: edgir.ValInit) -> None:
65+
cls._elt_type._populate_decl_proto(pb.array)
6866

6967
@staticmethod
7068
def array_of_elt(elt: ConstraintExpr) -> ArrayExpr:

edg/core/Binding.py

Lines changed: 60 additions & 87 deletions
Original file line numberDiff line numberDiff line change
@@ -75,7 +75,7 @@ def is_bound(self) -> bool:
7575
return True
7676

7777
@abstractmethod
78-
def expr_to_proto(self, expr: ConstraintExpr, ref_map: Refable.RefMapType) -> edgir.ValueExpr: ...
78+
def populate_expr_proto(self, pb: edgir.ValueExpr, expr: ConstraintExpr, ref_map: Refable.RefMapType) -> None: ...
7979

8080
@abstractmethod
8181
def get_subexprs(self) -> Iterable[Union[ConstraintExpr, BasePort]]: ...
@@ -106,10 +106,8 @@ def is_bound(self) -> bool:
106106
return True
107107

108108
@override
109-
def expr_to_proto(self, expr: ConstraintExpr, ref_map: Refable.RefMapType) -> edgir.ValueExpr:
110-
pb = edgir.ValueExpr()
109+
def populate_expr_proto(self, pb: edgir.ValueExpr, expr: ConstraintExpr, ref_map: Refable.RefMapType) -> None:
111110
pb.ref.CopyFrom(ref_map[expr])
112-
return pb
113111

114112

115113
class InitParamBinding(ParamBinding):
@@ -126,6 +124,14 @@ class LiteralBinding(Binding):
126124
def get_subexprs(self) -> Iterable[Union[ConstraintExpr, BasePort]]:
127125
return []
128126

127+
@abstractmethod
128+
def populate_literal_proto(self, pb: edgir.ValueLit) -> None:
129+
raise NotImplementedError
130+
131+
@override
132+
def populate_expr_proto(self, pb: edgir.ValueExpr, expr: ConstraintExpr, ref_map: Refable.RefMapType) -> None:
133+
self.populate_literal_proto(pb.literal)
134+
129135

130136
class BoolLiteralBinding(LiteralBinding):
131137
@override
@@ -137,10 +143,8 @@ def __init__(self, value: bool):
137143
self.value = value
138144

139145
@override
140-
def expr_to_proto(self, expr: ConstraintExpr, ref_map: Refable.RefMapType) -> edgir.ValueExpr:
141-
pb = edgir.ValueExpr()
142-
pb.literal.boolean.val = self.value
143-
return pb
146+
def populate_literal_proto(self, pb: edgir.ValueLit) -> None:
147+
pb.boolean.val = self.value
144148

145149

146150
class IntLiteralBinding(LiteralBinding):
@@ -152,10 +156,8 @@ def __init__(self, value: int):
152156
self.value = value
153157

154158
@override
155-
def expr_to_proto(self, expr: ConstraintExpr, ref_map: Refable.RefMapType) -> edgir.ValueExpr:
156-
pb = edgir.ValueExpr()
157-
pb.literal.integer.val = self.value
158-
return pb
159+
def populate_literal_proto(self, pb: edgir.ValueLit) -> None:
160+
pb.integer.val = self.value
159161

160162

161163
class FloatLiteralBinding(LiteralBinding):
@@ -167,10 +169,8 @@ def __init__(self, value: Union[float, int]):
167169
self.value: float = float(value)
168170

169171
@override
170-
def expr_to_proto(self, expr: ConstraintExpr, ref_map: Refable.RefMapType) -> edgir.ValueExpr:
171-
pb = edgir.ValueExpr()
172-
pb.literal.floating.val = self.value
173-
return pb
172+
def populate_literal_proto(self, pb: edgir.ValueLit) -> None:
173+
pb.floating.val = self.value
174174

175175

176176
class RangeLiteralBinding(LiteralBinding):
@@ -182,11 +182,9 @@ def __init__(self, value: Range):
182182
self.value = value
183183

184184
@override
185-
def expr_to_proto(self, expr: ConstraintExpr, ref_map: Refable.RefMapType) -> edgir.ValueExpr:
186-
pb = edgir.ValueExpr()
187-
pb.literal.range.minimum.floating.val = self.value.lower
188-
pb.literal.range.maximum.floating.val = self.value.upper
189-
return pb
185+
def populate_literal_proto(self, pb: edgir.ValueLit) -> None:
186+
pb.range.minimum.floating.val = self.value.lower
187+
pb.range.maximum.floating.val = self.value.upper
190188

191189

192190
class StringLiteralBinding(LiteralBinding):
@@ -199,10 +197,8 @@ def __init__(self, value: str):
199197
self.value = value
200198

201199
@override
202-
def expr_to_proto(self, expr: ConstraintExpr, ref_map: Refable.RefMapType) -> edgir.ValueExpr:
203-
pb = edgir.ValueExpr()
204-
pb.literal.text.val = self.value
205-
return pb
200+
def populate_literal_proto(self, pb: edgir.ValueLit) -> None:
201+
pb.text.val = self.value
206202

207203

208204
class ArrayLiteralBinding(LiteralBinding):
@@ -215,14 +211,10 @@ def __init__(self, values: Sequence[LiteralBinding]):
215211
self.values = values
216212

217213
@override
218-
def expr_to_proto(self, expr: ConstraintExpr, ref_map: Refable.RefMapType) -> edgir.ValueExpr:
219-
pb = edgir.ValueExpr()
220-
pb.literal.array.SetInParent()
214+
def populate_literal_proto(self, pb: edgir.ValueLit) -> None:
215+
pb.array.SetInParent()
221216
for value in self.values:
222-
elt_value = value.expr_to_proto(expr, ref_map)
223-
assert elt_value.HasField('literal')
224-
pb.literal.array.elts.add().CopyFrom(elt_value.literal)
225-
return pb
217+
value.populate_literal_proto(pb.array.elts.add())
226218

227219

228220
class RangeBuilderBinding(Binding):
@@ -240,15 +232,13 @@ def get_subexprs(self) -> Iterable[Union[ConstraintExpr, BasePort]]:
240232
return chain(self.lower._get_exprs(), self.lower._get_exprs())
241233

242234
@override
243-
def expr_to_proto(self, expr: ConstraintExpr, ref_map: Refable.RefMapType) -> edgir.ValueExpr:
244-
pb = edgir.ValueExpr()
235+
def populate_expr_proto(self, pb: edgir.ValueExpr, expr: ConstraintExpr, ref_map: Refable.RefMapType) -> None:
245236
pb.binary.op = edgir.BinaryExpr.RANGE
246-
pb.binary.lhs.CopyFrom(self.lower._expr_to_proto(ref_map))
247-
pb.binary.rhs.CopyFrom(self.upper._expr_to_proto(ref_map))
248-
return pb
237+
self.lower._populate_expr_proto(pb.binary.lhs, ref_map)
238+
self.upper._populate_expr_proto(pb.binary.rhs, ref_map)
249239

250240

251-
class ArrayBinding(LiteralBinding):
241+
class ArrayBinding(Binding):
252242
@override
253243
def __repr__(self) -> str:
254244
return f"Array({self.values})"
@@ -258,12 +248,14 @@ def __init__(self, values: Sequence[ConstraintExpr]):
258248
self.values = values
259249

260250
@override
261-
def expr_to_proto(self, expr: ConstraintExpr, ref_map: Refable.RefMapType) -> edgir.ValueExpr:
262-
pb = edgir.ValueExpr()
251+
def get_subexprs(self) -> Iterable[Union[ConstraintExpr, BasePort]]:
252+
return self.values
253+
254+
@override
255+
def populate_expr_proto(self, pb: edgir.ValueExpr, expr: ConstraintExpr, ref_map: Refable.RefMapType) -> None:
263256
pb.array.SetInParent()
264257
for value in self.values:
265-
pb.array.vals.add().CopyFrom(value._expr_to_proto(ref_map))
266-
return pb
258+
value._populate_expr_proto(pb.array.vals.add(), ref_map)
267259

268260

269261
class UnaryOpBinding(Binding):
@@ -293,12 +285,9 @@ def get_subexprs(self) -> Iterable[Union[ConstraintExpr, BasePort]]:
293285
return chain(self.src._get_exprs())
294286

295287
@override
296-
def expr_to_proto(self, expr: ConstraintExpr,
297-
ref_map: Refable.RefMapType) -> edgir.ValueExpr:
298-
pb = edgir.ValueExpr()
288+
def populate_expr_proto(self, pb: edgir.ValueExpr, expr: ConstraintExpr, ref_map: Refable.RefMapType) -> None:
299289
pb.unary.op = self.op_map[self.op]
300-
pb.unary.val.CopyFrom(self.src._expr_to_proto(ref_map))
301-
return pb
290+
self.src._populate_expr_proto(pb.unary.val, ref_map)
302291

303292
class UnarySetOpBinding(Binding):
304293
@override
@@ -332,12 +321,9 @@ def get_subexprs(self) -> Iterable[Union[ConstraintExpr, BasePort]]:
332321
return chain(self.src._get_exprs())
333322

334323
@override
335-
def expr_to_proto(self, expr: ConstraintExpr,
336-
ref_map: Refable.RefMapType) -> edgir.ValueExpr:
337-
pb = edgir.ValueExpr()
324+
def populate_expr_proto(self, pb: edgir.ValueExpr, expr: ConstraintExpr, ref_map: Refable.RefMapType) -> None:
338325
pb.unary_set.op = self.op_map[self.op]
339-
pb.unary_set.vals.CopyFrom(self.src._expr_to_proto(ref_map))
340-
return pb
326+
self.src._populate_expr_proto(pb.unary_set.vals, ref_map)
341327

342328
class BinaryOpBinding(Binding):
343329
@override
@@ -385,12 +371,11 @@ def get_subexprs(self) -> Iterable[Union[ConstraintExpr, BasePort]]:
385371
return chain(self.lhs._get_exprs(), self.rhs._get_exprs())
386372

387373
@override
388-
def expr_to_proto(self, expr: ConstraintExpr, ref_map: Refable.RefMapType) -> edgir.ValueExpr:
389-
pb = edgir.ValueExpr()
374+
def populate_expr_proto(self, pb: edgir.ValueExpr, expr: ConstraintExpr, ref_map: Refable.RefMapType) -> None:
390375
pb.binary.op = self.op_map[self.op]
391-
pb.binary.lhs.CopyFrom(self.lhs._expr_to_proto(ref_map))
392-
pb.binary.rhs.CopyFrom(self.rhs._expr_to_proto(ref_map))
393-
return pb
376+
self.lhs._populate_expr_proto(pb.binary.lhs, ref_map)
377+
self.rhs._populate_expr_proto(pb.binary.rhs, ref_map)
378+
394379

395380
class BinarySetOpBinding(Binding):
396381
@override
@@ -417,12 +402,10 @@ def get_subexprs(self) -> Iterable[Union[ConstraintExpr, BasePort]]:
417402
return chain(self.lhset._get_exprs(), self.rhs._get_exprs())
418403

419404
@override
420-
def expr_to_proto(self, expr: ConstraintExpr, ref_map: Refable.RefMapType) -> edgir.ValueExpr:
421-
pb = edgir.ValueExpr()
405+
def populate_expr_proto(self, pb: edgir.ValueExpr, expr: ConstraintExpr, ref_map: Refable.RefMapType) -> None:
422406
pb.binary_set.op = self.op_map[self.op]
423-
pb.binary_set.lhset.CopyFrom(self.lhset._expr_to_proto(ref_map))
424-
pb.binary_set.rhs.CopyFrom(self.rhs._expr_to_proto(ref_map))
425-
return pb
407+
self.lhset._populate_expr_proto(pb.binary_set.lhset, ref_map)
408+
self.rhs._populate_expr_proto(pb.binary_set.rhs, ref_map)
426409

427410

428411
class IfThenElseBinding(Binding):
@@ -441,12 +424,10 @@ def get_subexprs(self) -> Iterable[Union[ConstraintExpr, BasePort]]:
441424
return chain(self.cond._get_exprs(), self.then_val._get_exprs(), self.else_val._get_exprs())
442425

443426
@override
444-
def expr_to_proto(self, expr: ConstraintExpr, ref_map: Refable.RefMapType) -> edgir.ValueExpr:
445-
pb = edgir.ValueExpr()
446-
pb.ifThenElse.cond.CopyFrom(self.cond._expr_to_proto(ref_map))
447-
pb.ifThenElse.tru.CopyFrom(self.then_val._expr_to_proto(ref_map))
448-
pb.ifThenElse.fal.CopyFrom(self.else_val._expr_to_proto(ref_map))
449-
return pb
427+
def populate_expr_proto(self, pb: edgir.ValueExpr, expr: ConstraintExpr, ref_map: Refable.RefMapType) -> None:
428+
self.cond._populate_expr_proto(pb.ifThenElse.cond, ref_map)
429+
self.then_val._populate_expr_proto(pb.ifThenElse.tru, ref_map)
430+
self.else_val._populate_expr_proto(pb.ifThenElse.fal, ref_map)
450431

451432

452433
class IsConnectedBinding(Binding):
@@ -463,11 +444,10 @@ def get_subexprs(self) -> Iterable[Union[ConstraintExpr, BasePort]]:
463444
return [self.src]
464445

465446
@override
466-
def expr_to_proto(self, expr: ConstraintExpr, ref_map: Refable.RefMapType) -> edgir.ValueExpr:
467-
pb = edgir.ValueExpr()
447+
def populate_expr_proto(self, pb: edgir.ValueExpr, expr: ConstraintExpr, ref_map: Refable.RefMapType) -> None:
468448
pb.ref.CopyFrom(ref_map[self.src])
469449
pb.ref.steps.add().reserved_param = edgir.IS_CONNECTED
470-
return pb
450+
471451

472452
class NameBinding(Binding):
473453
@override
@@ -483,11 +463,9 @@ def get_subexprs(self) -> Iterable[Union[ConstraintExpr, BasePort]]:
483463
return []
484464

485465
@override
486-
def expr_to_proto(self, expr: ConstraintExpr, ref_map: Refable.RefMapType) -> edgir.ValueExpr:
487-
pb = edgir.ValueExpr()
466+
def populate_expr_proto(self, pb: edgir.ValueExpr, expr: ConstraintExpr, ref_map: Refable.RefMapType) -> None:
488467
pb.ref.CopyFrom(ref_map[self.src])
489468
pb.ref.steps.add().reserved_param = edgir.NAME
490-
return pb
491469

492470

493471
class LengthBinding(Binding):
@@ -504,11 +482,9 @@ def get_subexprs(self) -> Iterable[Union[ConstraintExpr, BasePort]]:
504482
return [self.src]
505483

506484
@override
507-
def expr_to_proto(self, expr: ConstraintExpr, ref_map: Refable.RefMapType) -> edgir.ValueExpr:
508-
pb = edgir.ValueExpr()
485+
def populate_expr_proto(self, pb: edgir.ValueExpr, expr: ConstraintExpr, ref_map: Refable.RefMapType) -> None:
509486
pb.ref.CopyFrom(ref_map[self.src])
510487
pb.ref.steps.add().reserved_param = edgir.LENGTH
511-
return pb
512488

513489

514490
class AllocatedBinding(Binding):
@@ -525,21 +501,17 @@ def get_subexprs(self) -> Iterable[Union[ConstraintExpr, BasePort]]:
525501
return [self.src]
526502

527503
@override
528-
def expr_to_proto(self, expr: ConstraintExpr, ref_map: Refable.RefMapType) -> edgir.ValueExpr:
529-
pb = edgir.ValueExpr()
504+
def populate_expr_proto(self, pb: edgir.ValueExpr, expr: ConstraintExpr, ref_map: Refable.RefMapType) -> None:
530505
pb.ref.CopyFrom(ref_map[self.src])
531506
pb.ref.steps.add().reserved_param = edgir.ALLOCATED
532-
return pb
533507

534508

535509
class AssignBinding(Binding):
536-
# Convenience method to make an assign expr without the rest of this proto infrastructure
537510
@staticmethod
538-
def make_assign(target: ConstraintExpr, value: ConstraintExpr, ref_map: Refable.RefMapType) -> edgir.ValueExpr:
539-
pb = edgir.ValueExpr()
511+
def populate_assign_proto(pb: edgir.ValueExpr, target: ConstraintExpr, value: ConstraintExpr, ref_map: Refable.RefMapType) -> None:
512+
# Convenience method to make an assign expr without the rest of this proto infrastructure
540513
pb.assign.dst.CopyFrom(ref_map[target])
541-
pb.assign.src.CopyFrom(value._expr_to_proto(ref_map))
542-
return pb
514+
value._populate_expr_proto(pb.assign.src, ref_map)
543515

544516
@override
545517
def __repr__(self) -> str:
@@ -555,5 +527,6 @@ def get_subexprs(self) -> Iterable[Union[ConstraintExpr, BasePort]]:
555527
return [self.value]
556528

557529
@override
558-
def expr_to_proto(self, expr: ConstraintExpr, ref_map: Refable.RefMapType) -> edgir.ValueExpr:
559-
return self.make_assign(self.target, self.value, ref_map)
530+
def populate_expr_proto(self, pb: edgir.ValueExpr, expr: ConstraintExpr, ref_map: Refable.RefMapType) -> None:
531+
pb.assign.dst.CopyFrom(ref_map[self.target])
532+
self.value._populate_expr_proto(pb.assign.src, ref_map)

0 commit comments

Comments
 (0)