This project compares the performance and capabilities of three different OpenQASM 3 parsers:
- Qiskit ANTLR Parser (Reference Implementation)
- Qiskit Rust Parser (Experimental)
- Qasm-ts
The ANTLR-based parser is qiskit's reference implementation for parsing OpenQASM 3. It is accessible through the loads() and load() methods, which require installing the qiskit-qasm3-import package. This parser uses ANTLR4 to generate a parser from the official OpenQASM 3 grammar.
The general workflow for parsing OpenQASM 3 from the qiskit reference parser is as follows:
- OpenQASM 3 String - Loaded script or string of OpenQASM
qiskit.qasm3.loads()- Entry point in qiskitqiskit_qasm3_import.parse()- Callsopenqasm3packageopenqasm3.parse()- Entry point for the ANTLR parserqasm3Lexer- ANTLR lexer to tokenize input stringqasm3Parser- ANTLR parser to generate the abstract syntax tree
Note: Qiskit provides further downstream steps such as converting the resulting AST to a Circuit. For sake of benchmarking, we are only concerned up to the AST generation.
The qiskit rust parser is a native high performance experimental parser that is built as a native extension through the main qiskit Python package (through PyO3 bindings) and exposed through qiskit._accerlate. The rust parser is used when using the loads_experimental() and load_experimental() methods. The actual building of the qiskit._accelerate Python extension module is done through the qiskit-pyext crate. The Python bindings are built through the qiskit._qasm3 crate, the rust level qiskit interface to the native rust parser.
The general workflow for parsing OpenQASM 3 from the experimental rust parser is as follows:
- OpenQASM 3 String - Loaded script or string of OpenQASM
qiskit.qasm3.loads_experimental()- Entry point in qiskitqiskit._accelerate_qasm3.loads()- The PyO3 binding that connects Python to Rustoq3_lexer- Tokenizes the input stringoq3_parser- Creates the abstract syntax tree
Note: The rust rust parser provides further downstream steps such as performing semantic analysis on the resulting AST to build an abstract semantic graph (ASG). For sake of benchmarking, we are only concerned up to the AST generation.
The qasm-ts parser is an external typescript library for usage in web applications.
The general workflow for parsing OpenQASM 3 from the qasm-ts parser is as follows:
- OpenQASM 3 String - Loaded script or string of OpenQASM
parseString()- Entry point in qasm-tslex()- Tokenizes the input stringparse()- Creates the abtract syntax tree
It is recommended to create a python virtual environment.
python3 -m env env
source env/bin/activate # For Linux/macOS
env\Script\activate # For WindowsNext, install project dependencies.
For Python dependencies:
pip install -r requirements.txtFor Node.js dependencies:
npm installpython benchmarks/parse_bench.py
- The OpenQASM 3 Python bindings provided to the Rust parser do not expose a way to just generate an AST. Rather, the exposed
loads()andload()functions also perform semantic analysis to generate abstract semantic graphs. In order to benchmark just to the AST generation, the Rust crates were used directly rather than through the Python bindings. - Similarly, the
qiskit-qasm3-importmodule only exposes functions that perform ANTLR parsing plus downstream conversion of the AST to a Qiskit circuit. To avoid this, theopenqasmlibrary is used directly. - In order to avoid including Nodejs and Rust compilation in the benchmark times, a non-timed warm up run is used to initialize system resources. In the Rust instance, the warmup run is used to compile the release binary and the path is cached using an LRU cache for retrieval on subsequent timed iterations. For the Typescript library, the warm up run is used to initialize a server where the QASM snippets to be parsed will be sent.