Iris API lines of code: OpenNN vs PyTorch vs TensorFlow
OpenNN implements the complete Iris classification workflow in 14 logical source lines of application code, compared with 43 for PyTorch and 23 for TensorFlow. For this matched example, OpenNN uses 67% fewer logical instructions than PyTorch and 39% fewer than TensorFlow.
This benchmark measures application-level API conciseness, not framework source size, runtime performance, ecosystem scope, or model quality. Blank lines and comments are excluded, and multiline statements count once.
Contents
- Introduction
- Benchmark application
- Counting methodology
- Results
- What the code covers
- Discussion
- Conclusions
- Reproducing
- References
Introduction
An API affects how much application code a team must write, review, test, and maintain. The raw number of physical lines is a poor comparison across C++ and Python because formatting, braces, comments, and multiline calls differ. This benchmark therefore counts logical source lines of code, or LSLOC, for the same end-to-end Iris classification workflow.
The comparison is deliberately limited to user-facing application code. It does not count the implementation of OpenNN, PyTorch, TensorFlow, NumPy, Pandas, or scikit-learn. It asks a practical question: how many logical instructions does the user write to take the Iris data from loading through training, evaluation, prediction, and export?
Benchmark application
| Item | Matched workflow |
|---|---|
| Dataset | Iris flower classification |
| Inputs | 4 numerical flower measurements |
| Targets | 3 Iris species |
| Network | 4 -> 16 tanh -> 3 classes |
| Data preparation | Load, split, and scale |
| Training | Construct and train the classifier |
| Evaluation | Produce a confusion matrix |
| Deployment | Predict one new flower |
| Persistence/export | Save or export the trained model |
| Metric | Logical application instructions; lower is better |
Each implementation covers those same seven stages. Framework-specific APIs differ, so the code is aligned by outcome rather than forced into identical low-level calls.
Counting methodology
The benchmark runner applies language-aware rules:
- Blank lines and comment-only lines are ignored.
- C++ brace-only and semicolon-only lines are ignored.
- A C++ statement split across several physical lines counts once.
- Each C++ include and control statement counts as one logical instruction.
- Python is parsed into an abstract syntax tree, and each executable statement node counts once.
- Formatting a call over several lines does not increase its count.
This avoids rewarding compressed formatting or penalizing readable multiline code. The three benchmark files are kept beside the counter so changes to the workflow can be reviewed directly.
Results
| Framework | Language | Logical instructions | Relative to OpenNN |
|---|---|---|---|
| OpenNN | C++ | 14 | 1.00x |
| PyTorch | Python | 43 | 3.07x |
| TensorFlow | Python | 23 | 1.64x |
OpenNN requires 29 fewer logical instructions than PyTorch and 9 fewer than TensorFlow. Expressed as reductions, the OpenNN application is 67.4% shorter than PyTorch and 39.1% shorter than TensorFlow under this counting rule.
What the code covers
| Stage | OpenNN abstraction | Reference-framework application work |
|---|---|---|
| Data | Dataset loads and manages the tabular workflow | Load with Pandas, split and scale with scikit-learn, then convert arrays/tensors |
| Model | ClassificationNetwork builds the classification stack | Declare the input and dense layers explicitly |
| Training | TrainingStrategy owns the training procedure | Configure the optimizer/loss and invoke or implement the training loop |
| Testing | TestingAnalysis calculates the confusion matrix | Generate predictions and construct the confusion matrix |
| Deployment | Model-owned scaling and calculate_outputs | Reuse the external scaler and execute the framework model |
| Persistence | Save the OpenNN model | Save or export through framework-specific formats |
OpenNN’s reduction comes mainly from integrated dataset, training, and testing abstractions. The PyTorch example exposes more of the optimization and evaluation procedure. TensorFlow/Keras encapsulates its training loop, so its result sits between OpenNN and PyTorch.
Discussion
Fewer application instructions can reduce integration work and make a complete workflow easier to inspect. In this example, the C++ application remains the shortest even though C++ normally carries more syntax than Python. That result comes from API scope rather than language compression.
LOC is not a measure of capability or engineering quality by itself. A more explicit API can be useful when a project needs custom control, while a higher-level API can remove repeated glue code. The result also belongs to this specific tabular classification workflow; a custom research model or unsupported operation can produce a different ordering.
These application-level values are separate from the framework-source LOC benchmark, which counts library implementation code rather than the user’s Iris application.
Conclusions
- OpenNN completes the Iris workflow in 14 logical application instructions.
- PyTorch uses 43 instructions, or 3.07x the OpenNN count.
- TensorFlow uses 23 instructions, or 1.64x the OpenNN count.
- The result measures API conciseness for one matched workflow, not total framework size or runtime performance.
- The benchmark is reproducible from the three source examples and the language-aware counter.
Reproducing
Run the counter from the repository root:
python docs/benchmarks/footprint/application-loc/count_lsloc.py
It reads opennn_iris.cpp, pytorch_iris.py, and tensorflow_iris.py from the same benchmark directory and prints the three counts as JSON.