From 2b4d9c8c1989638070bac3edf1f51de826e8f03d Mon Sep 17 00:00:00 2001 From: Jake Lishman Date: Wed, 12 Jul 2023 15:30:49 +0100 Subject: [PATCH] Remove `_legacy_format_cache` slot from `CircuitInstruction` This was originally added as a mitigation for performance loss in consumers of `QuantumCircuit.data` that were still using the legacy interface. It is now becoming more critical to minimise memory usage in the `QuantumCircuit` object, so the extra slot is a luxury we can no longer afford. This represents a 12.5% reduction in the inherent memory footprint of `CircuitInstruction`, though in practice the impact will be smaller, since the `operation` and `qubits` fields will near-universally have associated weight themselves (the `clbits` field is _usually_ the empty tuple, with is a natural singleton untracked by the GC in CPython). Other ongoing work on making more objects singletons will reduce those weights, however. --- qiskit/circuit/quantumcircuitdata.py | 18 +++++++----------- 1 file changed, 7 insertions(+), 11 deletions(-) diff --git a/qiskit/circuit/quantumcircuitdata.py b/qiskit/circuit/quantumcircuitdata.py index a2dd5b96e0a1..e1e61873bed6 100644 --- a/qiskit/circuit/quantumcircuitdata.py +++ b/qiskit/circuit/quantumcircuitdata.py @@ -58,7 +58,7 @@ class CircuitInstruction: of distinct items, with no duplicates. """ - __slots__ = ("operation", "qubits", "clbits", "_legacy_format_cache") + __slots__ = ("operation", "qubits", "clbits") operation: Operation """The logical operation that this instruction represents an execution of.""" @@ -76,7 +76,6 @@ def __init__( self.operation = operation self.qubits = tuple(qubits) self.clbits = tuple(clbits) - self._legacy_format_cache = None def copy(self) -> "CircuitInstruction": """Return a shallow copy of the :class:`CircuitInstruction`.""" @@ -117,7 +116,7 @@ def __eq__(self, other): and self.operation == other.operation ) if isinstance(other, tuple): - return self._legacy_format == other + return self._legacy_format() == other return NotImplemented # Legacy tuple-like interface support. @@ -127,19 +126,16 @@ def __eq__(self, other): # like that via unpacking or similar. That means that the `parameters` field is completely # absent, and the qubits and clbits must be converted to lists. - @property def _legacy_format(self): - if self._legacy_format_cache is None: - # The qubits and clbits were generally stored as lists in the old format, and various - # places assume that they will certainly be lists. - self._legacy_format_cache = (self.operation, list(self.qubits), list(self.clbits)) - return self._legacy_format_cache + # The qubits and clbits were generally stored as lists in the old format, and various + # places assume that they will certainly be lists. + return (self.operation, list(self.qubits), list(self.clbits)) def __getitem__(self, key): - return self._legacy_format[key] + return self._legacy_format()[key] def __iter__(self): - return iter(self._legacy_format) + return iter(self._legacy_format()) def __len__(self): return 3