From d79eda9dac9c9794091b6ea3544ab2bf69646db6 Mon Sep 17 00:00:00 2001 From: Alex Rubinsteyn Date: Tue, 6 Oct 2026 12:54:27 -0400 Subject: [PATCH 1/3] Optimize attribute parsing and bound Arrow assembly memory (3.0.1) --- benchmarks/README.md | 7 +- benchmarks/compare_readers.py | 2 + benchmarks/compare_releases.py | 139 + benchmarks/optimization-results.json | 7145 ++++++++++++++++++++++++++ benchmarks/optimization.md | 147 + gtfparse/attribute_parsing.py | 87 +- gtfparse/read_gtf.py | 67 +- tasks/todo.md | 106 + tests/test_attribute_optimization.py | 128 + 9 files changed, 7771 insertions(+), 57 deletions(-) create mode 100644 benchmarks/compare_releases.py create mode 100644 benchmarks/optimization-results.json create mode 100644 benchmarks/optimization.md create mode 100644 tests/test_attribute_optimization.py diff --git a/benchmarks/README.md b/benchmarks/README.md index 06379db..87711b7 100644 --- a/benchmarks/README.md +++ b/benchmarks/README.md @@ -1,9 +1,12 @@ # GTF reader backend comparison -Version 3 uses PyArrow for fixed-column parsing and pandas for attribute +The 3.0.0 migration uses PyArrow for fixed-column parsing and pandas for attribute processing and writing. Polars is an optional output adapter. This directory contains the measurement harness and the evidence for that decision. +The follow-up [3.0.1 optimization report](optimization.md) compares the optimized +complete reader with both the 2.9.1 Polars and 3.0.0 Arrow/pandas releases. + ## Reproduction The recorded runs use Python 3.12.6, NumPy 2.5.3, PyArrow 25.0.1, Polars 1.44.2, @@ -54,7 +57,7 @@ include raw attributes, filtering, selection, aliases, version casts, biotype inference and converters; separate regressions cover streams, nullable fields, comments, malformed inputs and progress/cancellation semantics. -## Production results +## 3.0.0 migration results The table shows three-run medians for equivalent pandas output. Complete load time includes fixed-column reading, attribute expansion, assembly and transforms. diff --git a/benchmarks/compare_readers.py b/benchmarks/compare_readers.py index d41778e..04db5e1 100644 --- a/benchmarks/compare_readers.py +++ b/benchmarks/compare_readers.py @@ -17,6 +17,7 @@ from pathlib import Path from time import perf_counter, process_time +import numpy as np import pandas as pd import pyarrow as pa import pyarrow.compute as pc @@ -257,6 +258,7 @@ def main(): "versions": { "gtfparse": __version__, "pandas": pd.__version__, + "numpy": np.__version__, "polars": pl.__version__ if pl is not None else None, "pyarrow": pa.__version__, "python": platform.python_version(), diff --git a/benchmarks/compare_releases.py b/benchmarks/compare_releases.py new file mode 100644 index 0000000..c610a48 --- /dev/null +++ b/benchmarks/compare_releases.py @@ -0,0 +1,139 @@ +"""Repeat complete production reads sequentially in fresh processes. + +Pass --baseline LABEL ROOT for each older checkout and --python PATH for each +interpreter. See optimization.md for the measured corpus and reproduction. +""" + +import argparse +import hashlib +import json +import os +import statistics +import subprocess +import sys +from datetime import datetime, timezone +from pathlib import Path + + +def summarize(records): + groups = {} + for record in records: + key = ( + record["versions"]["pandas"], + record["path"], + record["release"], + tuple(sorted(record["versions"].items())), + ) + groups.setdefault(key, []).append(record) + summaries = [] + for (pandas, path, release, _versions), runs in groups.items(): + summary = {"pandas": pandas, "input": path, "release": release, "runs": len(runs)} + summary["versions"] = runs[0]["versions"] + for name in ("wall_seconds", "cpu_seconds", "peak_rss_mib"): + values = [run[name] for run in runs] + summary[name] = { + "median": statistics.median(values), + "min": min(values), + "max": max(values), + } + summary["stage_medians"] = { + name: statistics.median(run["stages"][name] for run in runs) + for name in runs[0]["stages"] + } + summary["checksum"] = runs[0]["checksum"] + summaries.append(summary) + return summaries + + +def main(): + parser = argparse.ArgumentParser(description=__doc__) + parser.add_argument("inputs", nargs="+", type=Path) + parser.add_argument( + "--baseline", nargs=2, action="append", default=[], metavar=("LABEL", "ROOT") + ) + parser.add_argument("--python", action="append", dest="interpreters") + parser.add_argument("--repeats", type=int, default=3) + parser.add_argument("--threads", type=int, default=4) + parser.add_argument("--result-type", choices=["pandas", "polars"], default="pandas") + parser.add_argument("--features", nargs="+") + parser.add_argument("--usecols", nargs="+") + parser.add_argument("--output", required=True, type=Path) + args = parser.parse_args() + if args.repeats < 1 or args.threads < 1: + parser.error("repeats and threads must be positive") + if len({path.name for path in args.inputs}) != len(args.inputs): + parser.error("input basenames must be distinct") + script = Path(__file__).with_name("compare_readers.py") + releases = [*args.baseline, ("optimized", str(script.parent.parent))] + expected = {} + records = [] + environment = dict(os.environ, POLARS_MAX_THREADS=str(args.threads)) + with args.output.with_suffix(".jsonl").open("w") as raw: + for interpreter in args.interpreters or [sys.executable]: + for repeat in range(1, args.repeats + 1): + # Rotate reader order and reverse corpus order to distribute ordering effects. + offset = (repeat - 1) % len(releases) + order = releases[offset:] + releases[:offset] + paths = args.inputs if repeat % 2 else args.inputs[::-1] + for path in paths: + for label, root in order: + command = [ + interpreter, + str(script), + str(path), + "--backend", + "production", + "--library-root", + root, + "--threads", + str(args.threads), + "--result-type", + args.result_type, + ] + for name in ("features", "usecols"): + value = getattr(args, name) + if value: + command.extend(["--" + name, *value]) + run = subprocess.run( + command, env=environment, capture_output=True, text=True, check=True + ) + record = json.loads(run.stdout) + key = path.name + content = record["checksum"], record["rows"], record["columns"] + if key in expected and expected[key] != content: + raise RuntimeError( + f"Reader results differ: {path}, {label}, {interpreter}" + ) + expected[key] = content + record.update(path=path.name, release=label, repeat=repeat) + records.append(record) + raw.write(json.dumps(record, sort_keys=True) + "\n") + raw.flush() + print( + record["versions"]["pandas"], + repeat, + path.name, + label, + round(record["wall_seconds"], 3), + round(record["peak_rss_mib"]), + flush=True, + ) + result = { + "description": "Complete production readers; imports/checksums outside wall time; sequential fresh processes", + "date": datetime.now(timezone.utc).isoformat(), + "threads": args.threads, + "inputs": { + path.name: { + "bytes": path.stat().st_size, + "sha256": hashlib.sha256(path.read_bytes()).hexdigest(), + } + for path in args.inputs + }, + "summaries": summarize(records), + "measurements": records, + } + args.output.write_text(json.dumps(result, indent=2) + "\n") + + +if __name__ == "__main__": + main() diff --git a/benchmarks/optimization-results.json b/benchmarks/optimization-results.json new file mode 100644 index 0000000..2e04d7c --- /dev/null +++ b/benchmarks/optimization-results.json @@ -0,0 +1,7145 @@ +{ + "description": "Final 3.0.1 captured-pair parser and 250000-row batched Arrow attribute assembly; complete production pipelines.", + "date": "2026-10-06", + "baseline_sources": { + "2.9.1-polars": "3e0912c", + "3.0.0-arrow": "be449cbed70be8f515bb92b3eb2f43e55276917c", + "optimized": "perf/attribute-expansion PR against be449cb; version 3.0.1" + }, + "method": { + "threads": 4, + "final_measurements": 84, + "subset_repeats": 3, + "other_repeats": 1, + "order": "sequential fresh processes; rotating reader order and alternating forward/reversed corpus order", + "timing": "complete read_gtf, including expansion, assembly and transforms; imports/checksums excluded", + "memory": "process peak RSS including imports, sampled before hashing; shared workstation, no OS cache flushing", + "equivalence": "all column values, row count and column order; normalized dtype representations for checksumming; exact dtypes checked separately against 3.0.0" + }, + "inputs": { + "ensembl-250k.gtf": { + "bytes": 111900013, + "sha256": "ac84dc46b89df30eea025c5a36ea3c452f6546be037f77d1eb68fa813226958e", + "rows": 250000, + "source_url": "https://ftp.ensembl.org/pub/release-114/gtf/homo_sapiens/Homo_sapiens.GRCh38.114.gtf.gz", + "selection": "first 250000 annotation rows plus original header" + }, + "ensembl-250k.gtf.gz": { + "bytes": 3524624, + "sha256": "3000128cb22ea68754c01bd3d72fe347c9c86d05b9cae9fed65d1440c57291cd", + "rows": 250000, + "source_url": "https://ftp.ensembl.org/pub/release-114/gtf/homo_sapiens/Homo_sapiens.GRCh38.114.gtf.gz", + "selection": "first 250000 annotation rows plus original header" + }, + "gencode-250k.gtf": { + "bytes": 109586053, + "sha256": "04e929726d7c7837c7669b3795883b55537d389274ba6661a8ab56b5df06bc23", + "rows": 250000, + "source_url": "https://ftp.ebi.ac.uk/pub/databases/gencode/Gencode_human/release_48/gencode.v48.primary_assembly.annotation.gtf.gz", + "selection": "first 250000 annotation rows plus original header" + }, + "gencode-250k.gtf.gz": { + "bytes": 3520115, + "sha256": "6d560c4098d78e6beb8616f08e2bdbbf3071a026edca622e505e294be7f5011d", + "rows": 250000, + "source_url": "https://ftp.ebi.ac.uk/pub/databases/gencode/Gencode_human/release_48/gencode.v48.primary_assembly.annotation.gtf.gz", + "selection": "first 250000 annotation rows plus original header" + }, + "Homo_sapiens.GRCh38.114.gtf.gz": { + "bytes": 64228966, + "sha256": "75ec5b7a1bbb8ce566622dd9abf974ad37d390130325dae6d197d1a590854c50", + "rows": 4116048, + "source_url": "https://ftp.ensembl.org/pub/release-114/gtf/homo_sapiens/Homo_sapiens.GRCh38.114.gtf.gz", + "selection": "full file" + }, + "gencode.v48.primary_assembly.annotation.gtf.gz": { + "bytes": 59094311, + "sha256": "ad15e956fb7643172afca6dcaae176cc76400532392978a191c981d0a052e668", + "rows": 4119244, + "source_url": "https://ftp.ebi.ac.uk/pub/databases/gencode/Gencode_human/release_48/gencode.v48.primary_assembly.annotation.gtf.gz", + "selection": "full file" + } + }, + "final_sweeps": { + "subsets": { + "description": "Complete production readers; imports/checksums outside wall time; sequential fresh processes", + "date": "2026-10-06T16:44:26.773200+00:00", + "threads": 4, + "inputs": { + "ensembl-250k.gtf": { + "bytes": 111900013, + "sha256": "ac84dc46b89df30eea025c5a36ea3c452f6546be037f77d1eb68fa813226958e", + "rows": 250000, + "source_url": "https://ftp.ensembl.org/pub/release-114/gtf/homo_sapiens/Homo_sapiens.GRCh38.114.gtf.gz", + "selection": "first 250000 annotation rows plus original header" + }, + "ensembl-250k.gtf.gz": { + "bytes": 3524624, + "sha256": "3000128cb22ea68754c01bd3d72fe347c9c86d05b9cae9fed65d1440c57291cd", + "rows": 250000, + "source_url": "https://ftp.ensembl.org/pub/release-114/gtf/homo_sapiens/Homo_sapiens.GRCh38.114.gtf.gz", + "selection": "first 250000 annotation rows plus original header" + }, + "gencode-250k.gtf": { + "bytes": 109586053, + "sha256": "04e929726d7c7837c7669b3795883b55537d389274ba6661a8ab56b5df06bc23", + "rows": 250000, + "source_url": "https://ftp.ebi.ac.uk/pub/databases/gencode/Gencode_human/release_48/gencode.v48.primary_assembly.annotation.gtf.gz", + "selection": "first 250000 annotation rows plus original header" + }, + "gencode-250k.gtf.gz": { + "bytes": 3520115, + "sha256": "6d560c4098d78e6beb8616f08e2bdbbf3071a026edca622e505e294be7f5011d", + "rows": 250000, + "source_url": "https://ftp.ebi.ac.uk/pub/databases/gencode/Gencode_human/release_48/gencode.v48.primary_assembly.annotation.gtf.gz", + "selection": "first 250000 annotation rows plus original header" + } + }, + "summaries": [ + { + "pandas": "2.3.3", + "input": "ensembl-250k.gtf", + "release": "2.9.1-polars", + "runs": 3, + "versions": { + "gtfparse": "2.9.1", + "numpy": "2.5.3", + "pandas": "2.3.3", + "polars": "1.44.2", + "pyarrow": "25.0.1", + "python": "3.12.6" + }, + "wall_seconds": { + "median": 2.5705371249932796, + "min": 2.545209417003207, + "max": 2.871901207996416 + }, + "cpu_seconds": { + "median": 2.640136, + "min": 2.633258, + "max": 2.717941 + }, + "peak_rss_mib": { + "median": 560.328125, + "min": 560.3125, + "max": 560.671875 + }, + "stage_medians": { + "attributes": 1.8935110830061603, + "convert": 0.34992329200031236, + "other": 0.23882933298591524, + "read": 0.08401687500008848 + }, + "checksum": "be944cfa699afc930317973a3ee1ca1dc6d309c10071bc32b63a9b54abbdcca8" + }, + { + "pandas": "2.3.3", + "input": "ensembl-250k.gtf", + "release": "3.0.0-arrow", + "runs": 3, + "versions": { + "gtfparse": "3.0.0", + "numpy": "2.5.3", + "pandas": "2.3.3", + "polars": "1.44.2", + "pyarrow": "25.0.1", + "python": "3.12.6" + }, + "wall_seconds": { + "median": 2.9074682079954073, + "min": 2.8575992499972926, + "max": 3.467279165997752 + }, + "cpu_seconds": { + "median": 2.986738, + "min": 2.943254, + "max": 3.3548989999999996 + }, + "peak_rss_mib": { + "median": 616.6875, + "min": 615.40625, + "max": 627.53125 + }, + "stage_medians": { + "attributes": 1.87293291700189, + "convert": 0.28285558299103286, + "other": 0.4966888319904683, + "read": 0.2723564589978196 + }, + "checksum": "be944cfa699afc930317973a3ee1ca1dc6d309c10071bc32b63a9b54abbdcca8" + }, + { + "pandas": "2.3.3", + "input": "ensembl-250k.gtf", + "release": "optimized", + "runs": 3, + "versions": { + "gtfparse": "3.0.1", + "numpy": "2.5.3", + "pandas": "2.3.3", + "polars": "1.44.2", + "pyarrow": "25.0.1", + "python": "3.12.6" + }, + "wall_seconds": { + "median": 2.2852479170105653, + "min": 2.253485958004603, + "max": 2.4167407499917317 + }, + "cpu_seconds": { + "median": 2.373172, + "min": 2.334993, + "max": 2.539217 + }, + "peak_rss_mib": { + "median": 583.40625, + "min": 576.484375, + "max": 593.40625 + }, + "stage_medians": { + "attributes": 1.2345331250107847, + "convert": 0.2886152910068631, + "other": 0.502303834000486, + "read": 0.2740694169915514 + }, + "checksum": "be944cfa699afc930317973a3ee1ca1dc6d309c10071bc32b63a9b54abbdcca8" + }, + { + "pandas": "2.3.3", + "input": "ensembl-250k.gtf.gz", + "release": "2.9.1-polars", + "runs": 3, + "versions": { + "gtfparse": "2.9.1", + "numpy": "2.5.3", + "pandas": "2.3.3", + "polars": "1.44.2", + "pyarrow": "25.0.1", + "python": "3.12.6" + }, + "wall_seconds": { + "median": 2.8604007920075674, + "min": 2.602536874997895, + "max": 3.8669654580007773 + }, + "cpu_seconds": { + "median": 2.8331690000000003, + "min": 2.6671, + "max": 3.038677 + }, + "peak_rss_mib": { + "median": 561.046875, + "min": 524.484375, + "max": 561.09375 + }, + "stage_medians": { + "attributes": 1.9897701250010869, + "convert": 0.34451254199666437, + "other": 0.2918442920054076, + "read": 0.21517366600164678 + }, + "checksum": "be944cfa699afc930317973a3ee1ca1dc6d309c10071bc32b63a9b54abbdcca8" + }, + { + "pandas": "2.3.3", + "input": "ensembl-250k.gtf.gz", + "release": "3.0.0-arrow", + "runs": 3, + "versions": { + "gtfparse": "3.0.0", + "numpy": "2.5.3", + "pandas": "2.3.3", + "polars": "1.44.2", + "pyarrow": "25.0.1", + "python": "3.12.6" + }, + "wall_seconds": { + "median": 4.57787587500934, + "min": 3.4941771660087397, + "max": 5.500599250008236 + }, + "cpu_seconds": { + "median": 3.36688, + "min": 3.302426, + "max": 3.37763 + }, + "peak_rss_mib": { + "median": 619.71875, + "min": 615.78125, + "max": 625.609375 + }, + "stage_medians": { + "attributes": 2.818784125003731, + "convert": 0.4906274579989258, + "other": 0.9829520420025801, + "read": 0.2925547919876408 + }, + "checksum": "be944cfa699afc930317973a3ee1ca1dc6d309c10071bc32b63a9b54abbdcca8" + }, + { + "pandas": "2.3.3", + "input": "ensembl-250k.gtf.gz", + "release": "optimized", + "runs": 3, + "versions": { + "gtfparse": "3.0.1", + "numpy": "2.5.3", + "pandas": "2.3.3", + "polars": "1.44.2", + "pyarrow": "25.0.1", + "python": "3.12.6" + }, + "wall_seconds": { + "median": 2.361613708999357, + "min": 2.2743365000060294, + "max": 3.9647754170000553 + }, + "cpu_seconds": { + "median": 2.433655, + "min": 2.355343, + "max": 2.82855 + }, + "peak_rss_mib": { + "median": 583.96875, + "min": 574.75, + "max": 591.171875 + }, + "stage_medians": { + "attributes": 1.2559461250057211, + "convert": 0.2896352910029236, + "other": 0.535507876003976, + "read": 0.28052441698673647 + }, + "checksum": "be944cfa699afc930317973a3ee1ca1dc6d309c10071bc32b63a9b54abbdcca8" + }, + { + "pandas": "2.3.3", + "input": "gencode-250k.gtf", + "release": "2.9.1-polars", + "runs": 3, + "versions": { + "gtfparse": "2.9.1", + "numpy": "2.5.3", + "pandas": "2.3.3", + "polars": "1.44.2", + "pyarrow": "25.0.1", + "python": "3.12.6" + }, + "wall_seconds": { + "median": 3.1804067909979494, + "min": 2.3660601659939857, + "max": 5.55182199999399 + }, + "cpu_seconds": { + "median": 2.5377099999999997, + "min": 2.266625, + "max": 2.560311 + }, + "peak_rss_mib": { + "median": 567.3125, + "min": 566.484375, + "max": 567.546875 + }, + "stage_medians": { + "attributes": 2.646453332999954, + "convert": 0.09764800000994, + "other": 0.3458024169958662, + "read": 0.1014160000049742 + }, + "checksum": "8d394118a91daefd2d5ee4f50c07ef5dee567e6ad373c052fa6cf3898c807641" + }, + { + "pandas": "2.3.3", + "input": "gencode-250k.gtf", + "release": "3.0.0-arrow", + "runs": 3, + "versions": { + "gtfparse": "3.0.0", + "numpy": "2.5.3", + "pandas": "2.3.3", + "polars": "1.44.2", + "pyarrow": "25.0.1", + "python": "3.12.6" + }, + "wall_seconds": { + "median": 2.585112458007643, + "min": 2.5604790829966078, + "max": 5.565355083002942 + }, + "cpu_seconds": { + "median": 2.658798, + "min": 2.651787, + "max": 3.191441 + }, + "peak_rss_mib": { + "median": 587.6875, + "min": 551.328125, + "max": 591.8125 + }, + "stage_medians": { + "attributes": 1.7814520410029218, + "convert": 7.35829962650314e-05, + "other": 0.5366334179998375, + "read": 0.26695341600861866 + }, + "checksum": "8d394118a91daefd2d5ee4f50c07ef5dee567e6ad373c052fa6cf3898c807641" + }, + { + "pandas": "2.3.3", + "input": "gencode-250k.gtf", + "release": "optimized", + "runs": 3, + "versions": { + "gtfparse": "3.0.1", + "numpy": "2.5.3", + "pandas": "2.3.3", + "polars": "1.44.2", + "pyarrow": "25.0.1", + "python": "3.12.6" + }, + "wall_seconds": { + "median": 3.716955208001309, + "min": 2.337004041997716, + "max": 4.0017947089945665 + }, + "cpu_seconds": { + "median": 2.425999, + "min": 2.2283709999999997, + "max": 2.4871540000000003 + }, + "peak_rss_mib": { + "median": 549.84375, + "min": 527.203125, + "max": 565.484375 + }, + "stage_medians": { + "attributes": 2.1337991250038613, + "convert": 5.26670046383515e-05, + "other": 0.8941883750085253, + "read": 0.4248130839987425 + }, + "checksum": "8d394118a91daefd2d5ee4f50c07ef5dee567e6ad373c052fa6cf3898c807641" + }, + { + "pandas": "2.3.3", + "input": "gencode-250k.gtf.gz", + "release": "2.9.1-polars", + "runs": 3, + "versions": { + "gtfparse": "2.9.1", + "numpy": "2.5.3", + "pandas": "2.3.3", + "polars": "1.44.2", + "pyarrow": "25.0.1", + "python": "3.12.6" + }, + "wall_seconds": { + "median": 3.60983508299978, + "min": 2.207000333000906, + "max": 3.854776332998881 + }, + "cpu_seconds": { + "median": 2.671091, + "min": 2.2800469999999997, + "max": 2.790294 + }, + "peak_rss_mib": { + "median": 567.796875, + "min": 567.5, + "max": 568.4375 + }, + "stage_medians": { + "attributes": 2.8298818330076756, + "convert": 0.131129208006314, + "other": 0.4548585419834126, + "read": 0.19396550000237767 + }, + "checksum": "8d394118a91daefd2d5ee4f50c07ef5dee567e6ad373c052fa6cf3898c807641" + }, + { + "pandas": "2.3.3", + "input": "gencode-250k.gtf.gz", + "release": "3.0.0-arrow", + "runs": 3, + "versions": { + "gtfparse": "3.0.0", + "numpy": "2.5.3", + "pandas": "2.3.3", + "polars": "1.44.2", + "pyarrow": "25.0.1", + "python": "3.12.6" + }, + "wall_seconds": { + "median": 3.8968885840004077, + "min": 2.4905160420021275, + "max": 3.9853524999925867 + }, + "cpu_seconds": { + "median": 3.075842, + "min": 2.574939, + "max": 3.087378 + }, + "peak_rss_mib": { + "median": 583.796875, + "min": 580.96875, + "max": 587.78125 + }, + "stage_medians": { + "attributes": 2.6965094580082223, + "convert": 8.433299080934376e-05, + "other": 0.7963529169937829, + "read": 0.3873044999927515 + }, + "checksum": "8d394118a91daefd2d5ee4f50c07ef5dee567e6ad373c052fa6cf3898c807641" + }, + { + "pandas": "2.3.3", + "input": "gencode-250k.gtf.gz", + "release": "optimized", + "runs": 3, + "versions": { + "gtfparse": "3.0.1", + "numpy": "2.5.3", + "pandas": "2.3.3", + "polars": "1.44.2", + "pyarrow": "25.0.1", + "python": "3.12.6" + }, + "wall_seconds": { + "median": 3.736287124993396, + "min": 1.9886879580008099, + "max": 3.8399662080046255 + }, + "cpu_seconds": { + "median": 2.54815, + "min": 2.080072, + "max": 2.6218580000000005 + }, + "peak_rss_mib": { + "median": 557.890625, + "min": 495.1875, + "max": 566.9375 + }, + "stage_medians": { + "attributes": 2.2640662500052713, + "convert": 4.354199336376041e-05, + "other": 0.9998161669936962, + "read": 0.39063262499985285 + }, + "checksum": "8d394118a91daefd2d5ee4f50c07ef5dee567e6ad373c052fa6cf3898c807641" + }, + { + "pandas": "3.0.6", + "input": "ensembl-250k.gtf", + "release": "2.9.1-polars", + "runs": 3, + "versions": { + "gtfparse": "2.9.1", + "numpy": "2.5.3", + "pandas": "3.0.6", + "polars": "1.44.2", + "pyarrow": "25.0.1", + "python": "3.12.6" + }, + "wall_seconds": { + "median": 2.5418692079983884, + "min": 2.3415217919973657, + "max": 2.7177458749938523 + }, + "cpu_seconds": { + "median": 2.420429, + "min": 2.414792, + "max": 2.556296 + }, + "peak_rss_mib": { + "median": 552.5, + "min": 552.21875, + "max": 552.828125 + }, + "stage_medians": { + "attributes": 1.8557262500107754, + "convert": 0.22684966700035147, + "other": 0.23259929296909831, + "read": 0.03862558300897945 + }, + "checksum": "be944cfa699afc930317973a3ee1ca1dc6d309c10071bc32b63a9b54abbdcca8" + }, + { + "pandas": "3.0.6", + "input": "ensembl-250k.gtf", + "release": "3.0.0-arrow", + "runs": 3, + "versions": { + "gtfparse": "3.0.0", + "numpy": "2.5.3", + "pandas": "3.0.6", + "polars": "1.44.2", + "pyarrow": "25.0.1", + "python": "3.12.6" + }, + "wall_seconds": { + "median": 2.824426291990676, + "min": 2.7780951250024373, + "max": 2.897920041010366 + }, + "cpu_seconds": { + "median": 2.896116, + "min": 2.85385, + "max": 2.979457 + }, + "peak_rss_mib": { + "median": 599.765625, + "min": 590.28125, + "max": 601.796875 + }, + "stage_medians": { + "attributes": 1.8735739160038065, + "convert": 0.18741612500161864, + "other": 0.5475739179964876, + "read": 0.21546933299396187 + }, + "checksum": "be944cfa699afc930317973a3ee1ca1dc6d309c10071bc32b63a9b54abbdcca8" + }, + { + "pandas": "3.0.6", + "input": "ensembl-250k.gtf", + "release": "optimized", + "runs": 3, + "versions": { + "gtfparse": "3.0.1", + "numpy": "2.5.3", + "pandas": "3.0.6", + "polars": "1.44.2", + "pyarrow": "25.0.1", + "python": "3.12.6" + }, + "wall_seconds": { + "median": 1.9066367920022458, + "min": 1.8812497079925379, + "max": 2.1686059169878718 + }, + "cpu_seconds": { + "median": 1.9879889999999998, + "min": 1.981777, + "max": 2.111438 + }, + "peak_rss_mib": { + "median": 576.71875, + "min": 574.484375, + "max": 578.09375 + }, + "stage_medians": { + "attributes": 1.255898375005927, + "convert": 0.18790645799890626, + "other": 0.2516916669992497, + "read": 0.21316074999049306 + }, + "checksum": "be944cfa699afc930317973a3ee1ca1dc6d309c10071bc32b63a9b54abbdcca8" + }, + { + "pandas": "3.0.6", + "input": "ensembl-250k.gtf.gz", + "release": "2.9.1-polars", + "runs": 3, + "versions": { + "gtfparse": "2.9.1", + "numpy": "2.5.3", + "pandas": "3.0.6", + "polars": "1.44.2", + "pyarrow": "25.0.1", + "python": "3.12.6" + }, + "wall_seconds": { + "median": 2.3489610830001766, + "min": 2.341782832998433, + "max": 2.4118617909989553 + }, + "cpu_seconds": { + "median": 2.415416, + "min": 2.4144940000000004, + "max": 2.4895519999999998 + }, + "peak_rss_mib": { + "median": 553.15625, + "min": 553.046875, + "max": 553.421875 + }, + "stage_medians": { + "attributes": 1.8477172499988228, + "convert": 0.20435254200128838, + "other": 0.22192491599707864, + "read": 0.0779351250093896 + }, + "checksum": "be944cfa699afc930317973a3ee1ca1dc6d309c10071bc32b63a9b54abbdcca8" + }, + { + "pandas": "3.0.6", + "input": "ensembl-250k.gtf.gz", + "release": "3.0.0-arrow", + "runs": 3, + "versions": { + "gtfparse": "3.0.0", + "numpy": "2.5.3", + "pandas": "3.0.6", + "polars": "1.44.2", + "pyarrow": "25.0.1", + "python": "3.12.6" + }, + "wall_seconds": { + "median": 2.80403087499144, + "min": 2.7633427499968093, + "max": 2.8217112080019433 + }, + "cpu_seconds": { + "median": 2.888417, + "min": 2.854932, + "max": 2.9196619999999998 + }, + "peak_rss_mib": { + "median": 599.984375, + "min": 595.125, + "max": 607.015625 + }, + "stage_medians": { + "attributes": 1.8276292090013158, + "convert": 0.18400516700057779, + "other": 0.556629457991221, + "read": 0.23586362499918323 + }, + "checksum": "be944cfa699afc930317973a3ee1ca1dc6d309c10071bc32b63a9b54abbdcca8" + }, + { + "pandas": "3.0.6", + "input": "ensembl-250k.gtf.gz", + "release": "optimized", + "runs": 3, + "versions": { + "gtfparse": "3.0.1", + "numpy": "2.5.3", + "pandas": "3.0.6", + "polars": "1.44.2", + "pyarrow": "25.0.1", + "python": "3.12.6" + }, + "wall_seconds": { + "median": 1.876802041006158, + "min": 1.8565174999966985, + "max": 1.9292772500048159 + }, + "cpu_seconds": { + "median": 1.958045, + "min": 1.9496789999999997, + "max": 2.03234 + }, + "peak_rss_mib": { + "median": 574.140625, + "min": 572.890625, + "max": 574.84375 + }, + "stage_medians": { + "attributes": 1.2322392920032144, + "convert": 0.1897575000039069, + "other": 0.23446987399074715, + "read": 0.22112158400705084 + }, + "checksum": "be944cfa699afc930317973a3ee1ca1dc6d309c10071bc32b63a9b54abbdcca8" + }, + { + "pandas": "3.0.6", + "input": "gencode-250k.gtf", + "release": "2.9.1-polars", + "runs": 3, + "versions": { + "gtfparse": "2.9.1", + "numpy": "2.5.3", + "pandas": "3.0.6", + "polars": "1.44.2", + "pyarrow": "25.0.1", + "python": "3.12.6" + }, + "wall_seconds": { + "median": 2.047686125006294, + "min": 1.996198959008325, + "max": 2.0576451669912785 + }, + "cpu_seconds": { + "median": 2.116965, + "min": 2.082073, + "max": 2.142511 + }, + "peak_rss_mib": { + "median": 559.5, + "min": 559.421875, + "max": 559.671875 + }, + "stage_medians": { + "attributes": 1.7327500000101281, + "convert": 0.017430042003979906, + "other": 0.24500191600236576, + "read": 0.027468333006254397 + }, + "checksum": "8d394118a91daefd2d5ee4f50c07ef5dee567e6ad373c052fa6cf3898c807641" + }, + { + "pandas": "3.0.6", + "input": "gencode-250k.gtf", + "release": "3.0.0-arrow", + "runs": 3, + "versions": { + "gtfparse": "3.0.0", + "numpy": "2.5.3", + "pandas": "3.0.6", + "polars": "1.44.2", + "pyarrow": "25.0.1", + "python": "3.12.6" + }, + "wall_seconds": { + "median": 2.682168958010152, + "min": 2.5138637089985423, + "max": 2.747774916992057 + }, + "cpu_seconds": { + "median": 2.681481, + "min": 2.606457, + "max": 2.745542 + }, + "peak_rss_mib": { + "median": 593.15625, + "min": 591.375, + "max": 598.234375 + }, + "stage_medians": { + "attributes": 1.8231396670016693, + "convert": 0.00015558300947304815, + "other": 0.6528683740034467, + "read": 0.21073287499893922 + }, + "checksum": "8d394118a91daefd2d5ee4f50c07ef5dee567e6ad373c052fa6cf3898c807641" + }, + { + "pandas": "3.0.6", + "input": "gencode-250k.gtf", + "release": "optimized", + "runs": 3, + "versions": { + "gtfparse": "3.0.1", + "numpy": "2.5.3", + "pandas": "3.0.6", + "polars": "1.44.2", + "pyarrow": "25.0.1", + "python": "3.12.6" + }, + "wall_seconds": { + "median": 1.7089971670066006, + "min": 1.6545389160019113, + "max": 1.8188800839998294 + }, + "cpu_seconds": { + "median": 1.784423, + "min": 1.7458540000000002, + "max": 1.804453 + }, + "peak_rss_mib": { + "median": 576.578125, + "min": 576.234375, + "max": 578.703125 + }, + "stage_medians": { + "attributes": 1.216064499996719, + "convert": 2.5416011339984834e-05, + "other": 0.28129791701212525, + "read": 0.21160841699747834 + }, + "checksum": "8d394118a91daefd2d5ee4f50c07ef5dee567e6ad373c052fa6cf3898c807641" + }, + { + "pandas": "3.0.6", + "input": "gencode-250k.gtf.gz", + "release": "2.9.1-polars", + "runs": 3, + "versions": { + "gtfparse": "2.9.1", + "numpy": "2.5.3", + "pandas": "3.0.6", + "polars": "1.44.2", + "pyarrow": "25.0.1", + "python": "3.12.6" + }, + "wall_seconds": { + "median": 2.099596250001923, + "min": 2.0580523329990683, + "max": 2.2535872500011465 + }, + "cpu_seconds": { + "median": 2.1718260000000003, + "min": 2.126937, + "max": 2.24322 + }, + "peak_rss_mib": { + "median": 560.15625, + "min": 560.0, + "max": 560.78125 + }, + "stage_medians": { + "attributes": 1.7444164579937933, + "convert": 0.018364208008279093, + "other": 0.26727887500601355, + "read": 0.07006466700113378 + }, + "checksum": "8d394118a91daefd2d5ee4f50c07ef5dee567e6ad373c052fa6cf3898c807641" + }, + { + "pandas": "3.0.6", + "input": "gencode-250k.gtf.gz", + "release": "3.0.0-arrow", + "runs": 3, + "versions": { + "gtfparse": "3.0.0", + "numpy": "2.5.3", + "pandas": "3.0.6", + "polars": "1.44.2", + "pyarrow": "25.0.1", + "python": "3.12.6" + }, + "wall_seconds": { + "median": 2.524030959000811, + "min": 2.5057187499915017, + "max": 2.5275498749979306 + }, + "cpu_seconds": { + "median": 2.6059170000000003, + "min": 2.589577, + "max": 2.6144279999999998 + }, + "peak_rss_mib": { + "median": 595.03125, + "min": 589.8125, + "max": 595.265625 + }, + "stage_medians": { + "attributes": 1.7339677080017282, + "convert": 0.0001550410088384524, + "other": 0.5685903760022484, + "read": 0.2197710839973297 + }, + "checksum": "8d394118a91daefd2d5ee4f50c07ef5dee567e6ad373c052fa6cf3898c807641" + }, + { + "pandas": "3.0.6", + "input": "gencode-250k.gtf.gz", + "release": "optimized", + "runs": 3, + "versions": { + "gtfparse": "3.0.1", + "numpy": "2.5.3", + "pandas": "3.0.6", + "polars": "1.44.2", + "pyarrow": "25.0.1", + "python": "3.12.6" + }, + "wall_seconds": { + "median": 1.7293930830055615, + "min": 1.6913924160035094, + "max": 1.730756167002255 + }, + "cpu_seconds": { + "median": 1.789281, + "min": 1.7782019999999998, + "max": 1.827663 + }, + "peak_rss_mib": { + "median": 574.265625, + "min": 572.78125, + "max": 583.171875 + }, + "stage_medians": { + "attributes": 1.23295112499909, + "convert": 2.5416986318305135e-05, + "other": 0.268862833007006, + "read": 0.22319108400552068 + }, + "checksum": "8d394118a91daefd2d5ee4f50c07ef5dee567e6ad373c052fa6cf3898c807641" + } + ], + "measurements": [ + { + "backend": "production", + "checksum": "be944cfa699afc930317973a3ee1ca1dc6d309c10071bc32b63a9b54abbdcca8", + "columns": [ + "seqname", + "source", + "feature", + "start", + "end", + "score", + "strand", + "frame", + "gene_id", + "gene_version", + "gene_name", + "gene_source", + "gene_biotype", + "transcript_id", + "transcript_version", + "transcript_name", + "transcript_source", + "transcript_biotype", + "tag", + "transcript_support_level", + "exon_number", + "exon_id", + "exon_version", + "protein_id", + "protein_version", + "ccds_id" + ], + "cpu_count": 10, + "cpu_seconds": 2.717941, + "features": null, + "input_bytes": 111900013, + "path": "ensembl-250k.gtf", + "peak_rss_mib": 560.3125, + "platform": "macOS-26.5-arm64-arm-64bit", + "result_type": "pandas", + "rows": 250000, + "stages": { + "attributes": 1.8935110830061603, + "convert": 0.3650127500004601, + "other": 0.23882933298591524, + "read": 0.37454804200388025 + }, + "threads": 4, + "usecols": null, + "versions": { + "gtfparse": "2.9.1", + "numpy": "2.5.3", + "pandas": "2.3.3", + "polars": "1.44.2", + "pyarrow": "25.0.1", + "python": "3.12.6" + }, + "wall_seconds": 2.871901207996416, + "release": "2.9.1-polars", + "repeat": 1 + }, + { + "backend": "production", + "checksum": "be944cfa699afc930317973a3ee1ca1dc6d309c10071bc32b63a9b54abbdcca8", + "columns": [ + "seqname", + "source", + "feature", + "start", + "end", + "score", + "strand", + "frame", + "gene_id", + "gene_version", + "gene_name", + "gene_source", + "gene_biotype", + "transcript_id", + "transcript_version", + "transcript_name", + "transcript_source", + "transcript_biotype", + "tag", + "transcript_support_level", + "exon_number", + "exon_id", + "exon_version", + "protein_id", + "protein_version", + "ccds_id" + ], + "cpu_count": 10, + "cpu_seconds": 2.986738, + "features": null, + "input_bytes": 111900013, + "path": "ensembl-250k.gtf", + "peak_rss_mib": 615.40625, + "platform": "macOS-26.5-arm64-arm-64bit", + "result_type": "pandas", + "rows": 250000, + "stages": { + "attributes": 1.8604427090031095, + "convert": 0.2779802080040099, + "other": 0.4966888319904683, + "read": 0.2723564589978196 + }, + "threads": 4, + "usecols": null, + "versions": { + "gtfparse": "3.0.0", + "numpy": "2.5.3", + "pandas": "2.3.3", + "polars": "1.44.2", + "pyarrow": "25.0.1", + "python": "3.12.6" + }, + "wall_seconds": 2.9074682079954073, + "release": "3.0.0-arrow", + "repeat": 1 + }, + { + "backend": "production", + "checksum": "be944cfa699afc930317973a3ee1ca1dc6d309c10071bc32b63a9b54abbdcca8", + "columns": [ + "seqname", + "source", + "feature", + "start", + "end", + "score", + "strand", + "frame", + "gene_id", + "gene_version", + "gene_name", + "gene_source", + "gene_biotype", + "transcript_id", + "transcript_version", + "transcript_name", + "transcript_source", + "transcript_biotype", + "tag", + "transcript_support_level", + "exon_number", + "exon_id", + "exon_version", + "protein_id", + "protein_version", + "ccds_id" + ], + "cpu_count": 10, + "cpu_seconds": 2.334993, + "features": null, + "input_bytes": 111900013, + "path": "ensembl-250k.gtf", + "peak_rss_mib": 583.40625, + "platform": "macOS-26.5-arm64-arm-64bit", + "result_type": "pandas", + "rows": 250000, + "stages": { + "attributes": 1.2237206660065567, + "convert": 0.2886152910068631, + "other": 0.4670805839996319, + "read": 0.2740694169915514 + }, + "threads": 4, + "usecols": null, + "versions": { + "gtfparse": "3.0.1", + "numpy": "2.5.3", + "pandas": "2.3.3", + "polars": "1.44.2", + "pyarrow": "25.0.1", + "python": "3.12.6" + }, + "wall_seconds": 2.253485958004603, + "release": "optimized", + "repeat": 1 + }, + { + "backend": "production", + "checksum": "be944cfa699afc930317973a3ee1ca1dc6d309c10071bc32b63a9b54abbdcca8", + "columns": [ + "seqname", + "source", + "feature", + "start", + "end", + "score", + "strand", + "frame", + "gene_id", + "gene_version", + "gene_name", + "gene_source", + "gene_biotype", + "transcript_id", + "transcript_version", + "transcript_name", + "transcript_source", + "transcript_biotype", + "tag", + "transcript_support_level", + "exon_number", + "exon_id", + "exon_version", + "protein_id", + "protein_version", + "ccds_id" + ], + "cpu_count": 10, + "cpu_seconds": 2.8331690000000003, + "features": null, + "input_bytes": 3524624, + "path": "ensembl-250k.gtf.gz", + "peak_rss_mib": 524.484375, + "platform": "macOS-26.5-arm64-arm-64bit", + "result_type": "pandas", + "rows": 250000, + "stages": { + "attributes": 1.9897701250010869, + "convert": 0.34451254199666437, + "other": 0.2918442920054076, + "read": 0.23427383300440852 + }, + "threads": 4, + "usecols": null, + "versions": { + "gtfparse": "2.9.1", + "numpy": "2.5.3", + "pandas": "2.3.3", + "polars": "1.44.2", + "pyarrow": "25.0.1", + "python": "3.12.6" + }, + "wall_seconds": 2.8604007920075674, + "release": "2.9.1-polars", + "repeat": 1 + }, + { + "backend": "production", + "checksum": "be944cfa699afc930317973a3ee1ca1dc6d309c10071bc32b63a9b54abbdcca8", + "columns": [ + "seqname", + "source", + "feature", + "start", + "end", + "score", + "strand", + "frame", + "gene_id", + "gene_version", + "gene_name", + "gene_source", + "gene_biotype", + "transcript_id", + "transcript_version", + "transcript_name", + "transcript_source", + "transcript_biotype", + "tag", + "transcript_support_level", + "exon_number", + "exon_id", + "exon_version", + "protein_id", + "protein_version", + "ccds_id" + ], + "cpu_count": 10, + "cpu_seconds": 3.36688, + "features": null, + "input_bytes": 3524624, + "path": "ensembl-250k.gtf.gz", + "peak_rss_mib": 619.71875, + "platform": "macOS-26.5-arm64-arm-64bit", + "result_type": "pandas", + "rows": 250000, + "stages": { + "attributes": 2.199549124998157, + "convert": 0.32413274999998976, + "other": 0.6779404990229523, + "read": 0.2925547919876408 + }, + "threads": 4, + "usecols": null, + "versions": { + "gtfparse": "3.0.0", + "numpy": "2.5.3", + "pandas": "2.3.3", + "polars": "1.44.2", + "pyarrow": "25.0.1", + "python": "3.12.6" + }, + "wall_seconds": 3.4941771660087397, + "release": "3.0.0-arrow", + "repeat": 1 + }, + { + "backend": "production", + "checksum": "be944cfa699afc930317973a3ee1ca1dc6d309c10071bc32b63a9b54abbdcca8", + "columns": [ + "seqname", + "source", + "feature", + "start", + "end", + "score", + "strand", + "frame", + "gene_id", + "gene_version", + "gene_name", + "gene_source", + "gene_biotype", + "transcript_id", + "transcript_version", + "transcript_name", + "transcript_source", + "transcript_biotype", + "tag", + "transcript_support_level", + "exon_number", + "exon_id", + "exon_version", + "protein_id", + "protein_version", + "ccds_id" + ], + "cpu_count": 10, + "cpu_seconds": 2.433655, + "features": null, + "input_bytes": 3524624, + "path": "ensembl-250k.gtf.gz", + "peak_rss_mib": 583.96875, + "platform": "macOS-26.5-arm64-arm-64bit", + "result_type": "pandas", + "rows": 250000, + "stages": { + "attributes": 1.2559461250057211, + "convert": 0.2896352910029236, + "other": 0.535507876003976, + "read": 0.28052441698673647 + }, + "threads": 4, + "usecols": null, + "versions": { + "gtfparse": "3.0.1", + "numpy": "2.5.3", + "pandas": "2.3.3", + "polars": "1.44.2", + "pyarrow": "25.0.1", + "python": "3.12.6" + }, + "wall_seconds": 2.361613708999357, + "release": "optimized", + "repeat": 1 + }, + { + "backend": "production", + "checksum": "8d394118a91daefd2d5ee4f50c07ef5dee567e6ad373c052fa6cf3898c807641", + "columns": [ + "seqname", + "source", + "feature", + "start", + "end", + "score", + "strand", + "frame", + "gene_id", + "gene_type", + "gene_name", + "level", + "tag", + "transcript_id", + "transcript_type", + "transcript_name", + "exon_number", + "exon_id", + "transcript_support_level", + "havana_transcript", + "hgnc_id", + "havana_gene", + "ont", + "protein_id", + "ccdsid" + ], + "cpu_count": 10, + "cpu_seconds": 2.266625, + "features": null, + "input_bytes": 109586053, + "path": "gencode-250k.gtf", + "peak_rss_mib": 567.3125, + "platform": "macOS-26.5-arm64-arm-64bit", + "result_type": "pandas", + "rows": 250000, + "stages": { + "attributes": 1.758518542003003, + "convert": 0.06522274999588262, + "other": 0.2602612069895258, + "read": 0.28205766700557433 + }, + "threads": 4, + "usecols": null, + "versions": { + "gtfparse": "2.9.1", + "numpy": "2.5.3", + "pandas": "2.3.3", + "polars": "1.44.2", + "pyarrow": "25.0.1", + "python": "3.12.6" + }, + "wall_seconds": 2.3660601659939857, + "release": "2.9.1-polars", + "repeat": 1 + }, + { + "backend": "production", + "checksum": "8d394118a91daefd2d5ee4f50c07ef5dee567e6ad373c052fa6cf3898c807641", + "columns": [ + "seqname", + "source", + "feature", + "start", + "end", + "score", + "strand", + "frame", + "gene_id", + "gene_type", + "gene_name", + "level", + "tag", + "transcript_id", + "transcript_type", + "transcript_name", + "exon_number", + "exon_id", + "transcript_support_level", + "havana_transcript", + "hgnc_id", + "havana_gene", + "ont", + "protein_id", + "ccdsid" + ], + "cpu_count": 10, + "cpu_seconds": 2.651787, + "features": null, + "input_bytes": 109586053, + "path": "gencode-250k.gtf", + "peak_rss_mib": 591.8125, + "platform": "macOS-26.5-arm64-arm-64bit", + "result_type": "pandas", + "rows": 250000, + "stages": { + "attributes": 1.7611734999954933, + "convert": 6.516699795611203e-05, + "other": 0.5358809580066008, + "read": 0.26335945799655747 + }, + "threads": 4, + "usecols": null, + "versions": { + "gtfparse": "3.0.0", + "numpy": "2.5.3", + "pandas": "2.3.3", + "polars": "1.44.2", + "pyarrow": "25.0.1", + "python": "3.12.6" + }, + "wall_seconds": 2.5604790829966078, + "release": "3.0.0-arrow", + "repeat": 1 + }, + { + "backend": "production", + "checksum": "8d394118a91daefd2d5ee4f50c07ef5dee567e6ad373c052fa6cf3898c807641", + "columns": [ + "seqname", + "source", + "feature", + "start", + "end", + "score", + "strand", + "frame", + "gene_id", + "gene_type", + "gene_name", + "level", + "tag", + "transcript_id", + "transcript_type", + "transcript_name", + "exon_number", + "exon_id", + "transcript_support_level", + "havana_transcript", + "hgnc_id", + "havana_gene", + "ont", + "protein_id", + "ccdsid" + ], + "cpu_count": 10, + "cpu_seconds": 2.2283709999999997, + "features": null, + "input_bytes": 109586053, + "path": "gencode-250k.gtf", + "peak_rss_mib": 549.84375, + "platform": "macOS-26.5-arm64-arm-64bit", + "result_type": "pandas", + "rows": 250000, + "stages": { + "attributes": 1.285506374988472, + "convert": 5.26670046383515e-05, + "other": 0.7597022910049418, + "read": 0.2917427089996636 + }, + "threads": 4, + "usecols": null, + "versions": { + "gtfparse": "3.0.1", + "numpy": "2.5.3", + "pandas": "2.3.3", + "polars": "1.44.2", + "pyarrow": "25.0.1", + "python": "3.12.6" + }, + "wall_seconds": 2.337004041997716, + "release": "optimized", + "repeat": 1 + }, + { + "backend": "production", + "checksum": "8d394118a91daefd2d5ee4f50c07ef5dee567e6ad373c052fa6cf3898c807641", + "columns": [ + "seqname", + "source", + "feature", + "start", + "end", + "score", + "strand", + "frame", + "gene_id", + "gene_type", + "gene_name", + "level", + "tag", + "transcript_id", + "transcript_type", + "transcript_name", + "exon_number", + "exon_id", + "transcript_support_level", + "havana_transcript", + "hgnc_id", + "havana_gene", + "ont", + "protein_id", + "ccdsid" + ], + "cpu_count": 10, + "cpu_seconds": 2.671091, + "features": null, + "input_bytes": 3520115, + "path": "gencode-250k.gtf.gz", + "peak_rss_mib": 567.796875, + "platform": "macOS-26.5-arm64-arm-64bit", + "result_type": "pandas", + "rows": 250000, + "stages": { + "attributes": 2.8298818330076756, + "convert": 0.131129208006314, + "other": 0.4548585419834126, + "read": 0.19396550000237767 + }, + "threads": 4, + "usecols": null, + "versions": { + "gtfparse": "2.9.1", + "numpy": "2.5.3", + "pandas": "2.3.3", + "polars": "1.44.2", + "pyarrow": "25.0.1", + "python": "3.12.6" + }, + "wall_seconds": 3.60983508299978, + "release": "2.9.1-polars", + "repeat": 1 + }, + { + "backend": "production", + "checksum": "8d394118a91daefd2d5ee4f50c07ef5dee567e6ad373c052fa6cf3898c807641", + "columns": [ + "seqname", + "source", + "feature", + "start", + "end", + "score", + "strand", + "frame", + "gene_id", + "gene_type", + "gene_name", + "level", + "tag", + "transcript_id", + "transcript_type", + "transcript_name", + "exon_number", + "exon_id", + "transcript_support_level", + "havana_transcript", + "hgnc_id", + "havana_gene", + "ont", + "protein_id", + "ccdsid" + ], + "cpu_count": 10, + "cpu_seconds": 3.075842, + "features": null, + "input_bytes": 3520115, + "path": "gencode-250k.gtf.gz", + "peak_rss_mib": 587.78125, + "platform": "macOS-26.5-arm64-arm-64bit", + "result_type": "pandas", + "rows": 250000, + "stages": { + "attributes": 2.6965094580082223, + "convert": 8.433299080934376e-05, + "other": 0.8129902930086246, + "read": 0.3873044999927515 + }, + "threads": 4, + "usecols": null, + "versions": { + "gtfparse": "3.0.0", + "numpy": "2.5.3", + "pandas": "2.3.3", + "polars": "1.44.2", + "pyarrow": "25.0.1", + "python": "3.12.6" + }, + "wall_seconds": 3.8968885840004077, + "release": "3.0.0-arrow", + "repeat": 1 + }, + { + "backend": "production", + "checksum": "8d394118a91daefd2d5ee4f50c07ef5dee567e6ad373c052fa6cf3898c807641", + "columns": [ + "seqname", + "source", + "feature", + "start", + "end", + "score", + "strand", + "frame", + "gene_id", + "gene_type", + "gene_name", + "level", + "tag", + "transcript_id", + "transcript_type", + "transcript_name", + "exon_number", + "exon_id", + "transcript_support_level", + "havana_transcript", + "hgnc_id", + "havana_gene", + "ont", + "protein_id", + "ccdsid" + ], + "cpu_count": 10, + "cpu_seconds": 2.54815, + "features": null, + "input_bytes": 3520115, + "path": "gencode-250k.gtf.gz", + "peak_rss_mib": 566.9375, + "platform": "macOS-26.5-arm64-arm-64bit", + "result_type": "pandas", + "rows": 250000, + "stages": { + "attributes": 2.345767665989115, + "convert": 7.06670107319951e-05, + "other": 0.9998161669936962, + "read": 0.39063262499985285 + }, + "threads": 4, + "usecols": null, + "versions": { + "gtfparse": "3.0.1", + "numpy": "2.5.3", + "pandas": "2.3.3", + "polars": "1.44.2", + "pyarrow": "25.0.1", + "python": "3.12.6" + }, + "wall_seconds": 3.736287124993396, + "release": "optimized", + "repeat": 1 + }, + { + "backend": "production", + "checksum": "8d394118a91daefd2d5ee4f50c07ef5dee567e6ad373c052fa6cf3898c807641", + "columns": [ + "seqname", + "source", + "feature", + "start", + "end", + "score", + "strand", + "frame", + "gene_id", + "gene_type", + "gene_name", + "level", + "tag", + "transcript_id", + "transcript_type", + "transcript_name", + "exon_number", + "exon_id", + "transcript_support_level", + "havana_transcript", + "hgnc_id", + "havana_gene", + "ont", + "protein_id", + "ccdsid" + ], + "cpu_count": 10, + "cpu_seconds": 3.087378, + "features": null, + "input_bytes": 3520115, + "path": "gencode-250k.gtf.gz", + "peak_rss_mib": 583.796875, + "platform": "macOS-26.5-arm64-arm-64bit", + "result_type": "pandas", + "rows": 250000, + "stages": { + "attributes": 2.7883104579959763, + "convert": 0.00013437500456348062, + "other": 0.7963529169937829, + "read": 0.400554749998264 + }, + "threads": 4, + "usecols": null, + "versions": { + "gtfparse": "3.0.0", + "numpy": "2.5.3", + "pandas": "2.3.3", + "polars": "1.44.2", + "pyarrow": "25.0.1", + "python": "3.12.6" + }, + "wall_seconds": 3.9853524999925867, + "release": "3.0.0-arrow", + "repeat": 2 + }, + { + "backend": "production", + "checksum": "8d394118a91daefd2d5ee4f50c07ef5dee567e6ad373c052fa6cf3898c807641", + "columns": [ + "seqname", + "source", + "feature", + "start", + "end", + "score", + "strand", + "frame", + "gene_id", + "gene_type", + "gene_name", + "level", + "tag", + "transcript_id", + "transcript_type", + "transcript_name", + "exon_number", + "exon_id", + "transcript_support_level", + "havana_transcript", + "hgnc_id", + "havana_gene", + "ont", + "protein_id", + "ccdsid" + ], + "cpu_count": 10, + "cpu_seconds": 2.6218580000000005, + "features": null, + "input_bytes": 3520115, + "path": "gencode-250k.gtf.gz", + "peak_rss_mib": 495.1875, + "platform": "macOS-26.5-arm64-arm-64bit", + "result_type": "pandas", + "rows": 250000, + "stages": { + "attributes": 2.2640662500052713, + "convert": 4.354199336376041e-05, + "other": 1.0697560000116937, + "read": 0.5061004159942968 + }, + "threads": 4, + "usecols": null, + "versions": { + "gtfparse": "3.0.1", + "numpy": "2.5.3", + "pandas": "2.3.3", + "polars": "1.44.2", + "pyarrow": "25.0.1", + "python": "3.12.6" + }, + "wall_seconds": 3.8399662080046255, + "release": "optimized", + "repeat": 2 + }, + { + "backend": "production", + "checksum": "8d394118a91daefd2d5ee4f50c07ef5dee567e6ad373c052fa6cf3898c807641", + "columns": [ + "seqname", + "source", + "feature", + "start", + "end", + "score", + "strand", + "frame", + "gene_id", + "gene_type", + "gene_name", + "level", + "tag", + "transcript_id", + "transcript_type", + "transcript_name", + "exon_number", + "exon_id", + "transcript_support_level", + "havana_transcript", + "hgnc_id", + "havana_gene", + "ont", + "protein_id", + "ccdsid" + ], + "cpu_count": 10, + "cpu_seconds": 2.790294, + "features": null, + "input_bytes": 3520115, + "path": "gencode-250k.gtf.gz", + "peak_rss_mib": 568.4375, + "platform": "macOS-26.5-arm64-arm-64bit", + "result_type": "pandas", + "rows": 250000, + "stages": { + "attributes": 2.8794367499940563, + "convert": 0.19175450000329874, + "other": 0.5437821660016198, + "read": 0.2398029169999063 + }, + "threads": 4, + "usecols": null, + "versions": { + "gtfparse": "2.9.1", + "numpy": "2.5.3", + "pandas": "2.3.3", + "polars": "1.44.2", + "pyarrow": "25.0.1", + "python": "3.12.6" + }, + "wall_seconds": 3.854776332998881, + "release": "2.9.1-polars", + "repeat": 2 + }, + { + "backend": "production", + "checksum": "8d394118a91daefd2d5ee4f50c07ef5dee567e6ad373c052fa6cf3898c807641", + "columns": [ + "seqname", + "source", + "feature", + "start", + "end", + "score", + "strand", + "frame", + "gene_id", + "gene_type", + "gene_name", + "level", + "tag", + "transcript_id", + "transcript_type", + "transcript_name", + "exon_number", + "exon_id", + "transcript_support_level", + "havana_transcript", + "hgnc_id", + "havana_gene", + "ont", + "protein_id", + "ccdsid" + ], + "cpu_count": 10, + "cpu_seconds": 3.191441, + "features": null, + "input_bytes": 109586053, + "path": "gencode-250k.gtf", + "peak_rss_mib": 551.328125, + "platform": "macOS-26.5-arm64-arm-64bit", + "result_type": "pandas", + "rows": 250000, + "stages": { + "attributes": 3.7154556659952505, + "convert": 7.458300387952477e-05, + "other": 1.3441707089950796, + "read": 0.5056541250087321 + }, + "threads": 4, + "usecols": null, + "versions": { + "gtfparse": "3.0.0", + "numpy": "2.5.3", + "pandas": "2.3.3", + "polars": "1.44.2", + "pyarrow": "25.0.1", + "python": "3.12.6" + }, + "wall_seconds": 5.565355083002942, + "release": "3.0.0-arrow", + "repeat": 2 + }, + { + "backend": "production", + "checksum": "8d394118a91daefd2d5ee4f50c07ef5dee567e6ad373c052fa6cf3898c807641", + "columns": [ + "seqname", + "source", + "feature", + "start", + "end", + "score", + "strand", + "frame", + "gene_id", + "gene_type", + "gene_name", + "level", + "tag", + "transcript_id", + "transcript_type", + "transcript_name", + "exon_number", + "exon_id", + "transcript_support_level", + "havana_transcript", + "hgnc_id", + "havana_gene", + "ont", + "protein_id", + "ccdsid" + ], + "cpu_count": 10, + "cpu_seconds": 2.425999, + "features": null, + "input_bytes": 109586053, + "path": "gencode-250k.gtf", + "peak_rss_mib": 565.484375, + "platform": "macOS-26.5-arm64-arm-64bit", + "result_type": "pandas", + "rows": 250000, + "stages": { + "attributes": 2.2242981659946963, + "convert": 7.416699372697622e-05, + "other": 0.8941883750085253, + "read": 0.5983945000043605 + }, + "threads": 4, + "usecols": null, + "versions": { + "gtfparse": "3.0.1", + "numpy": "2.5.3", + "pandas": "2.3.3", + "polars": "1.44.2", + "pyarrow": "25.0.1", + "python": "3.12.6" + }, + "wall_seconds": 3.716955208001309, + "release": "optimized", + "repeat": 2 + }, + { + "backend": "production", + "checksum": "8d394118a91daefd2d5ee4f50c07ef5dee567e6ad373c052fa6cf3898c807641", + "columns": [ + "seqname", + "source", + "feature", + "start", + "end", + "score", + "strand", + "frame", + "gene_id", + "gene_type", + "gene_name", + "level", + "tag", + "transcript_id", + "transcript_type", + "transcript_name", + "exon_number", + "exon_id", + "transcript_support_level", + "havana_transcript", + "hgnc_id", + "havana_gene", + "ont", + "protein_id", + "ccdsid" + ], + "cpu_count": 10, + "cpu_seconds": 2.5377099999999997, + "features": null, + "input_bytes": 109586053, + "path": "gencode-250k.gtf", + "peak_rss_mib": 566.484375, + "platform": "macOS-26.5-arm64-arm-64bit", + "result_type": "pandas", + "rows": 250000, + "stages": { + "attributes": 4.694422458007466, + "convert": 0.10437379199720453, + "other": 0.6516097499843454, + "read": 0.1014160000049742 + }, + "threads": 4, + "usecols": null, + "versions": { + "gtfparse": "2.9.1", + "numpy": "2.5.3", + "pandas": "2.3.3", + "polars": "1.44.2", + "pyarrow": "25.0.1", + "python": "3.12.6" + }, + "wall_seconds": 5.55182199999399, + "release": "2.9.1-polars", + "repeat": 2 + }, + { + "backend": "production", + "checksum": "be944cfa699afc930317973a3ee1ca1dc6d309c10071bc32b63a9b54abbdcca8", + "columns": [ + "seqname", + "source", + "feature", + "start", + "end", + "score", + "strand", + "frame", + "gene_id", + "gene_version", + "gene_name", + "gene_source", + "gene_biotype", + "transcript_id", + "transcript_version", + "transcript_name", + "transcript_source", + "transcript_biotype", + "tag", + "transcript_support_level", + "exon_number", + "exon_id", + "exon_version", + "protein_id", + "protein_version", + "ccds_id" + ], + "cpu_count": 10, + "cpu_seconds": 3.37763, + "features": null, + "input_bytes": 3524624, + "path": "ensembl-250k.gtf.gz", + "peak_rss_mib": 625.609375, + "platform": "macOS-26.5-arm64-arm-64bit", + "result_type": "pandas", + "rows": 250000, + "stages": { + "attributes": 3.433137957996223, + "convert": 0.5808867920131888, + "other": 1.0155575410026358, + "read": 0.4710169589961879 + }, + "threads": 4, + "usecols": null, + "versions": { + "gtfparse": "3.0.0", + "numpy": "2.5.3", + "pandas": "2.3.3", + "polars": "1.44.2", + "pyarrow": "25.0.1", + "python": "3.12.6" + }, + "wall_seconds": 5.500599250008236, + "release": "3.0.0-arrow", + "repeat": 2 + }, + { + "backend": "production", + "checksum": "be944cfa699afc930317973a3ee1ca1dc6d309c10071bc32b63a9b54abbdcca8", + "columns": [ + "seqname", + "source", + "feature", + "start", + "end", + "score", + "strand", + "frame", + "gene_id", + "gene_version", + "gene_name", + "gene_source", + "gene_biotype", + "transcript_id", + "transcript_version", + "transcript_name", + "transcript_source", + "transcript_biotype", + "tag", + "transcript_support_level", + "exon_number", + "exon_id", + "exon_version", + "protein_id", + "protein_version", + "ccds_id" + ], + "cpu_count": 10, + "cpu_seconds": 2.82855, + "features": null, + "input_bytes": 3524624, + "path": "ensembl-250k.gtf.gz", + "peak_rss_mib": 591.171875, + "platform": "macOS-26.5-arm64-arm-64bit", + "result_type": "pandas", + "rows": 250000, + "stages": { + "attributes": 1.8764499579992844, + "convert": 0.557577957995818, + "other": 1.1187510839954484, + "read": 0.4119964170095045 + }, + "threads": 4, + "usecols": null, + "versions": { + "gtfparse": "3.0.1", + "numpy": "2.5.3", + "pandas": "2.3.3", + "polars": "1.44.2", + "pyarrow": "25.0.1", + "python": "3.12.6" + }, + "wall_seconds": 3.9647754170000553, + "release": "optimized", + "repeat": 2 + }, + { + "backend": "production", + "checksum": "be944cfa699afc930317973a3ee1ca1dc6d309c10071bc32b63a9b54abbdcca8", + "columns": [ + "seqname", + "source", + "feature", + "start", + "end", + "score", + "strand", + "frame", + "gene_id", + "gene_version", + "gene_name", + "gene_source", + "gene_biotype", + "transcript_id", + "transcript_version", + "transcript_name", + "transcript_source", + "transcript_biotype", + "tag", + "transcript_support_level", + "exon_number", + "exon_id", + "exon_version", + "protein_id", + "protein_version", + "ccds_id" + ], + "cpu_count": 10, + "cpu_seconds": 3.038677, + "features": null, + "input_bytes": 3524624, + "path": "ensembl-250k.gtf.gz", + "peak_rss_mib": 561.046875, + "platform": "macOS-26.5-arm64-arm-64bit", + "result_type": "pandas", + "rows": 250000, + "stages": { + "attributes": 2.7519126660045004, + "convert": 0.5172319999983301, + "other": 0.3826471259963, + "read": 0.21517366600164678 + }, + "threads": 4, + "usecols": null, + "versions": { + "gtfparse": "2.9.1", + "numpy": "2.5.3", + "pandas": "2.3.3", + "polars": "1.44.2", + "pyarrow": "25.0.1", + "python": "3.12.6" + }, + "wall_seconds": 3.8669654580007773, + "release": "2.9.1-polars", + "repeat": 2 + }, + { + "backend": "production", + "checksum": "be944cfa699afc930317973a3ee1ca1dc6d309c10071bc32b63a9b54abbdcca8", + "columns": [ + "seqname", + "source", + "feature", + "start", + "end", + "score", + "strand", + "frame", + "gene_id", + "gene_version", + "gene_name", + "gene_source", + "gene_biotype", + "transcript_id", + "transcript_version", + "transcript_name", + "transcript_source", + "transcript_biotype", + "tag", + "transcript_support_level", + "exon_number", + "exon_id", + "exon_version", + "protein_id", + "protein_version", + "ccds_id" + ], + "cpu_count": 10, + "cpu_seconds": 3.3548989999999996, + "features": null, + "input_bytes": 111900013, + "path": "ensembl-250k.gtf", + "peak_rss_mib": 627.53125, + "platform": "macOS-26.5-arm64-arm-64bit", + "result_type": "pandas", + "rows": 250000, + "stages": { + "attributes": 2.187712124999962, + "convert": 0.3620601250004256, + "other": 0.5586184159910772, + "read": 0.35888850000628736 + }, + "threads": 4, + "usecols": null, + "versions": { + "gtfparse": "3.0.0", + "numpy": "2.5.3", + "pandas": "2.3.3", + "polars": "1.44.2", + "pyarrow": "25.0.1", + "python": "3.12.6" + }, + "wall_seconds": 3.467279165997752, + "release": "3.0.0-arrow", + "repeat": 2 + }, + { + "backend": "production", + "checksum": "be944cfa699afc930317973a3ee1ca1dc6d309c10071bc32b63a9b54abbdcca8", + "columns": [ + "seqname", + "source", + "feature", + "start", + "end", + "score", + "strand", + "frame", + "gene_id", + "gene_version", + "gene_name", + "gene_source", + "gene_biotype", + "transcript_id", + "transcript_version", + "transcript_name", + "transcript_source", + "transcript_biotype", + "tag", + "transcript_support_level", + "exon_number", + "exon_id", + "exon_version", + "protein_id", + "protein_version", + "ccds_id" + ], + "cpu_count": 10, + "cpu_seconds": 2.539217, + "features": null, + "input_bytes": 111900013, + "path": "ensembl-250k.gtf", + "peak_rss_mib": 593.40625, + "platform": "macOS-26.5-arm64-arm-64bit", + "result_type": "pandas", + "rows": 250000, + "stages": { + "attributes": 1.255412290993263, + "convert": 0.29558341699885204, + "other": 0.5362654589989688, + "read": 0.32947958300064784 + }, + "threads": 4, + "usecols": null, + "versions": { + "gtfparse": "3.0.1", + "numpy": "2.5.3", + "pandas": "2.3.3", + "polars": "1.44.2", + "pyarrow": "25.0.1", + "python": "3.12.6" + }, + "wall_seconds": 2.4167407499917317, + "release": "optimized", + "repeat": 2 + }, + { + "backend": "production", + "checksum": "be944cfa699afc930317973a3ee1ca1dc6d309c10071bc32b63a9b54abbdcca8", + "columns": [ + "seqname", + "source", + "feature", + "start", + "end", + "score", + "strand", + "frame", + "gene_id", + "gene_version", + "gene_name", + "gene_source", + "gene_biotype", + "transcript_id", + "transcript_version", + "transcript_name", + "transcript_source", + "transcript_biotype", + "tag", + "transcript_support_level", + "exon_number", + "exon_id", + "exon_version", + "protein_id", + "protein_version", + "ccds_id" + ], + "cpu_count": 10, + "cpu_seconds": 2.633258, + "features": null, + "input_bytes": 111900013, + "path": "ensembl-250k.gtf", + "peak_rss_mib": 560.328125, + "platform": "macOS-26.5-arm64-arm-64bit", + "result_type": "pandas", + "rows": 250000, + "stages": { + "attributes": 1.868775209004525, + "convert": 0.3353991249896353, + "other": 0.25759920800919645, + "read": 0.08343587499985006 + }, + "threads": 4, + "usecols": null, + "versions": { + "gtfparse": "2.9.1", + "numpy": "2.5.3", + "pandas": "2.3.3", + "polars": "1.44.2", + "pyarrow": "25.0.1", + "python": "3.12.6" + }, + "wall_seconds": 2.545209417003207, + "release": "2.9.1-polars", + "repeat": 2 + }, + { + "backend": "production", + "checksum": "be944cfa699afc930317973a3ee1ca1dc6d309c10071bc32b63a9b54abbdcca8", + "columns": [ + "seqname", + "source", + "feature", + "start", + "end", + "score", + "strand", + "frame", + "gene_id", + "gene_version", + "gene_name", + "gene_source", + "gene_biotype", + "transcript_id", + "transcript_version", + "transcript_name", + "transcript_source", + "transcript_biotype", + "tag", + "transcript_support_level", + "exon_number", + "exon_id", + "exon_version", + "protein_id", + "protein_version", + "ccds_id" + ], + "cpu_count": 10, + "cpu_seconds": 2.373172, + "features": null, + "input_bytes": 111900013, + "path": "ensembl-250k.gtf", + "peak_rss_mib": 576.484375, + "platform": "macOS-26.5-arm64-arm-64bit", + "result_type": "pandas", + "rows": 250000, + "stages": { + "attributes": 1.2345331250107847, + "convert": 0.28705333299876656, + "other": 0.502303834000486, + "read": 0.26135762500052806 + }, + "threads": 4, + "usecols": null, + "versions": { + "gtfparse": "3.0.1", + "numpy": "2.5.3", + "pandas": "2.3.3", + "polars": "1.44.2", + "pyarrow": "25.0.1", + "python": "3.12.6" + }, + "wall_seconds": 2.2852479170105653, + "release": "optimized", + "repeat": 3 + }, + { + "backend": "production", + "checksum": "be944cfa699afc930317973a3ee1ca1dc6d309c10071bc32b63a9b54abbdcca8", + "columns": [ + "seqname", + "source", + "feature", + "start", + "end", + "score", + "strand", + "frame", + "gene_id", + "gene_version", + "gene_name", + "gene_source", + "gene_biotype", + "transcript_id", + "transcript_version", + "transcript_name", + "transcript_source", + "transcript_biotype", + "tag", + "transcript_support_level", + "exon_number", + "exon_id", + "exon_version", + "protein_id", + "protein_version", + "ccds_id" + ], + "cpu_count": 10, + "cpu_seconds": 2.640136, + "features": null, + "input_bytes": 111900013, + "path": "ensembl-250k.gtf", + "peak_rss_mib": 560.671875, + "platform": "macOS-26.5-arm64-arm-64bit", + "result_type": "pandas", + "rows": 250000, + "stages": { + "attributes": 1.898370958995656, + "convert": 0.34992329200031236, + "other": 0.23822599899722263, + "read": 0.08401687500008848 + }, + "threads": 4, + "usecols": null, + "versions": { + "gtfparse": "2.9.1", + "numpy": "2.5.3", + "pandas": "2.3.3", + "polars": "1.44.2", + "pyarrow": "25.0.1", + "python": "3.12.6" + }, + "wall_seconds": 2.5705371249932796, + "release": "2.9.1-polars", + "repeat": 3 + }, + { + "backend": "production", + "checksum": "be944cfa699afc930317973a3ee1ca1dc6d309c10071bc32b63a9b54abbdcca8", + "columns": [ + "seqname", + "source", + "feature", + "start", + "end", + "score", + "strand", + "frame", + "gene_id", + "gene_version", + "gene_name", + "gene_source", + "gene_biotype", + "transcript_id", + "transcript_version", + "transcript_name", + "transcript_source", + "transcript_biotype", + "tag", + "transcript_support_level", + "exon_number", + "exon_id", + "exon_version", + "protein_id", + "protein_version", + "ccds_id" + ], + "cpu_count": 10, + "cpu_seconds": 2.943254, + "features": null, + "input_bytes": 111900013, + "path": "ensembl-250k.gtf", + "peak_rss_mib": 616.6875, + "platform": "macOS-26.5-arm64-arm-64bit", + "result_type": "pandas", + "rows": 250000, + "stages": { + "attributes": 1.87293291700189, + "convert": 0.28285558299103286, + "other": 0.4352961250115186, + "read": 0.26651462499285117 + }, + "threads": 4, + "usecols": null, + "versions": { + "gtfparse": "3.0.0", + "numpy": "2.5.3", + "pandas": "2.3.3", + "polars": "1.44.2", + "pyarrow": "25.0.1", + "python": "3.12.6" + }, + "wall_seconds": 2.8575992499972926, + "release": "3.0.0-arrow", + "repeat": 3 + }, + { + "backend": "production", + "checksum": "be944cfa699afc930317973a3ee1ca1dc6d309c10071bc32b63a9b54abbdcca8", + "columns": [ + "seqname", + "source", + "feature", + "start", + "end", + "score", + "strand", + "frame", + "gene_id", + "gene_version", + "gene_name", + "gene_source", + "gene_biotype", + "transcript_id", + "transcript_version", + "transcript_name", + "transcript_source", + "transcript_biotype", + "tag", + "transcript_support_level", + "exon_number", + "exon_id", + "exon_version", + "protein_id", + "protein_version", + "ccds_id" + ], + "cpu_count": 10, + "cpu_seconds": 2.355343, + "features": null, + "input_bytes": 3524624, + "path": "ensembl-250k.gtf.gz", + "peak_rss_mib": 574.75, + "platform": "macOS-26.5-arm64-arm-64bit", + "result_type": "pandas", + "rows": 250000, + "stages": { + "attributes": 1.2360343339969404, + "convert": 0.2817149159964174, + "other": 0.4799745410127798, + "read": 0.27661270899989177 + }, + "threads": 4, + "usecols": null, + "versions": { + "gtfparse": "3.0.1", + "numpy": "2.5.3", + "pandas": "2.3.3", + "polars": "1.44.2", + "pyarrow": "25.0.1", + "python": "3.12.6" + }, + "wall_seconds": 2.2743365000060294, + "release": "optimized", + "repeat": 3 + }, + { + "backend": "production", + "checksum": "be944cfa699afc930317973a3ee1ca1dc6d309c10071bc32b63a9b54abbdcca8", + "columns": [ + "seqname", + "source", + "feature", + "start", + "end", + "score", + "strand", + "frame", + "gene_id", + "gene_version", + "gene_name", + "gene_source", + "gene_biotype", + "transcript_id", + "transcript_version", + "transcript_name", + "transcript_source", + "transcript_biotype", + "tag", + "transcript_support_level", + "exon_number", + "exon_id", + "exon_version", + "protein_id", + "protein_version", + "ccds_id" + ], + "cpu_count": 10, + "cpu_seconds": 2.6671, + "features": null, + "input_bytes": 3524624, + "path": "ensembl-250k.gtf.gz", + "peak_rss_mib": 561.09375, + "platform": "macOS-26.5-arm64-arm-64bit", + "result_type": "pandas", + "rows": 250000, + "stages": { + "attributes": 1.8928518329921644, + "convert": 0.33677229199383873, + "other": 0.24612533301115036, + "read": 0.1267874170007417 + }, + "threads": 4, + "usecols": null, + "versions": { + "gtfparse": "2.9.1", + "numpy": "2.5.3", + "pandas": "2.3.3", + "polars": "1.44.2", + "pyarrow": "25.0.1", + "python": "3.12.6" + }, + "wall_seconds": 2.602536874997895, + "release": "2.9.1-polars", + "repeat": 3 + }, + { + "backend": "production", + "checksum": "be944cfa699afc930317973a3ee1ca1dc6d309c10071bc32b63a9b54abbdcca8", + "columns": [ + "seqname", + "source", + "feature", + "start", + "end", + "score", + "strand", + "frame", + "gene_id", + "gene_version", + "gene_name", + "gene_source", + "gene_biotype", + "transcript_id", + "transcript_version", + "transcript_name", + "transcript_source", + "transcript_biotype", + "tag", + "transcript_support_level", + "exon_number", + "exon_id", + "exon_version", + "protein_id", + "protein_version", + "ccds_id" + ], + "cpu_count": 10, + "cpu_seconds": 3.302426, + "features": null, + "input_bytes": 3524624, + "path": "ensembl-250k.gtf.gz", + "peak_rss_mib": 615.78125, + "platform": "macOS-26.5-arm64-arm-64bit", + "result_type": "pandas", + "rows": 250000, + "stages": { + "attributes": 2.818784125003731, + "convert": 0.4906274579989258, + "other": 0.9829520420025801, + "read": 0.2855122500041034 + }, + "threads": 4, + "usecols": null, + "versions": { + "gtfparse": "3.0.0", + "numpy": "2.5.3", + "pandas": "2.3.3", + "polars": "1.44.2", + "pyarrow": "25.0.1", + "python": "3.12.6" + }, + "wall_seconds": 4.57787587500934, + "release": "3.0.0-arrow", + "repeat": 3 + }, + { + "backend": "production", + "checksum": "8d394118a91daefd2d5ee4f50c07ef5dee567e6ad373c052fa6cf3898c807641", + "columns": [ + "seqname", + "source", + "feature", + "start", + "end", + "score", + "strand", + "frame", + "gene_id", + "gene_type", + "gene_name", + "level", + "tag", + "transcript_id", + "transcript_type", + "transcript_name", + "exon_number", + "exon_id", + "transcript_support_level", + "havana_transcript", + "hgnc_id", + "havana_gene", + "ont", + "protein_id", + "ccdsid" + ], + "cpu_count": 10, + "cpu_seconds": 2.4871540000000003, + "features": null, + "input_bytes": 109586053, + "path": "gencode-250k.gtf", + "peak_rss_mib": 527.203125, + "platform": "macOS-26.5-arm64-arm-64bit", + "result_type": "pandas", + "rows": 250000, + "stages": { + "attributes": 2.1337991250038613, + "convert": 4.9000009312294424e-05, + "other": 1.4431334999826504, + "read": 0.4248130839987425 + }, + "threads": 4, + "usecols": null, + "versions": { + "gtfparse": "3.0.1", + "numpy": "2.5.3", + "pandas": "2.3.3", + "polars": "1.44.2", + "pyarrow": "25.0.1", + "python": "3.12.6" + }, + "wall_seconds": 4.0017947089945665, + "release": "optimized", + "repeat": 3 + }, + { + "backend": "production", + "checksum": "8d394118a91daefd2d5ee4f50c07ef5dee567e6ad373c052fa6cf3898c807641", + "columns": [ + "seqname", + "source", + "feature", + "start", + "end", + "score", + "strand", + "frame", + "gene_id", + "gene_type", + "gene_name", + "level", + "tag", + "transcript_id", + "transcript_type", + "transcript_name", + "exon_number", + "exon_id", + "transcript_support_level", + "havana_transcript", + "hgnc_id", + "havana_gene", + "ont", + "protein_id", + "ccdsid" + ], + "cpu_count": 10, + "cpu_seconds": 2.560311, + "features": null, + "input_bytes": 109586053, + "path": "gencode-250k.gtf", + "peak_rss_mib": 567.546875, + "platform": "macOS-26.5-arm64-arm-64bit", + "result_type": "pandas", + "rows": 250000, + "stages": { + "attributes": 2.646453332999954, + "convert": 0.09764800000994, + "other": 0.3458024169958662, + "read": 0.0905030409921892 + }, + "threads": 4, + "usecols": null, + "versions": { + "gtfparse": "2.9.1", + "numpy": "2.5.3", + "pandas": "2.3.3", + "polars": "1.44.2", + "pyarrow": "25.0.1", + "python": "3.12.6" + }, + "wall_seconds": 3.1804067909979494, + "release": "2.9.1-polars", + "repeat": 3 + }, + { + "backend": "production", + "checksum": "8d394118a91daefd2d5ee4f50c07ef5dee567e6ad373c052fa6cf3898c807641", + "columns": [ + "seqname", + "source", + "feature", + "start", + "end", + "score", + "strand", + "frame", + "gene_id", + "gene_type", + "gene_name", + "level", + "tag", + "transcript_id", + "transcript_type", + "transcript_name", + "exon_number", + "exon_id", + "transcript_support_level", + "havana_transcript", + "hgnc_id", + "havana_gene", + "ont", + "protein_id", + "ccdsid" + ], + "cpu_count": 10, + "cpu_seconds": 2.658798, + "features": null, + "input_bytes": 109586053, + "path": "gencode-250k.gtf", + "peak_rss_mib": 587.6875, + "platform": "macOS-26.5-arm64-arm-64bit", + "result_type": "pandas", + "rows": 250000, + "stages": { + "attributes": 1.7814520410029218, + "convert": 7.35829962650314e-05, + "other": 0.5366334179998375, + "read": 0.26695341600861866 + }, + "threads": 4, + "usecols": null, + "versions": { + "gtfparse": "3.0.0", + "numpy": "2.5.3", + "pandas": "2.3.3", + "polars": "1.44.2", + "pyarrow": "25.0.1", + "python": "3.12.6" + }, + "wall_seconds": 2.585112458007643, + "release": "3.0.0-arrow", + "repeat": 3 + }, + { + "backend": "production", + "checksum": "8d394118a91daefd2d5ee4f50c07ef5dee567e6ad373c052fa6cf3898c807641", + "columns": [ + "seqname", + "source", + "feature", + "start", + "end", + "score", + "strand", + "frame", + "gene_id", + "gene_type", + "gene_name", + "level", + "tag", + "transcript_id", + "transcript_type", + "transcript_name", + "exon_number", + "exon_id", + "transcript_support_level", + "havana_transcript", + "hgnc_id", + "havana_gene", + "ont", + "protein_id", + "ccdsid" + ], + "cpu_count": 10, + "cpu_seconds": 2.080072, + "features": null, + "input_bytes": 3520115, + "path": "gencode-250k.gtf.gz", + "peak_rss_mib": 557.890625, + "platform": "macOS-26.5-arm64-arm-64bit", + "result_type": "pandas", + "rows": 250000, + "stages": { + "attributes": 1.1859509170026286, + "convert": 4.124999395571649e-05, + "other": 0.5394327910034917, + "read": 0.2632630000007339 + }, + "threads": 4, + "usecols": null, + "versions": { + "gtfparse": "3.0.1", + "numpy": "2.5.3", + "pandas": "2.3.3", + "polars": "1.44.2", + "pyarrow": "25.0.1", + "python": "3.12.6" + }, + "wall_seconds": 1.9886879580008099, + "release": "optimized", + "repeat": 3 + }, + { + "backend": "production", + "checksum": "8d394118a91daefd2d5ee4f50c07ef5dee567e6ad373c052fa6cf3898c807641", + "columns": [ + "seqname", + "source", + "feature", + "start", + "end", + "score", + "strand", + "frame", + "gene_id", + "gene_type", + "gene_name", + "level", + "tag", + "transcript_id", + "transcript_type", + "transcript_name", + "exon_number", + "exon_id", + "transcript_support_level", + "havana_transcript", + "hgnc_id", + "havana_gene", + "ont", + "protein_id", + "ccdsid" + ], + "cpu_count": 10, + "cpu_seconds": 2.2800469999999997, + "features": null, + "input_bytes": 3520115, + "path": "gencode-250k.gtf.gz", + "peak_rss_mib": 567.5, + "platform": "macOS-26.5-arm64-arm-64bit", + "result_type": "pandas", + "rows": 250000, + "stages": { + "attributes": 1.7495677080005407, + "convert": 0.06322920799721032, + "other": 0.27436150101129897, + "read": 0.11984191599185579 + }, + "threads": 4, + "usecols": null, + "versions": { + "gtfparse": "2.9.1", + "numpy": "2.5.3", + "pandas": "2.3.3", + "polars": "1.44.2", + "pyarrow": "25.0.1", + "python": "3.12.6" + }, + "wall_seconds": 2.207000333000906, + "release": "2.9.1-polars", + "repeat": 3 + }, + { + "backend": "production", + "checksum": "8d394118a91daefd2d5ee4f50c07ef5dee567e6ad373c052fa6cf3898c807641", + "columns": [ + "seqname", + "source", + "feature", + "start", + "end", + "score", + "strand", + "frame", + "gene_id", + "gene_type", + "gene_name", + "level", + "tag", + "transcript_id", + "transcript_type", + "transcript_name", + "exon_number", + "exon_id", + "transcript_support_level", + "havana_transcript", + "hgnc_id", + "havana_gene", + "ont", + "protein_id", + "ccdsid" + ], + "cpu_count": 10, + "cpu_seconds": 2.574939, + "features": null, + "input_bytes": 3520115, + "path": "gencode-250k.gtf.gz", + "peak_rss_mib": 580.96875, + "platform": "macOS-26.5-arm64-arm-64bit", + "result_type": "pandas", + "rows": 250000, + "stages": { + "attributes": 1.7354764170013368, + "convert": 6.454098911490291e-05, + "other": 0.5007614180067321, + "read": 0.25421366600494366 + }, + "threads": 4, + "usecols": null, + "versions": { + "gtfparse": "3.0.0", + "numpy": "2.5.3", + "pandas": "2.3.3", + "polars": "1.44.2", + "pyarrow": "25.0.1", + "python": "3.12.6" + }, + "wall_seconds": 2.4905160420021275, + "release": "3.0.0-arrow", + "repeat": 3 + }, + { + "backend": "production", + "checksum": "be944cfa699afc930317973a3ee1ca1dc6d309c10071bc32b63a9b54abbdcca8", + "columns": [ + "seqname", + "source", + "feature", + "start", + "end", + "score", + "strand", + "frame", + "gene_id", + "gene_version", + "gene_name", + "gene_source", + "gene_biotype", + "transcript_id", + "transcript_version", + "transcript_name", + "transcript_source", + "transcript_biotype", + "tag", + "transcript_support_level", + "exon_number", + "exon_id", + "exon_version", + "protein_id", + "protein_version", + "ccds_id" + ], + "cpu_count": 10, + "cpu_seconds": 2.420429, + "features": null, + "input_bytes": 111900013, + "path": "ensembl-250k.gtf", + "peak_rss_mib": 552.5, + "platform": "macOS-26.5-arm64-arm-64bit", + "result_type": "pandas", + "rows": 250000, + "stages": { + "attributes": 1.8500060840015067, + "convert": 0.22684966700035147, + "other": 0.2211527069885051, + "read": 0.2438607500080252 + }, + "threads": 4, + "usecols": null, + "versions": { + "gtfparse": "2.9.1", + "numpy": "2.5.3", + "pandas": "3.0.6", + "polars": "1.44.2", + "pyarrow": "25.0.1", + "python": "3.12.6" + }, + "wall_seconds": 2.5418692079983884, + "release": "2.9.1-polars", + "repeat": 1 + }, + { + "backend": "production", + "checksum": "be944cfa699afc930317973a3ee1ca1dc6d309c10071bc32b63a9b54abbdcca8", + "columns": [ + "seqname", + "source", + "feature", + "start", + "end", + "score", + "strand", + "frame", + "gene_id", + "gene_version", + "gene_name", + "gene_source", + "gene_biotype", + "transcript_id", + "transcript_version", + "transcript_name", + "transcript_source", + "transcript_biotype", + "tag", + "transcript_support_level", + "exon_number", + "exon_id", + "exon_version", + "protein_id", + "protein_version", + "ccds_id" + ], + "cpu_count": 10, + "cpu_seconds": 2.85385, + "features": null, + "input_bytes": 111900013, + "path": "ensembl-250k.gtf", + "peak_rss_mib": 601.796875, + "platform": "macOS-26.5-arm64-arm-64bit", + "result_type": "pandas", + "rows": 250000, + "stages": { + "attributes": 1.83066029100155, + "convert": 0.18445454101311043, + "other": 0.5475739179964876, + "read": 0.21540637499128934 + }, + "threads": 4, + "usecols": null, + "versions": { + "gtfparse": "3.0.0", + "numpy": "2.5.3", + "pandas": "3.0.6", + "polars": "1.44.2", + "pyarrow": "25.0.1", + "python": "3.12.6" + }, + "wall_seconds": 2.7780951250024373, + "release": "3.0.0-arrow", + "repeat": 1 + }, + { + "backend": "production", + "checksum": "be944cfa699afc930317973a3ee1ca1dc6d309c10071bc32b63a9b54abbdcca8", + "columns": [ + "seqname", + "source", + "feature", + "start", + "end", + "score", + "strand", + "frame", + "gene_id", + "gene_version", + "gene_name", + "gene_source", + "gene_biotype", + "transcript_id", + "transcript_version", + "transcript_name", + "transcript_source", + "transcript_biotype", + "tag", + "transcript_support_level", + "exon_number", + "exon_id", + "exon_version", + "protein_id", + "protein_version", + "ccds_id" + ], + "cpu_count": 10, + "cpu_seconds": 1.9879889999999998, + "features": null, + "input_bytes": 111900013, + "path": "ensembl-250k.gtf", + "peak_rss_mib": 576.71875, + "platform": "macOS-26.5-arm64-arm-64bit", + "result_type": "pandas", + "rows": 250000, + "stages": { + "attributes": 1.255898375005927, + "convert": 0.18790645799890626, + "other": 0.2516916669992497, + "read": 0.21114029199816287 + }, + "threads": 4, + "usecols": null, + "versions": { + "gtfparse": "3.0.1", + "numpy": "2.5.3", + "pandas": "3.0.6", + "polars": "1.44.2", + "pyarrow": "25.0.1", + "python": "3.12.6" + }, + "wall_seconds": 1.9066367920022458, + "release": "optimized", + "repeat": 1 + }, + { + "backend": "production", + "checksum": "be944cfa699afc930317973a3ee1ca1dc6d309c10071bc32b63a9b54abbdcca8", + "columns": [ + "seqname", + "source", + "feature", + "start", + "end", + "score", + "strand", + "frame", + "gene_id", + "gene_version", + "gene_name", + "gene_source", + "gene_biotype", + "transcript_id", + "transcript_version", + "transcript_name", + "transcript_source", + "transcript_biotype", + "tag", + "transcript_support_level", + "exon_number", + "exon_id", + "exon_version", + "protein_id", + "protein_version", + "ccds_id" + ], + "cpu_count": 10, + "cpu_seconds": 2.415416, + "features": null, + "input_bytes": 3524624, + "path": "ensembl-250k.gtf.gz", + "peak_rss_mib": 553.046875, + "platform": "macOS-26.5-arm64-arm-64bit", + "result_type": "pandas", + "rows": 250000, + "stages": { + "attributes": 1.846398291992955, + "convert": 0.20270275000075344, + "other": 0.22192491599707864, + "read": 0.0779351250093896 + }, + "threads": 4, + "usecols": null, + "versions": { + "gtfparse": "2.9.1", + "numpy": "2.5.3", + "pandas": "3.0.6", + "polars": "1.44.2", + "pyarrow": "25.0.1", + "python": "3.12.6" + }, + "wall_seconds": 2.3489610830001766, + "release": "2.9.1-polars", + "repeat": 1 + }, + { + "backend": "production", + "checksum": "be944cfa699afc930317973a3ee1ca1dc6d309c10071bc32b63a9b54abbdcca8", + "columns": [ + "seqname", + "source", + "feature", + "start", + "end", + "score", + "strand", + "frame", + "gene_id", + "gene_version", + "gene_name", + "gene_source", + "gene_biotype", + "transcript_id", + "transcript_version", + "transcript_name", + "transcript_source", + "transcript_biotype", + "tag", + "transcript_support_level", + "exon_number", + "exon_id", + "exon_version", + "protein_id", + "protein_version", + "ccds_id" + ], + "cpu_count": 10, + "cpu_seconds": 2.888417, + "features": null, + "input_bytes": 3524624, + "path": "ensembl-250k.gtf.gz", + "peak_rss_mib": 599.984375, + "platform": "macOS-26.5-arm64-arm-64bit", + "result_type": "pandas", + "rows": 250000, + "stages": { + "attributes": 1.8276292090013158, + "convert": 0.18389533399022184, + "other": 0.5644444149947958, + "read": 0.2280619170051068 + }, + "threads": 4, + "usecols": null, + "versions": { + "gtfparse": "3.0.0", + "numpy": "2.5.3", + "pandas": "3.0.6", + "polars": "1.44.2", + "pyarrow": "25.0.1", + "python": "3.12.6" + }, + "wall_seconds": 2.80403087499144, + "release": "3.0.0-arrow", + "repeat": 1 + }, + { + "backend": "production", + "checksum": "be944cfa699afc930317973a3ee1ca1dc6d309c10071bc32b63a9b54abbdcca8", + "columns": [ + "seqname", + "source", + "feature", + "start", + "end", + "score", + "strand", + "frame", + "gene_id", + "gene_version", + "gene_name", + "gene_source", + "gene_biotype", + "transcript_id", + "transcript_version", + "transcript_name", + "transcript_source", + "transcript_biotype", + "tag", + "transcript_support_level", + "exon_number", + "exon_id", + "exon_version", + "protein_id", + "protein_version", + "ccds_id" + ], + "cpu_count": 10, + "cpu_seconds": 1.958045, + "features": null, + "input_bytes": 3524624, + "path": "ensembl-250k.gtf.gz", + "peak_rss_mib": 574.140625, + "platform": "macOS-26.5-arm64-arm-64bit", + "result_type": "pandas", + "rows": 250000, + "stages": { + "attributes": 1.2322392920032144, + "convert": 0.1897575000039069, + "other": 0.23446987399074715, + "read": 0.2203353750082897 + }, + "threads": 4, + "usecols": null, + "versions": { + "gtfparse": "3.0.1", + "numpy": "2.5.3", + "pandas": "3.0.6", + "polars": "1.44.2", + "pyarrow": "25.0.1", + "python": "3.12.6" + }, + "wall_seconds": 1.876802041006158, + "release": "optimized", + "repeat": 1 + }, + { + "backend": "production", + "checksum": "8d394118a91daefd2d5ee4f50c07ef5dee567e6ad373c052fa6cf3898c807641", + "columns": [ + "seqname", + "source", + "feature", + "start", + "end", + "score", + "strand", + "frame", + "gene_id", + "gene_type", + "gene_name", + "level", + "tag", + "transcript_id", + "transcript_type", + "transcript_name", + "exon_number", + "exon_id", + "transcript_support_level", + "havana_transcript", + "hgnc_id", + "havana_gene", + "ont", + "protein_id", + "ccdsid" + ], + "cpu_count": 10, + "cpu_seconds": 2.116965, + "features": null, + "input_bytes": 109586053, + "path": "gencode-250k.gtf", + "peak_rss_mib": 559.671875, + "platform": "macOS-26.5-arm64-arm-64bit", + "result_type": "pandas", + "rows": 250000, + "stages": { + "attributes": 1.7515429170016432, + "convert": 0.017430042003979906, + "other": 0.24500191600236576, + "read": 0.03371124999830499 + }, + "threads": 4, + "usecols": null, + "versions": { + "gtfparse": "2.9.1", + "numpy": "2.5.3", + "pandas": "3.0.6", + "polars": "1.44.2", + "pyarrow": "25.0.1", + "python": "3.12.6" + }, + "wall_seconds": 2.047686125006294, + "release": "2.9.1-polars", + "repeat": 1 + }, + { + "backend": "production", + "checksum": "8d394118a91daefd2d5ee4f50c07ef5dee567e6ad373c052fa6cf3898c807641", + "columns": [ + "seqname", + "source", + "feature", + "start", + "end", + "score", + "strand", + "frame", + "gene_id", + "gene_type", + "gene_name", + "level", + "tag", + "transcript_id", + "transcript_type", + "transcript_name", + "exon_number", + "exon_id", + "transcript_support_level", + "havana_transcript", + "hgnc_id", + "havana_gene", + "ont", + "protein_id", + "ccdsid" + ], + "cpu_count": 10, + "cpu_seconds": 2.606457, + "features": null, + "input_bytes": 109586053, + "path": "gencode-250k.gtf", + "peak_rss_mib": 598.234375, + "platform": "macOS-26.5-arm64-arm-64bit", + "result_type": "pandas", + "rows": 250000, + "stages": { + "attributes": 1.736094084000797, + "convert": 0.00014029200247023255, + "other": 0.5668964579963358, + "read": 0.21073287499893922 + }, + "threads": 4, + "usecols": null, + "versions": { + "gtfparse": "3.0.0", + "numpy": "2.5.3", + "pandas": "3.0.6", + "polars": "1.44.2", + "pyarrow": "25.0.1", + "python": "3.12.6" + }, + "wall_seconds": 2.5138637089985423, + "release": "3.0.0-arrow", + "repeat": 1 + }, + { + "backend": "production", + "checksum": "8d394118a91daefd2d5ee4f50c07ef5dee567e6ad373c052fa6cf3898c807641", + "columns": [ + "seqname", + "source", + "feature", + "start", + "end", + "score", + "strand", + "frame", + "gene_id", + "gene_type", + "gene_name", + "level", + "tag", + "transcript_id", + "transcript_type", + "transcript_name", + "exon_number", + "exon_id", + "transcript_support_level", + "havana_transcript", + "hgnc_id", + "havana_gene", + "ont", + "protein_id", + "ccdsid" + ], + "cpu_count": 10, + "cpu_seconds": 1.784423, + "features": null, + "input_bytes": 109586053, + "path": "gencode-250k.gtf", + "peak_rss_mib": 578.703125, + "platform": "macOS-26.5-arm64-arm-64bit", + "result_type": "pandas", + "rows": 250000, + "stages": { + "attributes": 1.3149310419976246, + "convert": 2.5416011339984834e-05, + "other": 0.28562641798635013, + "read": 0.2182972080045147 + }, + "threads": 4, + "usecols": null, + "versions": { + "gtfparse": "3.0.1", + "numpy": "2.5.3", + "pandas": "3.0.6", + "polars": "1.44.2", + "pyarrow": "25.0.1", + "python": "3.12.6" + }, + "wall_seconds": 1.8188800839998294, + "release": "optimized", + "repeat": 1 + }, + { + "backend": "production", + "checksum": "8d394118a91daefd2d5ee4f50c07ef5dee567e6ad373c052fa6cf3898c807641", + "columns": [ + "seqname", + "source", + "feature", + "start", + "end", + "score", + "strand", + "frame", + "gene_id", + "gene_type", + "gene_name", + "level", + "tag", + "transcript_id", + "transcript_type", + "transcript_name", + "exon_number", + "exon_id", + "transcript_support_level", + "havana_transcript", + "hgnc_id", + "havana_gene", + "ont", + "protein_id", + "ccdsid" + ], + "cpu_count": 10, + "cpu_seconds": 2.1718260000000003, + "features": null, + "input_bytes": 3520115, + "path": "gencode-250k.gtf.gz", + "peak_rss_mib": 560.0, + "platform": "macOS-26.5-arm64-arm-64bit", + "result_type": "pandas", + "rows": 250000, + "stages": { + "attributes": 1.7444164579937933, + "convert": 0.017836250000982545, + "other": 0.26727887500601355, + "read": 0.07006466700113378 + }, + "threads": 4, + "usecols": null, + "versions": { + "gtfparse": "2.9.1", + "numpy": "2.5.3", + "pandas": "3.0.6", + "polars": "1.44.2", + "pyarrow": "25.0.1", + "python": "3.12.6" + }, + "wall_seconds": 2.099596250001923, + "release": "2.9.1-polars", + "repeat": 1 + }, + { + "backend": "production", + "checksum": "8d394118a91daefd2d5ee4f50c07ef5dee567e6ad373c052fa6cf3898c807641", + "columns": [ + "seqname", + "source", + "feature", + "start", + "end", + "score", + "strand", + "frame", + "gene_id", + "gene_type", + "gene_name", + "level", + "tag", + "transcript_id", + "transcript_type", + "transcript_name", + "exon_number", + "exon_id", + "transcript_support_level", + "havana_transcript", + "hgnc_id", + "havana_gene", + "ont", + "protein_id", + "ccdsid" + ], + "cpu_count": 10, + "cpu_seconds": 2.589577, + "features": null, + "input_bytes": 3520115, + "path": "gencode-250k.gtf.gz", + "peak_rss_mib": 595.265625, + "platform": "macOS-26.5-arm64-arm-64bit", + "result_type": "pandas", + "rows": 250000, + "stages": { + "attributes": 1.7193977919960162, + "convert": 0.0001550410088384524, + "other": 0.5679449589806609, + "read": 0.21822095800598618 + }, + "threads": 4, + "usecols": null, + "versions": { + "gtfparse": "3.0.0", + "numpy": "2.5.3", + "pandas": "3.0.6", + "polars": "1.44.2", + "pyarrow": "25.0.1", + "python": "3.12.6" + }, + "wall_seconds": 2.5057187499915017, + "release": "3.0.0-arrow", + "repeat": 1 + }, + { + "backend": "production", + "checksum": "8d394118a91daefd2d5ee4f50c07ef5dee567e6ad373c052fa6cf3898c807641", + "columns": [ + "seqname", + "source", + "feature", + "start", + "end", + "score", + "strand", + "frame", + "gene_id", + "gene_type", + "gene_name", + "level", + "tag", + "transcript_id", + "transcript_type", + "transcript_name", + "exon_number", + "exon_id", + "transcript_support_level", + "havana_transcript", + "hgnc_id", + "havana_gene", + "ont", + "protein_id", + "ccdsid" + ], + "cpu_count": 10, + "cpu_seconds": 1.789281, + "features": null, + "input_bytes": 3520115, + "path": "gencode-250k.gtf.gz", + "peak_rss_mib": 583.171875, + "platform": "macOS-26.5-arm64-arm-64bit", + "result_type": "pandas", + "rows": 250000, + "stages": { + "attributes": 1.208379874995444, + "convert": 2.6458001229912043e-05, + "other": 0.26576029100397136, + "read": 0.21722579200286418 + }, + "threads": 4, + "usecols": null, + "versions": { + "gtfparse": "3.0.1", + "numpy": "2.5.3", + "pandas": "3.0.6", + "polars": "1.44.2", + "pyarrow": "25.0.1", + "python": "3.12.6" + }, + "wall_seconds": 1.6913924160035094, + "release": "optimized", + "repeat": 1 + }, + { + "backend": "production", + "checksum": "8d394118a91daefd2d5ee4f50c07ef5dee567e6ad373c052fa6cf3898c807641", + "columns": [ + "seqname", + "source", + "feature", + "start", + "end", + "score", + "strand", + "frame", + "gene_id", + "gene_type", + "gene_name", + "level", + "tag", + "transcript_id", + "transcript_type", + "transcript_name", + "exon_number", + "exon_id", + "transcript_support_level", + "havana_transcript", + "hgnc_id", + "havana_gene", + "ont", + "protein_id", + "ccdsid" + ], + "cpu_count": 10, + "cpu_seconds": 2.6144279999999998, + "features": null, + "input_bytes": 3520115, + "path": "gencode-250k.gtf.gz", + "peak_rss_mib": 589.8125, + "platform": "macOS-26.5-arm64-arm-64bit", + "result_type": "pandas", + "rows": 250000, + "stages": { + "attributes": 1.7339677080017282, + "convert": 0.00014095898950472474, + "other": 0.5685903760022484, + "read": 0.2213319160073297 + }, + "threads": 4, + "usecols": null, + "versions": { + "gtfparse": "3.0.0", + "numpy": "2.5.3", + "pandas": "3.0.6", + "polars": "1.44.2", + "pyarrow": "25.0.1", + "python": "3.12.6" + }, + "wall_seconds": 2.524030959000811, + "release": "3.0.0-arrow", + "repeat": 2 + }, + { + "backend": "production", + "checksum": "8d394118a91daefd2d5ee4f50c07ef5dee567e6ad373c052fa6cf3898c807641", + "columns": [ + "seqname", + "source", + "feature", + "start", + "end", + "score", + "strand", + "frame", + "gene_id", + "gene_type", + "gene_name", + "level", + "tag", + "transcript_id", + "transcript_type", + "transcript_name", + "exon_number", + "exon_id", + "transcript_support_level", + "havana_transcript", + "hgnc_id", + "havana_gene", + "ont", + "protein_id", + "ccdsid" + ], + "cpu_count": 10, + "cpu_seconds": 1.827663, + "features": null, + "input_bytes": 3520115, + "path": "gencode-250k.gtf.gz", + "peak_rss_mib": 574.265625, + "platform": "macOS-26.5-arm64-arm-64bit", + "result_type": "pandas", + "rows": 250000, + "stages": { + "attributes": 1.236397083994234, + "convert": 2.5416986318305135e-05, + "other": 0.27114258201618213, + "read": 0.22319108400552068 + }, + "threads": 4, + "usecols": null, + "versions": { + "gtfparse": "3.0.1", + "numpy": "2.5.3", + "pandas": "3.0.6", + "polars": "1.44.2", + "pyarrow": "25.0.1", + "python": "3.12.6" + }, + "wall_seconds": 1.730756167002255, + "release": "optimized", + "repeat": 2 + }, + { + "backend": "production", + "checksum": "8d394118a91daefd2d5ee4f50c07ef5dee567e6ad373c052fa6cf3898c807641", + "columns": [ + "seqname", + "source", + "feature", + "start", + "end", + "score", + "strand", + "frame", + "gene_id", + "gene_type", + "gene_name", + "level", + "tag", + "transcript_id", + "transcript_type", + "transcript_name", + "exon_number", + "exon_id", + "transcript_support_level", + "havana_transcript", + "hgnc_id", + "havana_gene", + "ont", + "protein_id", + "ccdsid" + ], + "cpu_count": 10, + "cpu_seconds": 2.24322, + "features": null, + "input_bytes": 3520115, + "path": "gencode-250k.gtf.gz", + "peak_rss_mib": 560.78125, + "platform": "macOS-26.5-arm64-arm-64bit", + "result_type": "pandas", + "rows": 250000, + "stages": { + "attributes": 1.8704789170005824, + "convert": 0.024456458995700814, + "other": 0.2771191240171902, + "read": 0.08153274998767301 + }, + "threads": 4, + "usecols": null, + "versions": { + "gtfparse": "2.9.1", + "numpy": "2.5.3", + "pandas": "3.0.6", + "polars": "1.44.2", + "pyarrow": "25.0.1", + "python": "3.12.6" + }, + "wall_seconds": 2.2535872500011465, + "release": "2.9.1-polars", + "repeat": 2 + }, + { + "backend": "production", + "checksum": "8d394118a91daefd2d5ee4f50c07ef5dee567e6ad373c052fa6cf3898c807641", + "columns": [ + "seqname", + "source", + "feature", + "start", + "end", + "score", + "strand", + "frame", + "gene_id", + "gene_type", + "gene_name", + "level", + "tag", + "transcript_id", + "transcript_type", + "transcript_name", + "exon_number", + "exon_id", + "transcript_support_level", + "havana_transcript", + "hgnc_id", + "havana_gene", + "ont", + "protein_id", + "ccdsid" + ], + "cpu_count": 10, + "cpu_seconds": 2.745542, + "features": null, + "input_bytes": 109586053, + "path": "gencode-250k.gtf", + "peak_rss_mib": 591.375, + "platform": "macOS-26.5-arm64-arm-64bit", + "result_type": "pandas", + "rows": 250000, + "stages": { + "attributes": 1.8712519999971846, + "convert": 0.00015558300947304815, + "other": 0.6532173339946894, + "read": 0.22314999999071006 + }, + "threads": 4, + "usecols": null, + "versions": { + "gtfparse": "3.0.0", + "numpy": "2.5.3", + "pandas": "3.0.6", + "polars": "1.44.2", + "pyarrow": "25.0.1", + "python": "3.12.6" + }, + "wall_seconds": 2.747774916992057, + "release": "3.0.0-arrow", + "repeat": 2 + }, + { + "backend": "production", + "checksum": "8d394118a91daefd2d5ee4f50c07ef5dee567e6ad373c052fa6cf3898c807641", + "columns": [ + "seqname", + "source", + "feature", + "start", + "end", + "score", + "strand", + "frame", + "gene_id", + "gene_type", + "gene_name", + "level", + "tag", + "transcript_id", + "transcript_type", + "transcript_name", + "exon_number", + "exon_id", + "transcript_support_level", + "havana_transcript", + "hgnc_id", + "havana_gene", + "ont", + "protein_id", + "ccdsid" + ], + "cpu_count": 10, + "cpu_seconds": 1.7458540000000002, + "features": null, + "input_bytes": 109586053, + "path": "gencode-250k.gtf", + "peak_rss_mib": 576.578125, + "platform": "macOS-26.5-arm64-arm-64bit", + "result_type": "pandas", + "rows": 250000, + "stages": { + "attributes": 1.1965720830048667, + "convert": 2.504199801478535e-05, + "other": 0.25334479099547025, + "read": 0.20459700000355951 + }, + "threads": 4, + "usecols": null, + "versions": { + "gtfparse": "3.0.1", + "numpy": "2.5.3", + "pandas": "3.0.6", + "polars": "1.44.2", + "pyarrow": "25.0.1", + "python": "3.12.6" + }, + "wall_seconds": 1.6545389160019113, + "release": "optimized", + "repeat": 2 + }, + { + "backend": "production", + "checksum": "8d394118a91daefd2d5ee4f50c07ef5dee567e6ad373c052fa6cf3898c807641", + "columns": [ + "seqname", + "source", + "feature", + "start", + "end", + "score", + "strand", + "frame", + "gene_id", + "gene_type", + "gene_name", + "level", + "tag", + "transcript_id", + "transcript_type", + "transcript_name", + "exon_number", + "exon_id", + "transcript_support_level", + "havana_transcript", + "hgnc_id", + "havana_gene", + "ont", + "protein_id", + "ccdsid" + ], + "cpu_count": 10, + "cpu_seconds": 2.082073, + "features": null, + "input_bytes": 109586053, + "path": "gencode-250k.gtf", + "peak_rss_mib": 559.5, + "platform": "macOS-26.5-arm64-arm-64bit", + "result_type": "pandas", + "rows": 250000, + "stages": { + "attributes": 1.71495758301171, + "convert": 0.016908165998756886, + "other": 0.23707550199469551, + "read": 0.027257708003162406 + }, + "threads": 4, + "usecols": null, + "versions": { + "gtfparse": "2.9.1", + "numpy": "2.5.3", + "pandas": "3.0.6", + "polars": "1.44.2", + "pyarrow": "25.0.1", + "python": "3.12.6" + }, + "wall_seconds": 1.996198959008325, + "release": "2.9.1-polars", + "repeat": 2 + }, + { + "backend": "production", + "checksum": "be944cfa699afc930317973a3ee1ca1dc6d309c10071bc32b63a9b54abbdcca8", + "columns": [ + "seqname", + "source", + "feature", + "start", + "end", + "score", + "strand", + "frame", + "gene_id", + "gene_version", + "gene_name", + "gene_source", + "gene_biotype", + "transcript_id", + "transcript_version", + "transcript_name", + "transcript_source", + "transcript_biotype", + "tag", + "transcript_support_level", + "exon_number", + "exon_id", + "exon_version", + "protein_id", + "protein_version", + "ccds_id" + ], + "cpu_count": 10, + "cpu_seconds": 2.854932, + "features": null, + "input_bytes": 3524624, + "path": "ensembl-250k.gtf.gz", + "peak_rss_mib": 607.015625, + "platform": "macOS-26.5-arm64-arm-64bit", + "result_type": "pandas", + "rows": 250000, + "stages": { + "attributes": 1.81500345900713, + "convert": 0.18400516700057779, + "other": 0.5284704989899183, + "read": 0.23586362499918323 + }, + "threads": 4, + "usecols": null, + "versions": { + "gtfparse": "3.0.0", + "numpy": "2.5.3", + "pandas": "3.0.6", + "polars": "1.44.2", + "pyarrow": "25.0.1", + "python": "3.12.6" + }, + "wall_seconds": 2.7633427499968093, + "release": "3.0.0-arrow", + "repeat": 2 + }, + { + "backend": "production", + "checksum": "be944cfa699afc930317973a3ee1ca1dc6d309c10071bc32b63a9b54abbdcca8", + "columns": [ + "seqname", + "source", + "feature", + "start", + "end", + "score", + "strand", + "frame", + "gene_id", + "gene_version", + "gene_name", + "gene_source", + "gene_biotype", + "transcript_id", + "transcript_version", + "transcript_name", + "transcript_source", + "transcript_biotype", + "tag", + "transcript_support_level", + "exon_number", + "exon_id", + "exon_version", + "protein_id", + "protein_version", + "ccds_id" + ], + "cpu_count": 10, + "cpu_seconds": 1.9496789999999997, + "features": null, + "input_bytes": 3524624, + "path": "ensembl-250k.gtf.gz", + "peak_rss_mib": 572.890625, + "platform": "macOS-26.5-arm64-arm-64bit", + "result_type": "pandas", + "rows": 250000, + "stages": { + "attributes": 1.2216533339960733, + "convert": 0.18549491598969325, + "other": 0.22824766600388102, + "read": 0.22112158400705084 + }, + "threads": 4, + "usecols": null, + "versions": { + "gtfparse": "3.0.1", + "numpy": "2.5.3", + "pandas": "3.0.6", + "polars": "1.44.2", + "pyarrow": "25.0.1", + "python": "3.12.6" + }, + "wall_seconds": 1.8565174999966985, + "release": "optimized", + "repeat": 2 + }, + { + "backend": "production", + "checksum": "be944cfa699afc930317973a3ee1ca1dc6d309c10071bc32b63a9b54abbdcca8", + "columns": [ + "seqname", + "source", + "feature", + "start", + "end", + "score", + "strand", + "frame", + "gene_id", + "gene_version", + "gene_name", + "gene_source", + "gene_biotype", + "transcript_id", + "transcript_version", + "transcript_name", + "transcript_source", + "transcript_biotype", + "tag", + "transcript_support_level", + "exon_number", + "exon_id", + "exon_version", + "protein_id", + "protein_version", + "ccds_id" + ], + "cpu_count": 10, + "cpu_seconds": 2.4144940000000004, + "features": null, + "input_bytes": 3524624, + "path": "ensembl-250k.gtf.gz", + "peak_rss_mib": 553.15625, + "platform": "macOS-26.5-arm64-arm-64bit", + "result_type": "pandas", + "rows": 250000, + "stages": { + "attributes": 1.8477172499988228, + "convert": 0.20435254200128838, + "other": 0.21732766600325704, + "read": 0.07238537499506492 + }, + "threads": 4, + "usecols": null, + "versions": { + "gtfparse": "2.9.1", + "numpy": "2.5.3", + "pandas": "3.0.6", + "polars": "1.44.2", + "pyarrow": "25.0.1", + "python": "3.12.6" + }, + "wall_seconds": 2.341782832998433, + "release": "2.9.1-polars", + "repeat": 2 + }, + { + "backend": "production", + "checksum": "be944cfa699afc930317973a3ee1ca1dc6d309c10071bc32b63a9b54abbdcca8", + "columns": [ + "seqname", + "source", + "feature", + "start", + "end", + "score", + "strand", + "frame", + "gene_id", + "gene_version", + "gene_name", + "gene_source", + "gene_biotype", + "transcript_id", + "transcript_version", + "transcript_name", + "transcript_source", + "transcript_biotype", + "tag", + "transcript_support_level", + "exon_number", + "exon_id", + "exon_version", + "protein_id", + "protein_version", + "ccds_id" + ], + "cpu_count": 10, + "cpu_seconds": 2.896116, + "features": null, + "input_bytes": 111900013, + "path": "ensembl-250k.gtf", + "peak_rss_mib": 599.765625, + "platform": "macOS-26.5-arm64-arm-64bit", + "result_type": "pandas", + "rows": 250000, + "stages": { + "attributes": 1.8735739160038065, + "convert": 0.1892745829973137, + "other": 0.5461084599955939, + "read": 0.21546933299396187 + }, + "threads": 4, + "usecols": null, + "versions": { + "gtfparse": "3.0.0", + "numpy": "2.5.3", + "pandas": "3.0.6", + "polars": "1.44.2", + "pyarrow": "25.0.1", + "python": "3.12.6" + }, + "wall_seconds": 2.824426291990676, + "release": "3.0.0-arrow", + "repeat": 2 + }, + { + "backend": "production", + "checksum": "be944cfa699afc930317973a3ee1ca1dc6d309c10071bc32b63a9b54abbdcca8", + "columns": [ + "seqname", + "source", + "feature", + "start", + "end", + "score", + "strand", + "frame", + "gene_id", + "gene_version", + "gene_name", + "gene_source", + "gene_biotype", + "transcript_id", + "transcript_version", + "transcript_name", + "transcript_source", + "transcript_biotype", + "tag", + "transcript_support_level", + "exon_number", + "exon_id", + "exon_version", + "protein_id", + "protein_version", + "ccds_id" + ], + "cpu_count": 10, + "cpu_seconds": 1.981777, + "features": null, + "input_bytes": 111900013, + "path": "ensembl-250k.gtf", + "peak_rss_mib": 578.09375, + "platform": "macOS-26.5-arm64-arm-64bit", + "result_type": "pandas", + "rows": 250000, + "stages": { + "attributes": 1.241973957992741, + "convert": 0.1873781250033062, + "other": 0.23873687500599772, + "read": 0.21316074999049306 + }, + "threads": 4, + "usecols": null, + "versions": { + "gtfparse": "3.0.1", + "numpy": "2.5.3", + "pandas": "3.0.6", + "polars": "1.44.2", + "pyarrow": "25.0.1", + "python": "3.12.6" + }, + "wall_seconds": 1.8812497079925379, + "release": "optimized", + "repeat": 2 + }, + { + "backend": "production", + "checksum": "be944cfa699afc930317973a3ee1ca1dc6d309c10071bc32b63a9b54abbdcca8", + "columns": [ + "seqname", + "source", + "feature", + "start", + "end", + "score", + "strand", + "frame", + "gene_id", + "gene_version", + "gene_name", + "gene_source", + "gene_biotype", + "transcript_id", + "transcript_version", + "transcript_name", + "transcript_source", + "transcript_biotype", + "tag", + "transcript_support_level", + "exon_number", + "exon_id", + "exon_version", + "protein_id", + "protein_version", + "ccds_id" + ], + "cpu_count": 10, + "cpu_seconds": 2.414792, + "features": null, + "input_bytes": 111900013, + "path": "ensembl-250k.gtf", + "peak_rss_mib": 552.828125, + "platform": "macOS-26.5-arm64-arm-64bit", + "result_type": "pandas", + "rows": 250000, + "stages": { + "attributes": 1.8557262500107754, + "convert": 0.2145706660085125, + "other": 0.23259929296909831, + "read": 0.03862558300897945 + }, + "threads": 4, + "usecols": null, + "versions": { + "gtfparse": "2.9.1", + "numpy": "2.5.3", + "pandas": "3.0.6", + "polars": "1.44.2", + "pyarrow": "25.0.1", + "python": "3.12.6" + }, + "wall_seconds": 2.3415217919973657, + "release": "2.9.1-polars", + "repeat": 2 + }, + { + "backend": "production", + "checksum": "be944cfa699afc930317973a3ee1ca1dc6d309c10071bc32b63a9b54abbdcca8", + "columns": [ + "seqname", + "source", + "feature", + "start", + "end", + "score", + "strand", + "frame", + "gene_id", + "gene_version", + "gene_name", + "gene_source", + "gene_biotype", + "transcript_id", + "transcript_version", + "transcript_name", + "transcript_source", + "transcript_biotype", + "tag", + "transcript_support_level", + "exon_number", + "exon_id", + "exon_version", + "protein_id", + "protein_version", + "ccds_id" + ], + "cpu_count": 10, + "cpu_seconds": 2.111438, + "features": null, + "input_bytes": 111900013, + "path": "ensembl-250k.gtf", + "peak_rss_mib": 574.484375, + "platform": "macOS-26.5-arm64-arm-64bit", + "result_type": "pandas", + "rows": 250000, + "stages": { + "attributes": 1.4716607090085745, + "convert": 0.19871799999964423, + "other": 0.28257362397562247, + "read": 0.21565358400403056 + }, + "threads": 4, + "usecols": null, + "versions": { + "gtfparse": "3.0.1", + "numpy": "2.5.3", + "pandas": "3.0.6", + "polars": "1.44.2", + "pyarrow": "25.0.1", + "python": "3.12.6" + }, + "wall_seconds": 2.1686059169878718, + "release": "optimized", + "repeat": 3 + }, + { + "backend": "production", + "checksum": "be944cfa699afc930317973a3ee1ca1dc6d309c10071bc32b63a9b54abbdcca8", + "columns": [ + "seqname", + "source", + "feature", + "start", + "end", + "score", + "strand", + "frame", + "gene_id", + "gene_version", + "gene_name", + "gene_source", + "gene_biotype", + "transcript_id", + "transcript_version", + "transcript_name", + "transcript_source", + "transcript_biotype", + "tag", + "transcript_support_level", + "exon_number", + "exon_id", + "exon_version", + "protein_id", + "protein_version", + "ccds_id" + ], + "cpu_count": 10, + "cpu_seconds": 2.556296, + "features": null, + "input_bytes": 111900013, + "path": "ensembl-250k.gtf", + "peak_rss_mib": 552.21875, + "platform": "macOS-26.5-arm64-arm-64bit", + "result_type": "pandas", + "rows": 250000, + "stages": { + "attributes": 2.1370639169908827, + "convert": 0.23608004199923016, + "other": 0.31135054100013804, + "read": 0.033251375003601424 + }, + "threads": 4, + "usecols": null, + "versions": { + "gtfparse": "2.9.1", + "numpy": "2.5.3", + "pandas": "3.0.6", + "polars": "1.44.2", + "pyarrow": "25.0.1", + "python": "3.12.6" + }, + "wall_seconds": 2.7177458749938523, + "release": "2.9.1-polars", + "repeat": 3 + }, + { + "backend": "production", + "checksum": "be944cfa699afc930317973a3ee1ca1dc6d309c10071bc32b63a9b54abbdcca8", + "columns": [ + "seqname", + "source", + "feature", + "start", + "end", + "score", + "strand", + "frame", + "gene_id", + "gene_version", + "gene_name", + "gene_source", + "gene_biotype", + "transcript_id", + "transcript_version", + "transcript_name", + "transcript_source", + "transcript_biotype", + "tag", + "transcript_support_level", + "exon_number", + "exon_id", + "exon_version", + "protein_id", + "protein_version", + "ccds_id" + ], + "cpu_count": 10, + "cpu_seconds": 2.979457, + "features": null, + "input_bytes": 111900013, + "path": "ensembl-250k.gtf", + "peak_rss_mib": 590.28125, + "platform": "macOS-26.5-arm64-arm-64bit", + "result_type": "pandas", + "rows": 250000, + "stages": { + "attributes": 1.8968122079968452, + "convert": 0.18741612500161864, + "other": 0.5885198740143096, + "read": 0.22517183399759233 + }, + "threads": 4, + "usecols": null, + "versions": { + "gtfparse": "3.0.0", + "numpy": "2.5.3", + "pandas": "3.0.6", + "polars": "1.44.2", + "pyarrow": "25.0.1", + "python": "3.12.6" + }, + "wall_seconds": 2.897920041010366, + "release": "3.0.0-arrow", + "repeat": 3 + }, + { + "backend": "production", + "checksum": "be944cfa699afc930317973a3ee1ca1dc6d309c10071bc32b63a9b54abbdcca8", + "columns": [ + "seqname", + "source", + "feature", + "start", + "end", + "score", + "strand", + "frame", + "gene_id", + "gene_version", + "gene_name", + "gene_source", + "gene_biotype", + "transcript_id", + "transcript_version", + "transcript_name", + "transcript_source", + "transcript_biotype", + "tag", + "transcript_support_level", + "exon_number", + "exon_id", + "exon_version", + "protein_id", + "protein_version", + "ccds_id" + ], + "cpu_count": 10, + "cpu_seconds": 2.03234, + "features": null, + "input_bytes": 3524624, + "path": "ensembl-250k.gtf.gz", + "peak_rss_mib": 574.84375, + "platform": "macOS-26.5-arm64-arm-64bit", + "result_type": "pandas", + "rows": 250000, + "stages": { + "attributes": 1.2583790000062436, + "convert": 0.19016345900308806, + "other": 0.2520635830005631, + "read": 0.22867120799492113 + }, + "threads": 4, + "usecols": null, + "versions": { + "gtfparse": "3.0.1", + "numpy": "2.5.3", + "pandas": "3.0.6", + "polars": "1.44.2", + "pyarrow": "25.0.1", + "python": "3.12.6" + }, + "wall_seconds": 1.9292772500048159, + "release": "optimized", + "repeat": 3 + }, + { + "backend": "production", + "checksum": "be944cfa699afc930317973a3ee1ca1dc6d309c10071bc32b63a9b54abbdcca8", + "columns": [ + "seqname", + "source", + "feature", + "start", + "end", + "score", + "strand", + "frame", + "gene_id", + "gene_version", + "gene_name", + "gene_source", + "gene_biotype", + "transcript_id", + "transcript_version", + "transcript_name", + "transcript_source", + "transcript_biotype", + "tag", + "transcript_support_level", + "exon_number", + "exon_id", + "exon_version", + "protein_id", + "protein_version", + "ccds_id" + ], + "cpu_count": 10, + "cpu_seconds": 2.4895519999999998, + "features": null, + "input_bytes": 3524624, + "path": "ensembl-250k.gtf.gz", + "peak_rss_mib": 553.421875, + "platform": "macOS-26.5-arm64-arm-64bit", + "result_type": "pandas", + "rows": 250000, + "stages": { + "attributes": 1.8483212909923168, + "convert": 0.21014762499544304, + "other": 0.2704182920133462, + "read": 0.08297458299784921 + }, + "threads": 4, + "usecols": null, + "versions": { + "gtfparse": "2.9.1", + "numpy": "2.5.3", + "pandas": "3.0.6", + "polars": "1.44.2", + "pyarrow": "25.0.1", + "python": "3.12.6" + }, + "wall_seconds": 2.4118617909989553, + "release": "2.9.1-polars", + "repeat": 3 + }, + { + "backend": "production", + "checksum": "be944cfa699afc930317973a3ee1ca1dc6d309c10071bc32b63a9b54abbdcca8", + "columns": [ + "seqname", + "source", + "feature", + "start", + "end", + "score", + "strand", + "frame", + "gene_id", + "gene_version", + "gene_name", + "gene_source", + "gene_biotype", + "transcript_id", + "transcript_version", + "transcript_name", + "transcript_source", + "transcript_biotype", + "tag", + "transcript_support_level", + "exon_number", + "exon_id", + "exon_version", + "protein_id", + "protein_version", + "ccds_id" + ], + "cpu_count": 10, + "cpu_seconds": 2.9196619999999998, + "features": null, + "input_bytes": 3524624, + "path": "ensembl-250k.gtf.gz", + "peak_rss_mib": 595.125, + "platform": "macOS-26.5-arm64-arm-64bit", + "result_type": "pandas", + "rows": 250000, + "stages": { + "attributes": 1.8424518750107381, + "convert": 0.1856644170038635, + "other": 0.556629457991221, + "read": 0.23696545799612068 + }, + "threads": 4, + "usecols": null, + "versions": { + "gtfparse": "3.0.0", + "numpy": "2.5.3", + "pandas": "3.0.6", + "polars": "1.44.2", + "pyarrow": "25.0.1", + "python": "3.12.6" + }, + "wall_seconds": 2.8217112080019433, + "release": "3.0.0-arrow", + "repeat": 3 + }, + { + "backend": "production", + "checksum": "8d394118a91daefd2d5ee4f50c07ef5dee567e6ad373c052fa6cf3898c807641", + "columns": [ + "seqname", + "source", + "feature", + "start", + "end", + "score", + "strand", + "frame", + "gene_id", + "gene_type", + "gene_name", + "level", + "tag", + "transcript_id", + "transcript_type", + "transcript_name", + "exon_number", + "exon_id", + "transcript_support_level", + "havana_transcript", + "hgnc_id", + "havana_gene", + "ont", + "protein_id", + "ccdsid" + ], + "cpu_count": 10, + "cpu_seconds": 1.804453, + "features": null, + "input_bytes": 109586053, + "path": "gencode-250k.gtf", + "peak_rss_mib": 576.234375, + "platform": "macOS-26.5-arm64-arm-64bit", + "result_type": "pandas", + "rows": 250000, + "stages": { + "attributes": 1.216064499996719, + "convert": 2.633300027810037e-05, + "other": 0.28129791701212525, + "read": 0.21160841699747834 + }, + "threads": 4, + "usecols": null, + "versions": { + "gtfparse": "3.0.1", + "numpy": "2.5.3", + "pandas": "3.0.6", + "polars": "1.44.2", + "pyarrow": "25.0.1", + "python": "3.12.6" + }, + "wall_seconds": 1.7089971670066006, + "release": "optimized", + "repeat": 3 + }, + { + "backend": "production", + "checksum": "8d394118a91daefd2d5ee4f50c07ef5dee567e6ad373c052fa6cf3898c807641", + "columns": [ + "seqname", + "source", + "feature", + "start", + "end", + "score", + "strand", + "frame", + "gene_id", + "gene_type", + "gene_name", + "level", + "tag", + "transcript_id", + "transcript_type", + "transcript_name", + "exon_number", + "exon_id", + "transcript_support_level", + "havana_transcript", + "hgnc_id", + "havana_gene", + "ont", + "protein_id", + "ccdsid" + ], + "cpu_count": 10, + "cpu_seconds": 2.142511, + "features": null, + "input_bytes": 109586053, + "path": "gencode-250k.gtf", + "peak_rss_mib": 559.421875, + "platform": "macOS-26.5-arm64-arm-64bit", + "result_type": "pandas", + "rows": 250000, + "stages": { + "attributes": 1.7327500000101281, + "convert": 0.02303095800743904, + "other": 0.27439587596745696, + "read": 0.027468333006254397 + }, + "threads": 4, + "usecols": null, + "versions": { + "gtfparse": "2.9.1", + "numpy": "2.5.3", + "pandas": "3.0.6", + "polars": "1.44.2", + "pyarrow": "25.0.1", + "python": "3.12.6" + }, + "wall_seconds": 2.0576451669912785, + "release": "2.9.1-polars", + "repeat": 3 + }, + { + "backend": "production", + "checksum": "8d394118a91daefd2d5ee4f50c07ef5dee567e6ad373c052fa6cf3898c807641", + "columns": [ + "seqname", + "source", + "feature", + "start", + "end", + "score", + "strand", + "frame", + "gene_id", + "gene_type", + "gene_name", + "level", + "tag", + "transcript_id", + "transcript_type", + "transcript_name", + "exon_number", + "exon_id", + "transcript_support_level", + "havana_transcript", + "hgnc_id", + "havana_gene", + "ont", + "protein_id", + "ccdsid" + ], + "cpu_count": 10, + "cpu_seconds": 2.681481, + "features": null, + "input_bytes": 109586053, + "path": "gencode-250k.gtf", + "peak_rss_mib": 593.15625, + "platform": "macOS-26.5-arm64-arm-64bit", + "result_type": "pandas", + "rows": 250000, + "stages": { + "attributes": 1.8231396670016693, + "convert": 0.00015658400661777705, + "other": 0.6528683740034467, + "read": 0.20600433299841825 + }, + "threads": 4, + "usecols": null, + "versions": { + "gtfparse": "3.0.0", + "numpy": "2.5.3", + "pandas": "3.0.6", + "polars": "1.44.2", + "pyarrow": "25.0.1", + "python": "3.12.6" + }, + "wall_seconds": 2.682168958010152, + "release": "3.0.0-arrow", + "repeat": 3 + }, + { + "backend": "production", + "checksum": "8d394118a91daefd2d5ee4f50c07ef5dee567e6ad373c052fa6cf3898c807641", + "columns": [ + "seqname", + "source", + "feature", + "start", + "end", + "score", + "strand", + "frame", + "gene_id", + "gene_type", + "gene_name", + "level", + "tag", + "transcript_id", + "transcript_type", + "transcript_name", + "exon_number", + "exon_id", + "transcript_support_level", + "havana_transcript", + "hgnc_id", + "havana_gene", + "ont", + "protein_id", + "ccdsid" + ], + "cpu_count": 10, + "cpu_seconds": 1.7782019999999998, + "features": null, + "input_bytes": 3520115, + "path": "gencode-250k.gtf.gz", + "peak_rss_mib": 572.78125, + "platform": "macOS-26.5-arm64-arm-64bit", + "result_type": "pandas", + "rows": 250000, + "stages": { + "attributes": 1.23295112499909, + "convert": 2.3667002096772194e-05, + "other": 0.268862833007006, + "read": 0.22755545799736865 + }, + "threads": 4, + "usecols": null, + "versions": { + "gtfparse": "3.0.1", + "numpy": "2.5.3", + "pandas": "3.0.6", + "polars": "1.44.2", + "pyarrow": "25.0.1", + "python": "3.12.6" + }, + "wall_seconds": 1.7293930830055615, + "release": "optimized", + "repeat": 3 + }, + { + "backend": "production", + "checksum": "8d394118a91daefd2d5ee4f50c07ef5dee567e6ad373c052fa6cf3898c807641", + "columns": [ + "seqname", + "source", + "feature", + "start", + "end", + "score", + "strand", + "frame", + "gene_id", + "gene_type", + "gene_name", + "level", + "tag", + "transcript_id", + "transcript_type", + "transcript_name", + "exon_number", + "exon_id", + "transcript_support_level", + "havana_transcript", + "hgnc_id", + "havana_gene", + "ont", + "protein_id", + "ccdsid" + ], + "cpu_count": 10, + "cpu_seconds": 2.126937, + "features": null, + "input_bytes": 3520115, + "path": "gencode-250k.gtf.gz", + "peak_rss_mib": 560.15625, + "platform": "macOS-26.5-arm64-arm-64bit", + "result_type": "pandas", + "rows": 250000, + "stages": { + "attributes": 1.7179349170037312, + "convert": 0.018364208008279093, + "other": 0.2524259169877041, + "read": 0.06932729099935386 + }, + "threads": 4, + "usecols": null, + "versions": { + "gtfparse": "2.9.1", + "numpy": "2.5.3", + "pandas": "3.0.6", + "polars": "1.44.2", + "pyarrow": "25.0.1", + "python": "3.12.6" + }, + "wall_seconds": 2.0580523329990683, + "release": "2.9.1-polars", + "repeat": 3 + }, + { + "backend": "production", + "checksum": "8d394118a91daefd2d5ee4f50c07ef5dee567e6ad373c052fa6cf3898c807641", + "columns": [ + "seqname", + "source", + "feature", + "start", + "end", + "score", + "strand", + "frame", + "gene_id", + "gene_type", + "gene_name", + "level", + "tag", + "transcript_id", + "transcript_type", + "transcript_name", + "exon_number", + "exon_id", + "transcript_support_level", + "havana_transcript", + "hgnc_id", + "havana_gene", + "ont", + "protein_id", + "ccdsid" + ], + "cpu_count": 10, + "cpu_seconds": 2.6059170000000003, + "features": null, + "input_bytes": 3520115, + "path": "gencode-250k.gtf.gz", + "peak_rss_mib": 595.03125, + "platform": "macOS-26.5-arm64-arm-64bit", + "result_type": "pandas", + "rows": 250000, + "stages": { + "attributes": 1.7348792080010753, + "convert": 0.00019987499399576336, + "other": 0.5726997080055298, + "read": 0.2197710839973297 + }, + "threads": 4, + "usecols": null, + "versions": { + "gtfparse": "3.0.0", + "numpy": "2.5.3", + "pandas": "3.0.6", + "polars": "1.44.2", + "pyarrow": "25.0.1", + "python": "3.12.6" + }, + "wall_seconds": 2.5275498749979306, + "release": "3.0.0-arrow", + "repeat": 3 + } + ] + }, + "full": { + "description": "Complete production readers; imports/checksums outside wall time; sequential fresh processes", + "date": "2026-10-06T16:49:49.180246+00:00", + "threads": 4, + "inputs": { + "Homo_sapiens.GRCh38.114.gtf.gz": { + "bytes": 64228966, + "sha256": "75ec5b7a1bbb8ce566622dd9abf974ad37d390130325dae6d197d1a590854c50", + "rows": 4116048, + "source_url": "https://ftp.ensembl.org/pub/release-114/gtf/homo_sapiens/Homo_sapiens.GRCh38.114.gtf.gz", + "selection": "full file" + }, + "gencode.v48.primary_assembly.annotation.gtf.gz": { + "bytes": 59094311, + "sha256": "ad15e956fb7643172afca6dcaae176cc76400532392978a191c981d0a052e668", + "rows": 4119244, + "source_url": "https://ftp.ebi.ac.uk/pub/databases/gencode/Gencode_human/release_48/gencode.v48.primary_assembly.annotation.gtf.gz", + "selection": "full file" + } + }, + "summaries": [ + { + "pandas": "3.0.6", + "input": "Homo_sapiens.GRCh38.114.gtf.gz", + "release": "2.9.1-polars", + "runs": 1, + "versions": { + "gtfparse": "2.9.1", + "numpy": "2.5.3", + "pandas": "3.0.6", + "polars": "1.44.2", + "pyarrow": "25.0.1", + "python": "3.12.6" + }, + "wall_seconds": { + "median": 47.106003042004886, + "min": 47.106003042004886, + "max": 47.106003042004886 + }, + "cpu_seconds": { + "median": 41.689209, + "min": 41.689209, + "max": 41.689209 + }, + "peak_rss_mib": { + "median": 6504.0625, + "min": 6504.0625, + "max": 6504.0625 + }, + "stage_medians": { + "attributes": 34.80686404100561, + "convert": 4.723838749996503, + "other": 6.347857333996217, + "read": 1.227442917006556 + }, + "checksum": "86a89f01e15e261a4d93558f429f843ea5bfe7f7b9ab862b7b7cbc59df8d6988" + }, + { + "pandas": "3.0.6", + "input": "Homo_sapiens.GRCh38.114.gtf.gz", + "release": "3.0.0-arrow", + "runs": 1, + "versions": { + "gtfparse": "3.0.0", + "numpy": "2.5.3", + "pandas": "3.0.6", + "polars": "1.44.2", + "pyarrow": "25.0.1", + "python": "3.12.6" + }, + "wall_seconds": { + "median": 67.63390304200584, + "min": 67.63390304200584, + "max": 67.63390304200584 + }, + "cpu_seconds": { + "median": 54.188731, + "min": 54.188731, + "max": 54.188731 + }, + "peak_rss_mib": { + "median": 7198.8125, + "min": 7198.8125, + "max": 7198.8125 + }, + "stage_medians": { + "attributes": 47.70297658399795, + "convert": 3.748629665991757, + "other": 11.267300334016909, + "read": 4.914996457999223 + }, + "checksum": "86a89f01e15e261a4d93558f429f843ea5bfe7f7b9ab862b7b7cbc59df8d6988" + }, + { + "pandas": "3.0.6", + "input": "Homo_sapiens.GRCh38.114.gtf.gz", + "release": "optimized", + "runs": 1, + "versions": { + "gtfparse": "3.0.1", + "numpy": "2.5.3", + "pandas": "3.0.6", + "polars": "1.44.2", + "pyarrow": "25.0.1", + "python": "3.12.6" + }, + "wall_seconds": { + "median": 36.860391041002, + "min": 36.860391041002, + "max": 36.860391041002 + }, + "cpu_seconds": { + "median": 35.70663, + "min": 35.70663, + "max": 35.70663 + }, + "peak_rss_mib": { + "median": 3639.3125, + "min": 3639.3125, + "max": 3639.3125 + }, + "stage_medians": { + "attributes": 27.825113583006896, + "convert": 3.362754040994332, + "other": 0.15611587499734014, + "read": 5.516407542003435 + }, + "checksum": "86a89f01e15e261a4d93558f429f843ea5bfe7f7b9ab862b7b7cbc59df8d6988" + }, + { + "pandas": "3.0.6", + "input": "gencode.v48.primary_assembly.annotation.gtf.gz", + "release": "2.9.1-polars", + "runs": 1, + "versions": { + "gtfparse": "2.9.1", + "numpy": "2.5.3", + "pandas": "3.0.6", + "polars": "1.44.2", + "pyarrow": "25.0.1", + "python": "3.12.6" + }, + "wall_seconds": { + "median": 43.73683041699405, + "min": 43.73683041699405, + "max": 43.73683041699405 + }, + "cpu_seconds": { + "median": 38.00544, + "min": 38.00544, + "max": 38.00544 + }, + "peak_rss_mib": { + "median": 7090.890625, + "min": 7090.890625, + "max": 7090.890625 + }, + "stage_medians": { + "attributes": 36.88679691699508, + "convert": 0.4109674579958664, + "other": 4.4899386250035604, + "read": 1.949127416999545 + }, + "checksum": "52d9ca5d36dd0795856c27637e70e93cff34511b12226af66a07b4eb114d3d49" + }, + { + "pandas": "3.0.6", + "input": "gencode.v48.primary_assembly.annotation.gtf.gz", + "release": "3.0.0-arrow", + "runs": 1, + "versions": { + "gtfparse": "3.0.0", + "numpy": "2.5.3", + "pandas": "3.0.6", + "polars": "1.44.2", + "pyarrow": "25.0.1", + "python": "3.12.6" + }, + "wall_seconds": { + "median": 52.35360045799462, + "min": 52.35360045799462, + "max": 52.35360045799462 + }, + "cpu_seconds": { + "median": 49.702405, + "min": 49.702405, + "max": 49.702405 + }, + "peak_rss_mib": { + "median": 6559.75, + "min": 6559.75, + "max": 6559.75 + }, + "stage_medians": { + "attributes": 35.62854295800207, + "convert": 0.00019679100660141557, + "other": 12.81204349998734, + "read": 3.9128172089986037 + }, + "checksum": "52d9ca5d36dd0795856c27637e70e93cff34511b12226af66a07b4eb114d3d49" + }, + { + "pandas": "3.0.6", + "input": "gencode.v48.primary_assembly.annotation.gtf.gz", + "release": "optimized", + "runs": 1, + "versions": { + "gtfparse": "3.0.1", + "numpy": "2.5.3", + "pandas": "3.0.6", + "polars": "1.44.2", + "pyarrow": "25.0.1", + "python": "3.12.6" + }, + "wall_seconds": { + "median": 29.878576290997444, + "min": 29.878576290997444, + "max": 29.878576290997444 + }, + "cpu_seconds": { + "median": 30.355336, + "min": 30.355336, + "max": 30.355336 + }, + "peak_rss_mib": { + "median": 3697.5625, + "min": 3697.5625, + "max": 3697.5625 + }, + "stage_medians": { + "attributes": 25.754451957996935, + "convert": 2.766599936876446e-05, + "other": 0.14164995899773203, + "read": 3.9824467080034083 + }, + "checksum": "52d9ca5d36dd0795856c27637e70e93cff34511b12226af66a07b4eb114d3d49" + } + ], + "measurements": [ + { + "backend": "production", + "checksum": "86a89f01e15e261a4d93558f429f843ea5bfe7f7b9ab862b7b7cbc59df8d6988", + "columns": [ + "seqname", + "source", + "feature", + "start", + "end", + "score", + "strand", + "frame", + "gene_id", + "gene_version", + "gene_name", + "gene_source", + "gene_biotype", + "transcript_id", + "transcript_version", + "transcript_name", + "transcript_source", + "transcript_biotype", + "tag", + "transcript_support_level", + "exon_number", + "exon_id", + "exon_version", + "protein_id", + "protein_version", + "ccds_id" + ], + "cpu_count": 10, + "cpu_seconds": 41.689209, + "features": null, + "input_bytes": 64228966, + "path": "Homo_sapiens.GRCh38.114.gtf.gz", + "peak_rss_mib": 6504.0625, + "platform": "macOS-26.5-arm64-arm-64bit", + "result_type": "pandas", + "rows": 4116048, + "stages": { + "attributes": 34.80686404100561, + "convert": 4.723838749996503, + "other": 6.347857333996217, + "read": 1.227442917006556 + }, + "threads": 4, + "usecols": null, + "versions": { + "gtfparse": "2.9.1", + "numpy": "2.5.3", + "pandas": "3.0.6", + "polars": "1.44.2", + "pyarrow": "25.0.1", + "python": "3.12.6" + }, + "wall_seconds": 47.106003042004886, + "release": "2.9.1-polars", + "repeat": 1 + }, + { + "backend": "production", + "checksum": "86a89f01e15e261a4d93558f429f843ea5bfe7f7b9ab862b7b7cbc59df8d6988", + "columns": [ + "seqname", + "source", + "feature", + "start", + "end", + "score", + "strand", + "frame", + "gene_id", + "gene_version", + "gene_name", + "gene_source", + "gene_biotype", + "transcript_id", + "transcript_version", + "transcript_name", + "transcript_source", + "transcript_biotype", + "tag", + "transcript_support_level", + "exon_number", + "exon_id", + "exon_version", + "protein_id", + "protein_version", + "ccds_id" + ], + "cpu_count": 10, + "cpu_seconds": 54.188731, + "features": null, + "input_bytes": 64228966, + "path": "Homo_sapiens.GRCh38.114.gtf.gz", + "peak_rss_mib": 7198.8125, + "platform": "macOS-26.5-arm64-arm-64bit", + "result_type": "pandas", + "rows": 4116048, + "stages": { + "attributes": 47.70297658399795, + "convert": 3.748629665991757, + "other": 11.267300334016909, + "read": 4.914996457999223 + }, + "threads": 4, + "usecols": null, + "versions": { + "gtfparse": "3.0.0", + "numpy": "2.5.3", + "pandas": "3.0.6", + "polars": "1.44.2", + "pyarrow": "25.0.1", + "python": "3.12.6" + }, + "wall_seconds": 67.63390304200584, + "release": "3.0.0-arrow", + "repeat": 1 + }, + { + "backend": "production", + "checksum": "86a89f01e15e261a4d93558f429f843ea5bfe7f7b9ab862b7b7cbc59df8d6988", + "columns": [ + "seqname", + "source", + "feature", + "start", + "end", + "score", + "strand", + "frame", + "gene_id", + "gene_version", + "gene_name", + "gene_source", + "gene_biotype", + "transcript_id", + "transcript_version", + "transcript_name", + "transcript_source", + "transcript_biotype", + "tag", + "transcript_support_level", + "exon_number", + "exon_id", + "exon_version", + "protein_id", + "protein_version", + "ccds_id" + ], + "cpu_count": 10, + "cpu_seconds": 35.70663, + "features": null, + "input_bytes": 64228966, + "path": "Homo_sapiens.GRCh38.114.gtf.gz", + "peak_rss_mib": 3639.3125, + "platform": "macOS-26.5-arm64-arm-64bit", + "result_type": "pandas", + "rows": 4116048, + "stages": { + "attributes": 27.825113583006896, + "convert": 3.362754040994332, + "other": 0.15611587499734014, + "read": 5.516407542003435 + }, + "threads": 4, + "usecols": null, + "versions": { + "gtfparse": "3.0.1", + "numpy": "2.5.3", + "pandas": "3.0.6", + "polars": "1.44.2", + "pyarrow": "25.0.1", + "python": "3.12.6" + }, + "wall_seconds": 36.860391041002, + "release": "optimized", + "repeat": 1 + }, + { + "backend": "production", + "checksum": "52d9ca5d36dd0795856c27637e70e93cff34511b12226af66a07b4eb114d3d49", + "columns": [ + "seqname", + "source", + "feature", + "start", + "end", + "score", + "strand", + "frame", + "gene_id", + "gene_type", + "gene_name", + "level", + "tag", + "transcript_id", + "transcript_type", + "transcript_name", + "exon_number", + "exon_id", + "transcript_support_level", + "havana_transcript", + "hgnc_id", + "havana_gene", + "ont", + "protein_id", + "ccdsid", + "artif_dupl" + ], + "cpu_count": 10, + "cpu_seconds": 38.00544, + "features": null, + "input_bytes": 59094311, + "path": "gencode.v48.primary_assembly.annotation.gtf.gz", + "peak_rss_mib": 7090.890625, + "platform": "macOS-26.5-arm64-arm-64bit", + "result_type": "pandas", + "rows": 4119244, + "stages": { + "attributes": 36.88679691699508, + "convert": 0.4109674579958664, + "other": 4.4899386250035604, + "read": 1.949127416999545 + }, + "threads": 4, + "usecols": null, + "versions": { + "gtfparse": "2.9.1", + "numpy": "2.5.3", + "pandas": "3.0.6", + "polars": "1.44.2", + "pyarrow": "25.0.1", + "python": "3.12.6" + }, + "wall_seconds": 43.73683041699405, + "release": "2.9.1-polars", + "repeat": 1 + }, + { + "backend": "production", + "checksum": "52d9ca5d36dd0795856c27637e70e93cff34511b12226af66a07b4eb114d3d49", + "columns": [ + "seqname", + "source", + "feature", + "start", + "end", + "score", + "strand", + "frame", + "gene_id", + "gene_type", + "gene_name", + "level", + "tag", + "transcript_id", + "transcript_type", + "transcript_name", + "exon_number", + "exon_id", + "transcript_support_level", + "havana_transcript", + "hgnc_id", + "havana_gene", + "ont", + "protein_id", + "ccdsid", + "artif_dupl" + ], + "cpu_count": 10, + "cpu_seconds": 49.702405, + "features": null, + "input_bytes": 59094311, + "path": "gencode.v48.primary_assembly.annotation.gtf.gz", + "peak_rss_mib": 6559.75, + "platform": "macOS-26.5-arm64-arm-64bit", + "result_type": "pandas", + "rows": 4119244, + "stages": { + "attributes": 35.62854295800207, + "convert": 0.00019679100660141557, + "other": 12.81204349998734, + "read": 3.9128172089986037 + }, + "threads": 4, + "usecols": null, + "versions": { + "gtfparse": "3.0.0", + "numpy": "2.5.3", + "pandas": "3.0.6", + "polars": "1.44.2", + "pyarrow": "25.0.1", + "python": "3.12.6" + }, + "wall_seconds": 52.35360045799462, + "release": "3.0.0-arrow", + "repeat": 1 + }, + { + "backend": "production", + "checksum": "52d9ca5d36dd0795856c27637e70e93cff34511b12226af66a07b4eb114d3d49", + "columns": [ + "seqname", + "source", + "feature", + "start", + "end", + "score", + "strand", + "frame", + "gene_id", + "gene_type", + "gene_name", + "level", + "tag", + "transcript_id", + "transcript_type", + "transcript_name", + "exon_number", + "exon_id", + "transcript_support_level", + "havana_transcript", + "hgnc_id", + "havana_gene", + "ont", + "protein_id", + "ccdsid", + "artif_dupl" + ], + "cpu_count": 10, + "cpu_seconds": 30.355336, + "features": null, + "input_bytes": 59094311, + "path": "gencode.v48.primary_assembly.annotation.gtf.gz", + "peak_rss_mib": 3697.5625, + "platform": "macOS-26.5-arm64-arm-64bit", + "result_type": "pandas", + "rows": 4119244, + "stages": { + "attributes": 25.754451957996935, + "convert": 2.766599936876446e-05, + "other": 0.14164995899773203, + "read": 3.9824467080034083 + }, + "threads": 4, + "usecols": null, + "versions": { + "gtfparse": "3.0.1", + "numpy": "2.5.3", + "pandas": "3.0.6", + "polars": "1.44.2", + "pyarrow": "25.0.1", + "python": "3.12.6" + }, + "wall_seconds": 29.878576290997444, + "release": "optimized", + "repeat": 1 + } + ] + }, + "selective": { + "description": "Complete production readers; imports/checksums outside wall time; sequential fresh processes", + "date": "2026-10-06T16:50:13.534320+00:00", + "threads": 4, + "inputs": { + "ensembl-250k.gtf.gz": { + "bytes": 3524624, + "sha256": "3000128cb22ea68754c01bd3d72fe347c9c86d05b9cae9fed65d1440c57291cd", + "rows": 250000, + "source_url": "https://ftp.ensembl.org/pub/release-114/gtf/homo_sapiens/Homo_sapiens.GRCh38.114.gtf.gz", + "selection": "first 250000 annotation rows plus original header" + } + }, + "summaries": [ + { + "pandas": "3.0.6", + "input": "ensembl-250k.gtf.gz", + "release": "2.9.1-polars", + "runs": 1, + "versions": { + "gtfparse": "2.9.1", + "numpy": "2.5.3", + "pandas": "3.0.6", + "polars": "1.44.2", + "pyarrow": "25.0.1", + "python": "3.12.6" + }, + "wall_seconds": { + "median": 1.3659025410015602, + "min": 1.3659025410015602, + "max": 1.3659025410015602 + }, + "cpu_seconds": { + "median": 0.9866109999999999, + "min": 0.9866109999999999, + "max": 0.9866109999999999 + }, + "peak_rss_mib": { + "median": 319.515625, + "min": 319.515625, + "max": 319.515625 + }, + "stage_medians": { + "attributes": 1.0164038330112817, + "convert": 0.08103683299850672, + "other": 0.010387374990386888, + "read": 0.2580745000013849 + }, + "checksum": "82d74ad0f84f29bf2bf7aaa190846055aa244cb570b6799827b61970894e035b" + }, + { + "pandas": "3.0.6", + "input": "ensembl-250k.gtf.gz", + "release": "3.0.0-arrow", + "runs": 1, + "versions": { + "gtfparse": "3.0.0", + "numpy": "2.5.3", + "pandas": "3.0.6", + "polars": "1.44.2", + "pyarrow": "25.0.1", + "python": "3.12.6" + }, + "wall_seconds": { + "median": 1.4581702080031391, + "min": 1.4581702080031391, + "max": 1.4581702080031391 + }, + "cpu_seconds": { + "median": 1.165252, + "min": 1.165252, + "max": 1.165252 + }, + "peak_rss_mib": { + "median": 403.0625, + "min": 403.0625, + "max": 403.0625 + }, + "stage_medians": { + "attributes": 1.015940708006383, + "convert": 0.0028895419964101166, + "other": 0.052480124999419786, + "read": 0.3868598330009263 + }, + "checksum": "82d74ad0f84f29bf2bf7aaa190846055aa244cb570b6799827b61970894e035b" + }, + { + "pandas": "3.0.6", + "input": "ensembl-250k.gtf.gz", + "release": "optimized", + "runs": 1, + "versions": { + "gtfparse": "3.0.1", + "numpy": "2.5.3", + "pandas": "3.0.6", + "polars": "1.44.2", + "pyarrow": "25.0.1", + "python": "3.12.6" + }, + "wall_seconds": { + "median": 1.0357164169981843, + "min": 1.0357164169981843, + "max": 1.0357164169981843 + }, + "cpu_seconds": { + "median": 0.9732489999999999, + "min": 0.9732489999999999, + "max": 0.9732489999999999 + }, + "peak_rss_mib": { + "median": 402.984375, + "min": 402.984375, + "max": 402.984375 + }, + "stage_medians": { + "attributes": 0.6760162090067752, + "convert": 0.0008421660022577271, + "other": 0.01728591699793469, + "read": 0.3415721249912167 + }, + "checksum": "82d74ad0f84f29bf2bf7aaa190846055aa244cb570b6799827b61970894e035b" + } + ], + "measurements": [ + { + "backend": "production", + "checksum": "82d74ad0f84f29bf2bf7aaa190846055aa244cb570b6799827b61970894e035b", + "columns": [ + "seqname", + "start", + "end", + "gene_id", + "transcript_id" + ], + "cpu_count": 10, + "cpu_seconds": 0.9866109999999999, + "features": [ + "exon" + ], + "input_bytes": 3524624, + "path": "ensembl-250k.gtf.gz", + "peak_rss_mib": 319.515625, + "platform": "macOS-26.5-arm64-arm-64bit", + "result_type": "pandas", + "rows": 116284, + "stages": { + "attributes": 1.0164038330112817, + "convert": 0.08103683299850672, + "other": 0.010387374990386888, + "read": 0.2580745000013849 + }, + "threads": 4, + "usecols": [ + "seqname", + "start", + "end", + "gene_id", + "transcript_id" + ], + "versions": { + "gtfparse": "2.9.1", + "numpy": "2.5.3", + "pandas": "3.0.6", + "polars": "1.44.2", + "pyarrow": "25.0.1", + "python": "3.12.6" + }, + "wall_seconds": 1.3659025410015602, + "release": "2.9.1-polars", + "repeat": 1 + }, + { + "backend": "production", + "checksum": "82d74ad0f84f29bf2bf7aaa190846055aa244cb570b6799827b61970894e035b", + "columns": [ + "seqname", + "start", + "end", + "gene_id", + "transcript_id" + ], + "cpu_count": 10, + "cpu_seconds": 1.165252, + "features": [ + "exon" + ], + "input_bytes": 3524624, + "path": "ensembl-250k.gtf.gz", + "peak_rss_mib": 403.0625, + "platform": "macOS-26.5-arm64-arm-64bit", + "result_type": "pandas", + "rows": 116284, + "stages": { + "attributes": 1.015940708006383, + "convert": 0.0028895419964101166, + "other": 0.052480124999419786, + "read": 0.3868598330009263 + }, + "threads": 4, + "usecols": [ + "seqname", + "start", + "end", + "gene_id", + "transcript_id" + ], + "versions": { + "gtfparse": "3.0.0", + "numpy": "2.5.3", + "pandas": "3.0.6", + "polars": "1.44.2", + "pyarrow": "25.0.1", + "python": "3.12.6" + }, + "wall_seconds": 1.4581702080031391, + "release": "3.0.0-arrow", + "repeat": 1 + }, + { + "backend": "production", + "checksum": "82d74ad0f84f29bf2bf7aaa190846055aa244cb570b6799827b61970894e035b", + "columns": [ + "seqname", + "start", + "end", + "gene_id", + "transcript_id" + ], + "cpu_count": 10, + "cpu_seconds": 0.9732489999999999, + "features": [ + "exon" + ], + "input_bytes": 3524624, + "path": "ensembl-250k.gtf.gz", + "peak_rss_mib": 402.984375, + "platform": "macOS-26.5-arm64-arm-64bit", + "result_type": "pandas", + "rows": 116284, + "stages": { + "attributes": 0.6760162090067752, + "convert": 0.0008421660022577271, + "other": 0.01728591699793469, + "read": 0.3415721249912167 + }, + "threads": 4, + "usecols": [ + "seqname", + "start", + "end", + "gene_id", + "transcript_id" + ], + "versions": { + "gtfparse": "3.0.1", + "numpy": "2.5.3", + "pandas": "3.0.6", + "polars": "1.44.2", + "pyarrow": "25.0.1", + "python": "3.12.6" + }, + "wall_seconds": 1.0357164169981843, + "release": "optimized", + "repeat": 1 + } + ] + }, + "optional": { + "description": "Complete production readers; imports/checksums outside wall time; sequential fresh processes", + "date": "2026-10-06T16:50:25.858821+00:00", + "threads": 4, + "inputs": { + "ensembl-250k.gtf.gz": { + "bytes": 3524624, + "sha256": "3000128cb22ea68754c01bd3d72fe347c9c86d05b9cae9fed65d1440c57291cd", + "rows": 250000, + "source_url": "https://ftp.ensembl.org/pub/release-114/gtf/homo_sapiens/Homo_sapiens.GRCh38.114.gtf.gz", + "selection": "first 250000 annotation rows plus original header" + } + }, + "summaries": [ + { + "pandas": "3.0.6", + "input": "ensembl-250k.gtf.gz", + "release": "2.9.1-polars", + "runs": 1, + "versions": { + "gtfparse": "2.9.1", + "numpy": "2.5.3", + "pandas": "3.0.6", + "polars": "1.44.2", + "pyarrow": "25.0.1", + "python": "3.12.6" + }, + "wall_seconds": { + "median": 3.2213837079907535, + "min": 3.2213837079907535, + "max": 3.2213837079907535 + }, + "cpu_seconds": { + "median": 2.815719, + "min": 2.815719, + "max": 2.815719 + }, + "peak_rss_mib": { + "median": 511.4375, + "min": 511.4375, + "max": 511.4375 + }, + "stage_medians": { + "attributes": 2.372206415995606, + "convert": 0.4352557079982944, + "other": 0.3047657509887358, + "read": 0.10915583300811704 + }, + "checksum": "be944cfa699afc930317973a3ee1ca1dc6d309c10071bc32b63a9b54abbdcca8" + }, + { + "pandas": "3.0.6", + "input": "ensembl-250k.gtf.gz", + "release": "3.0.0-arrow", + "runs": 1, + "versions": { + "gtfparse": "3.0.0", + "numpy": "2.5.3", + "pandas": "3.0.6", + "polars": "1.44.2", + "pyarrow": "25.0.1", + "python": "3.12.6" + }, + "wall_seconds": { + "median": 3.4607763749954756, + "min": 3.4607763749954756, + "max": 3.4607763749954756 + }, + "cpu_seconds": { + "median": 3.2452810000000003, + "min": 3.2452810000000003, + "max": 3.2452810000000003 + }, + "peak_rss_mib": { + "median": 599.03125, + "min": 599.03125, + "max": 599.03125 + }, + "stage_medians": { + "attributes": 2.323183833999792, + "convert": 0.2275274999992689, + "other": 0.6323161249893019, + "read": 0.2777489160071127 + }, + "checksum": "be944cfa699afc930317973a3ee1ca1dc6d309c10071bc32b63a9b54abbdcca8" + }, + { + "pandas": "3.0.6", + "input": "ensembl-250k.gtf.gz", + "release": "optimized", + "runs": 1, + "versions": { + "gtfparse": "3.0.1", + "numpy": "2.5.3", + "pandas": "3.0.6", + "polars": "1.44.2", + "pyarrow": "25.0.1", + "python": "3.12.6" + }, + "wall_seconds": { + "median": 2.401918500007014, + "min": 2.401918500007014, + "max": 2.401918500007014 + }, + "cpu_seconds": { + "median": 2.172716, + "min": 2.172716, + "max": 2.172716 + }, + "peak_rss_mib": { + "median": 581.59375, + "min": 581.59375, + "max": 581.59375 + }, + "stage_medians": { + "attributes": 1.5562499160005245, + "convert": 0.2698556249961257, + "other": 0.3231227930082241, + "read": 0.25269016600213945 + }, + "checksum": "be944cfa699afc930317973a3ee1ca1dc6d309c10071bc32b63a9b54abbdcca8" + } + ], + "measurements": [ + { + "backend": "production", + "checksum": "be944cfa699afc930317973a3ee1ca1dc6d309c10071bc32b63a9b54abbdcca8", + "columns": [ + "seqname", + "source", + "feature", + "start", + "end", + "score", + "strand", + "frame", + "gene_id", + "gene_version", + "gene_name", + "gene_source", + "gene_biotype", + "transcript_id", + "transcript_version", + "transcript_name", + "transcript_source", + "transcript_biotype", + "tag", + "transcript_support_level", + "exon_number", + "exon_id", + "exon_version", + "protein_id", + "protein_version", + "ccds_id" + ], + "cpu_count": 10, + "cpu_seconds": 2.815719, + "features": null, + "input_bytes": 3524624, + "path": "ensembl-250k.gtf.gz", + "peak_rss_mib": 511.4375, + "platform": "macOS-26.5-arm64-arm-64bit", + "result_type": "polars", + "rows": 250000, + "stages": { + "attributes": 2.372206415995606, + "convert": 0.4352557079982944, + "other": 0.3047657509887358, + "read": 0.10915583300811704 + }, + "threads": 4, + "usecols": null, + "versions": { + "gtfparse": "2.9.1", + "numpy": "2.5.3", + "pandas": "3.0.6", + "polars": "1.44.2", + "pyarrow": "25.0.1", + "python": "3.12.6" + }, + "wall_seconds": 3.2213837079907535, + "release": "2.9.1-polars", + "repeat": 1 + }, + { + "backend": "production", + "checksum": "be944cfa699afc930317973a3ee1ca1dc6d309c10071bc32b63a9b54abbdcca8", + "columns": [ + "seqname", + "source", + "feature", + "start", + "end", + "score", + "strand", + "frame", + "gene_id", + "gene_version", + "gene_name", + "gene_source", + "gene_biotype", + "transcript_id", + "transcript_version", + "transcript_name", + "transcript_source", + "transcript_biotype", + "tag", + "transcript_support_level", + "exon_number", + "exon_id", + "exon_version", + "protein_id", + "protein_version", + "ccds_id" + ], + "cpu_count": 10, + "cpu_seconds": 3.2452810000000003, + "features": null, + "input_bytes": 3524624, + "path": "ensembl-250k.gtf.gz", + "peak_rss_mib": 599.03125, + "platform": "macOS-26.5-arm64-arm-64bit", + "result_type": "polars", + "rows": 250000, + "stages": { + "attributes": 2.323183833999792, + "convert": 0.2275274999992689, + "other": 0.6323161249893019, + "read": 0.2777489160071127 + }, + "threads": 4, + "usecols": null, + "versions": { + "gtfparse": "3.0.0", + "numpy": "2.5.3", + "pandas": "3.0.6", + "polars": "1.44.2", + "pyarrow": "25.0.1", + "python": "3.12.6" + }, + "wall_seconds": 3.4607763749954756, + "release": "3.0.0-arrow", + "repeat": 1 + }, + { + "backend": "production", + "checksum": "be944cfa699afc930317973a3ee1ca1dc6d309c10071bc32b63a9b54abbdcca8", + "columns": [ + "seqname", + "source", + "feature", + "start", + "end", + "score", + "strand", + "frame", + "gene_id", + "gene_version", + "gene_name", + "gene_source", + "gene_biotype", + "transcript_id", + "transcript_version", + "transcript_name", + "transcript_source", + "transcript_biotype", + "tag", + "transcript_support_level", + "exon_number", + "exon_id", + "exon_version", + "protein_id", + "protein_version", + "ccds_id" + ], + "cpu_count": 10, + "cpu_seconds": 2.172716, + "features": null, + "input_bytes": 3524624, + "path": "ensembl-250k.gtf.gz", + "peak_rss_mib": 581.59375, + "platform": "macOS-26.5-arm64-arm-64bit", + "result_type": "polars", + "rows": 250000, + "stages": { + "attributes": 1.5562499160005245, + "convert": 0.2698556249961257, + "other": 0.3231227930082241, + "read": 0.25269016600213945 + }, + "threads": 4, + "usecols": null, + "versions": { + "gtfparse": "3.0.1", + "numpy": "2.5.3", + "pandas": "3.0.6", + "polars": "1.44.2", + "pyarrow": "25.0.1", + "python": "3.12.6" + }, + "wall_seconds": 2.401918500007014, + "release": "optimized", + "repeat": 1 + } + ] + } + }, + "development_experiments": { + "unbatched_arrow_construction": { + "status": "rejected due to full-file temporary Python memory; excluded from final tables", + "full_sweep": { + "description": "Complete production readers; imports/checksums outside wall time; sequential fresh processes", + "date": "2026-10-06T16:22:10.192558+00:00", + "threads": 4, + "inputs": { + "Homo_sapiens.GRCh38.114.gtf.gz": { + "bytes": 64228966, + "sha256": "75ec5b7a1bbb8ce566622dd9abf974ad37d390130325dae6d197d1a590854c50" + }, + "gencode.v48.primary_assembly.annotation.gtf.gz": { + "bytes": 59094311, + "sha256": "ad15e956fb7643172afca6dcaae176cc76400532392978a191c981d0a052e668" + } + }, + "summaries": [ + { + "pandas": "3.0.6", + "input": "Homo_sapiens.GRCh38.114.gtf.gz", + "release": "2.9.1-polars", + "runs": 1, + "versions": { + "gtfparse": "2.9.1", + "numpy": "2.5.3", + "pandas": "3.0.6", + "polars": "1.44.2", + "pyarrow": "25.0.1", + "python": "3.12.6" + }, + "wall_seconds": { + "median": 38.26553320900712, + "min": 38.26553320900712, + "max": 38.26553320900712 + }, + "cpu_seconds": { + "median": 39.141783, + "min": 39.141783, + "max": 39.141783 + }, + "peak_rss_mib": { + "median": 5904.65625, + "min": 5904.65625, + "max": 5904.65625 + }, + "stage_medians": { + "attributes": 29.537428333002026, + "convert": 3.2695007080037612, + "other": 4.044133210001746, + "read": 1.4144709579995833 + }, + "checksum": "86a89f01e15e261a4d93558f429f843ea5bfe7f7b9ab862b7b7cbc59df8d6988" + }, + { + "pandas": "3.0.6", + "input": "Homo_sapiens.GRCh38.114.gtf.gz", + "release": "3.0.0-arrow", + "runs": 1, + "versions": { + "gtfparse": "3.0.0", + "numpy": "2.5.3", + "pandas": "3.0.6", + "polars": "1.44.2", + "pyarrow": "25.0.1", + "python": "3.12.6" + }, + "wall_seconds": { + "median": 50.37725683399185, + "min": 50.37725683399185, + "max": 50.37725683399185 + }, + "cpu_seconds": { + "median": 49.17406, + "min": 49.17406, + "max": 49.17406 + }, + "peak_rss_mib": { + "median": 4761.96875, + "min": 4761.96875, + "max": 4761.96875 + }, + "stage_medians": { + "attributes": 30.595317583007272, + "convert": 3.0611445410031592, + "other": 13.332102001979365, + "read": 3.388692708002054 + }, + "checksum": "86a89f01e15e261a4d93558f429f843ea5bfe7f7b9ab862b7b7cbc59df8d6988" + }, + { + "pandas": "3.0.6", + "input": "Homo_sapiens.GRCh38.114.gtf.gz", + "release": "optimized", + "runs": 1, + "versions": { + "gtfparse": "3.0.1", + "numpy": "2.5.3", + "pandas": "3.0.6", + "polars": "1.44.2", + "pyarrow": "25.0.1", + "python": "3.12.6" + }, + "wall_seconds": { + "median": 36.632469124990166, + "min": 36.632469124990166, + "max": 36.632469124990166 + }, + "cpu_seconds": { + "median": 35.212921, + "min": 35.212921, + "max": 35.212921 + }, + "peak_rss_mib": { + "median": 4345.953125, + "min": 4345.953125, + "max": 4345.953125 + }, + "stage_medians": { + "attributes": 22.29295879100391, + "convert": 3.045151915997849, + "other": 7.17012666798837, + "read": 4.124231750000035 + }, + "checksum": "86a89f01e15e261a4d93558f429f843ea5bfe7f7b9ab862b7b7cbc59df8d6988" + }, + { + "pandas": "3.0.6", + "input": "gencode.v48.primary_assembly.annotation.gtf.gz", + "release": "2.9.1-polars", + "runs": 1, + "versions": { + "gtfparse": "2.9.1", + "numpy": "2.5.3", + "pandas": "3.0.6", + "polars": "1.44.2", + "pyarrow": "25.0.1", + "python": "3.12.6" + }, + "wall_seconds": { + "median": 38.069211957990774, + "min": 38.069211957990774, + "max": 38.069211957990774 + }, + "cpu_seconds": { + "median": 38.543923, + "min": 38.543923, + "max": 38.543923 + }, + "peak_rss_mib": { + "median": 4241.171875, + "min": 4241.171875, + "max": 4241.171875 + }, + "stage_medians": { + "attributes": 29.99933870800305, + "convert": 0.44022654100263026, + "other": 6.081221167973126, + "read": 1.5484255410119658 + }, + "checksum": "52d9ca5d36dd0795856c27637e70e93cff34511b12226af66a07b4eb114d3d49" + }, + { + "pandas": "3.0.6", + "input": "gencode.v48.primary_assembly.annotation.gtf.gz", + "release": "3.0.0-arrow", + "runs": 1, + "versions": { + "gtfparse": "3.0.0", + "numpy": "2.5.3", + "pandas": "3.0.6", + "polars": "1.44.2", + "pyarrow": "25.0.1", + "python": "3.12.6" + }, + "wall_seconds": { + "median": 52.19000641599996, + "min": 52.19000641599996, + "max": 52.19000641599996 + }, + "cpu_seconds": { + "median": 49.825912, + "min": 49.825912, + "max": 49.825912 + }, + "peak_rss_mib": { + "median": 3982.234375, + "min": 3982.234375, + "max": 3982.234375 + }, + "stage_medians": { + "attributes": 31.662579041003482, + "convert": 0.0013554580073105171, + "other": 17.05685912599438, + "read": 3.4692127909947885 + }, + "checksum": "52d9ca5d36dd0795856c27637e70e93cff34511b12226af66a07b4eb114d3d49" + }, + { + "pandas": "3.0.6", + "input": "gencode.v48.primary_assembly.annotation.gtf.gz", + "release": "optimized", + "runs": 1, + "versions": { + "gtfparse": "3.0.1", + "numpy": "2.5.3", + "pandas": "3.0.6", + "polars": "1.44.2", + "pyarrow": "25.0.1", + "python": "3.12.6" + }, + "wall_seconds": { + "median": 36.182878458013874, + "min": 36.182878458013874, + "max": 36.182878458013874 + }, + "cpu_seconds": { + "median": 34.28559, + "min": 34.28559, + "max": 34.28559 + }, + "peak_rss_mib": { + "median": 5319.375, + "min": 5319.375, + "max": 5319.375 + }, + "stage_medians": { + "attributes": 24.223106332996394, + "convert": 6.958399899303913e-05, + "other": 8.451739916024962, + "read": 3.5079626249935245 + }, + "checksum": "52d9ca5d36dd0795856c27637e70e93cff34511b12226af66a07b4eb114d3d49" + } + ], + "measurements": [ + { + "backend": "production", + "checksum": "86a89f01e15e261a4d93558f429f843ea5bfe7f7b9ab862b7b7cbc59df8d6988", + "columns": [ + "seqname", + "source", + "feature", + "start", + "end", + "score", + "strand", + "frame", + "gene_id", + "gene_version", + "gene_name", + "gene_source", + "gene_biotype", + "transcript_id", + "transcript_version", + "transcript_name", + "transcript_source", + "transcript_biotype", + "tag", + "transcript_support_level", + "exon_number", + "exon_id", + "exon_version", + "protein_id", + "protein_version", + "ccds_id" + ], + "cpu_count": 10, + "cpu_seconds": 39.141783, + "features": null, + "input_bytes": 64228966, + "path": "Homo_sapiens.GRCh38.114.gtf.gz", + "peak_rss_mib": 5904.65625, + "platform": "macOS-26.5-arm64-arm-64bit", + "result_type": "pandas", + "rows": 4116048, + "stages": { + "attributes": 29.537428333002026, + "convert": 3.2695007080037612, + "other": 4.044133210001746, + "read": 1.4144709579995833 + }, + "threads": 4, + "usecols": null, + "versions": { + "gtfparse": "2.9.1", + "numpy": "2.5.3", + "pandas": "3.0.6", + "polars": "1.44.2", + "pyarrow": "25.0.1", + "python": "3.12.6" + }, + "wall_seconds": 38.26553320900712, + "release": "2.9.1-polars", + "repeat": 1 + }, + { + "backend": "production", + "checksum": "86a89f01e15e261a4d93558f429f843ea5bfe7f7b9ab862b7b7cbc59df8d6988", + "columns": [ + "seqname", + "source", + "feature", + "start", + "end", + "score", + "strand", + "frame", + "gene_id", + "gene_version", + "gene_name", + "gene_source", + "gene_biotype", + "transcript_id", + "transcript_version", + "transcript_name", + "transcript_source", + "transcript_biotype", + "tag", + "transcript_support_level", + "exon_number", + "exon_id", + "exon_version", + "protein_id", + "protein_version", + "ccds_id" + ], + "cpu_count": 10, + "cpu_seconds": 49.17406, + "features": null, + "input_bytes": 64228966, + "path": "Homo_sapiens.GRCh38.114.gtf.gz", + "peak_rss_mib": 4761.96875, + "platform": "macOS-26.5-arm64-arm-64bit", + "result_type": "pandas", + "rows": 4116048, + "stages": { + "attributes": 30.595317583007272, + "convert": 3.0611445410031592, + "other": 13.332102001979365, + "read": 3.388692708002054 + }, + "threads": 4, + "usecols": null, + "versions": { + "gtfparse": "3.0.0", + "numpy": "2.5.3", + "pandas": "3.0.6", + "polars": "1.44.2", + "pyarrow": "25.0.1", + "python": "3.12.6" + }, + "wall_seconds": 50.37725683399185, + "release": "3.0.0-arrow", + "repeat": 1 + }, + { + "backend": "production", + "checksum": "86a89f01e15e261a4d93558f429f843ea5bfe7f7b9ab862b7b7cbc59df8d6988", + "columns": [ + "seqname", + "source", + "feature", + "start", + "end", + "score", + "strand", + "frame", + "gene_id", + "gene_version", + "gene_name", + "gene_source", + "gene_biotype", + "transcript_id", + "transcript_version", + "transcript_name", + "transcript_source", + "transcript_biotype", + "tag", + "transcript_support_level", + "exon_number", + "exon_id", + "exon_version", + "protein_id", + "protein_version", + "ccds_id" + ], + "cpu_count": 10, + "cpu_seconds": 35.212921, + "features": null, + "input_bytes": 64228966, + "path": "Homo_sapiens.GRCh38.114.gtf.gz", + "peak_rss_mib": 4345.953125, + "platform": "macOS-26.5-arm64-arm-64bit", + "result_type": "pandas", + "rows": 4116048, + "stages": { + "attributes": 22.29295879100391, + "convert": 3.045151915997849, + "other": 7.17012666798837, + "read": 4.124231750000035 + }, + "threads": 4, + "usecols": null, + "versions": { + "gtfparse": "3.0.1", + "numpy": "2.5.3", + "pandas": "3.0.6", + "polars": "1.44.2", + "pyarrow": "25.0.1", + "python": "3.12.6" + }, + "wall_seconds": 36.632469124990166, + "release": "optimized", + "repeat": 1 + }, + { + "backend": "production", + "checksum": "52d9ca5d36dd0795856c27637e70e93cff34511b12226af66a07b4eb114d3d49", + "columns": [ + "seqname", + "source", + "feature", + "start", + "end", + "score", + "strand", + "frame", + "gene_id", + "gene_type", + "gene_name", + "level", + "tag", + "transcript_id", + "transcript_type", + "transcript_name", + "exon_number", + "exon_id", + "transcript_support_level", + "havana_transcript", + "hgnc_id", + "havana_gene", + "ont", + "protein_id", + "ccdsid", + "artif_dupl" + ], + "cpu_count": 10, + "cpu_seconds": 38.543923, + "features": null, + "input_bytes": 59094311, + "path": "gencode.v48.primary_assembly.annotation.gtf.gz", + "peak_rss_mib": 4241.171875, + "platform": "macOS-26.5-arm64-arm-64bit", + "result_type": "pandas", + "rows": 4119244, + "stages": { + "attributes": 29.99933870800305, + "convert": 0.44022654100263026, + "other": 6.081221167973126, + "read": 1.5484255410119658 + }, + "threads": 4, + "usecols": null, + "versions": { + "gtfparse": "2.9.1", + "numpy": "2.5.3", + "pandas": "3.0.6", + "polars": "1.44.2", + "pyarrow": "25.0.1", + "python": "3.12.6" + }, + "wall_seconds": 38.069211957990774, + "release": "2.9.1-polars", + "repeat": 1 + }, + { + "backend": "production", + "checksum": "52d9ca5d36dd0795856c27637e70e93cff34511b12226af66a07b4eb114d3d49", + "columns": [ + "seqname", + "source", + "feature", + "start", + "end", + "score", + "strand", + "frame", + "gene_id", + "gene_type", + "gene_name", + "level", + "tag", + "transcript_id", + "transcript_type", + "transcript_name", + "exon_number", + "exon_id", + "transcript_support_level", + "havana_transcript", + "hgnc_id", + "havana_gene", + "ont", + "protein_id", + "ccdsid", + "artif_dupl" + ], + "cpu_count": 10, + "cpu_seconds": 49.825912, + "features": null, + "input_bytes": 59094311, + "path": "gencode.v48.primary_assembly.annotation.gtf.gz", + "peak_rss_mib": 3982.234375, + "platform": "macOS-26.5-arm64-arm-64bit", + "result_type": "pandas", + "rows": 4119244, + "stages": { + "attributes": 31.662579041003482, + "convert": 0.0013554580073105171, + "other": 17.05685912599438, + "read": 3.4692127909947885 + }, + "threads": 4, + "usecols": null, + "versions": { + "gtfparse": "3.0.0", + "numpy": "2.5.3", + "pandas": "3.0.6", + "polars": "1.44.2", + "pyarrow": "25.0.1", + "python": "3.12.6" + }, + "wall_seconds": 52.19000641599996, + "release": "3.0.0-arrow", + "repeat": 1 + }, + { + "backend": "production", + "checksum": "52d9ca5d36dd0795856c27637e70e93cff34511b12226af66a07b4eb114d3d49", + "columns": [ + "seqname", + "source", + "feature", + "start", + "end", + "score", + "strand", + "frame", + "gene_id", + "gene_type", + "gene_name", + "level", + "tag", + "transcript_id", + "transcript_type", + "transcript_name", + "exon_number", + "exon_id", + "transcript_support_level", + "havana_transcript", + "hgnc_id", + "havana_gene", + "ont", + "protein_id", + "ccdsid", + "artif_dupl" + ], + "cpu_count": 10, + "cpu_seconds": 34.28559, + "features": null, + "input_bytes": 59094311, + "path": "gencode.v48.primary_assembly.annotation.gtf.gz", + "peak_rss_mib": 5319.375, + "platform": "macOS-26.5-arm64-arm-64bit", + "result_type": "pandas", + "rows": 4119244, + "stages": { + "attributes": 24.223106332996394, + "convert": 6.958399899303913e-05, + "other": 8.451739916024962, + "read": 3.5079626249935245 + }, + "threads": 4, + "usecols": null, + "versions": { + "gtfparse": "3.0.1", + "numpy": "2.5.3", + "pandas": "3.0.6", + "polars": "1.44.2", + "pyarrow": "25.0.1", + "python": "3.12.6" + }, + "wall_seconds": 36.182878458013874, + "release": "optimized", + "repeat": 1 + } + ] + }, + "gencode_repeat": { + "backend": "production", + "checksum": "52d9ca5d36dd0795856c27637e70e93cff34511b12226af66a07b4eb114d3d49", + "columns": [ + "seqname", + "source", + "feature", + "start", + "end", + "score", + "strand", + "frame", + "gene_id", + "gene_type", + "gene_name", + "level", + "tag", + "transcript_id", + "transcript_type", + "transcript_name", + "exon_number", + "exon_id", + "transcript_support_level", + "havana_transcript", + "hgnc_id", + "havana_gene", + "ont", + "protein_id", + "ccdsid", + "artif_dupl" + ], + "cpu_count": 10, + "cpu_seconds": 31.624218999999997, + "features": null, + "input_bytes": 59094311, + "path": "/private/tmp/gtfparse-polars-migration/gencode.v48.primary_assembly.annotation.gtf.gz", + "peak_rss_mib": 5973.859375, + "platform": "macOS-26.5-arm64-arm-64bit", + "result_type": "pandas", + "rows": 4119244, + "stages": { + "attributes": 21.284394458009047, + "convert": 6.145800580270588e-05, + "other": 6.3738490419782465, + "read": 3.6806942080002045 + }, + "threads": 4, + "usecols": null, + "versions": { + "gtfparse": "3.0.1", + "numpy": "2.5.3", + "pandas": "3.0.6", + "polars": "1.44.2", + "pyarrow": "25.0.1", + "python": "3.12.6" + }, + "wall_seconds": 31.3389991659933 + } + }, + "100000_row_batches": { + "status": "initial memory diagnostic; final implementation uses 250000 rows; excluded from final tables", + "gencode_measurement": { + "backend": "production", + "checksum": "52d9ca5d36dd0795856c27637e70e93cff34511b12226af66a07b4eb114d3d49", + "columns": [ + "seqname", + "source", + "feature", + "start", + "end", + "score", + "strand", + "frame", + "gene_id", + "gene_type", + "gene_name", + "level", + "tag", + "transcript_id", + "transcript_type", + "transcript_name", + "exon_number", + "exon_id", + "transcript_support_level", + "havana_transcript", + "hgnc_id", + "havana_gene", + "ont", + "protein_id", + "ccdsid", + "artif_dupl" + ], + "cpu_count": 10, + "cpu_seconds": 32.886145, + "features": null, + "input_bytes": 59094311, + "path": "/private/tmp/gtfparse-polars-migration/gencode.v48.primary_assembly.annotation.gtf.gz", + "peak_rss_mib": 2322.4375, + "platform": "macOS-26.5-arm64-arm-64bit", + "result_type": "pandas", + "rows": 4119244, + "stages": { + "attributes": 34.13356716699491, + "convert": 3.616600588429719e-05, + "other": 0.03949662500235718, + "read": 5.900347957998747 + }, + "threads": 4, + "usecols": null, + "versions": { + "gtfparse": "3.0.1", + "numpy": "2.5.3", + "pandas": "3.0.6", + "polars": "1.44.2", + "pyarrow": "25.0.1", + "python": "3.12.6" + }, + "wall_seconds": 40.073447916001896 + } + } + } +} diff --git a/benchmarks/optimization.md b/benchmarks/optimization.md new file mode 100644 index 0000000..f4a4370 --- /dev/null +++ b/benchmarks/optimization.md @@ -0,0 +1,147 @@ +# Complete-load optimization in 3.0.1 + +Version 3.0.1 retains the pandas default and optional Polars output introduced +in 3.0.0. It improves the shared Python attribute parser and the construction +of expanded pandas columns while keeping the supported reader behavior. + +## Changes + +- Capture attribute names and double-quoted values directly in the compiled + regex. Other quoted/unquoted values and pre-split sequences keep their + permissive cleanup and custom quote handling. Avoid splitting and slicing + every ordinary double-quoted pair and looking up each name twice. +- Convert raw attributes with missing entries mapped to None. For configured + Arrow strings, expand and construct columns in batches of 250,000 rows, then + retain compact Arrow chunks. Release each batch and temporary expanded list + after conversion. Fill missing prefixes/gaps with empty strings and preserve + first-seen column order, fixed-field collisions and global progress counts. + This bounds temporary Python values for large files, addressing #91. Other + string representations keep their compatible full-list construction. +- When pandas' configured inferred string dtype uses Arrow storage, construct + the Arrow string array directly and wrap it in that same pandas dtype. This + avoids an intermediate object-array inference pass. Other configured string + representations retain their ordinary pandas construction behavior. + +Column order, collisions with fixed fields, repeated and empty attributes, +custom quote/missing-value parameters, callbacks/cancellation, aliases, casts, +raw mode, filtering, gzip and caller-owned streams keep their previous behavior. +No process-wide pandas settings change. Numeric/categorical fixed-field reading +and the nine-field validation remain the same. + +## Reproduction and method + +Use the same benchmark interpreter/dependency versions for all release roots. +The recorded subsets use Python 3.12.6, pandas 2.3.3 or 3.0.6, NumPy 2.5.3, +Arrow 25.0.1 and optional Polars 1.44.2 with four threads. Extract the old package +sources into isolated directories, without changing their dependency versions: + +```sh +mkdir -p /tmp/gtfparse-2.9.1 /tmp/gtfparse-3.0.0 +git archive 3e0912c gtfparse | tar -x -C /tmp/gtfparse-2.9.1 +git archive be449cb gtfparse | tar -x -C /tmp/gtfparse-3.0.0 +python benchmarks/compare_releases.py \ + ensembl-250k.gtf ensembl-250k.gtf.gz gencode-250k.gtf gencode-250k.gtf.gz \ + --baseline 2.9.1-polars /tmp/gtfparse-2.9.1 \ + --baseline 3.0.0-arrow /tmp/gtfparse-3.0.0 \ + --python /path/to/pandas-2.3-env/bin/python \ + --python /path/to/pandas-3.0-env/bin/python \ + --repeats 3 --threads 4 --output comparisons.json +``` + +Install matching dependencies, including optional Polars for the historical +reader, in both environments. Each child starts a fresh process and runs the +complete production `read_gtf`; processes execute sequentially. Reader order +rotates and corpus order reverses between repetitions. Imports are outside the +reported load time. Peak RSS includes imported libraries and is captured before +content hashing. No OS-cache flushing or machine isolation is claimed. + +The first 250,000 annotation rows and original header of Ensembl release 114 +human GRCh38 and GENCODE v48 human primary assembly are the same inputs used in +[the migration benchmark](README.md#corpus-and-equivalence). Original URLs, +selection rules and hashes are retained there and in results.json. Complete +files provide separate scaling checks. Every run checks all column contents +and order against the other releases; different representations are normalized +only for hashing. Exact dtypes are checked separately against 3.0.0. + +Use `--features exon --usecols seqname start end gene_id transcript_id` for +selective-load comparisons and `--result-type polars` for optional output. +The JSON records contain versions, content hashes, dimensions, stage times, +median/min/max and pre-validation peak RSS. A JSON-lines sidecar is flushed +on each successful read, so failed experiments retain their completed records. +Compare complete times; the old and current read-stage callbacks cover different +conversion work and do not establish a pure CSV-engine speed ratio. + +## Results + +The table contains three-run medians of complete loads with equivalent pandas +output. All 72 runs match content hashes and column order across releases and +pandas versions. Times and memory are fresh measurements from this sweep; +compare readers within this table rather than mixing earlier timings from a +shared workstation. + +| pandas | Input (250k rows) | 2.9.1 Polars s | 3.0.0 Arrow s | 3.0.1 s | Polars MiB | 3.0.0 MiB | 3.0.1 MiB | +| --- | --- | ---: | ---: | ---: | ---: | ---: | ---: | +| 2.3.3 | ensembl-250k.gtf | 2.57 | 2.91 | 2.29 | 560 | 617 | 583 | +| 2.3.3 | ensembl-250k.gtf.gz | 2.86 | 4.58 | 2.36 | 561 | 620 | 584 | +| 2.3.3 | gencode-250k.gtf | 3.18 | 2.59 | 3.72 | 567 | 588 | 550 | +| 2.3.3 | gencode-250k.gtf.gz | 3.61 | 3.90 | 3.74 | 568 | 584 | 558 | +| 3.0.6 | ensembl-250k.gtf | 2.54 | 2.82 | 1.91 | 552 | 600 | 577 | +| 3.0.6 | ensembl-250k.gtf.gz | 2.35 | 2.80 | 1.88 | 553 | 600 | 574 | +| 3.0.6 | gencode-250k.gtf | 2.05 | 2.68 | 1.71 | 560 | 593 | 577 | +| 3.0.6 | gencode-250k.gtf.gz | 2.10 | 2.52 | 1.73 | 560 | 595 | 574 | + +On pandas 3.0.6, the optimized reader takes 17–25% less time than the Polars +baseline and 31–36% less time than 3.0.0 across all four cases. On pandas 2.3.3, +the Ensembl medians improve, while GENCODE wall times are mixed and highly +variable (individual complete reads span about 2–5.6 seconds). All retained +CPU-time medians improve, but that does not establish a wall-time speedup in +those noisy cases. No runs are discarded. Subset peak RSS is 3–6% lower than +3.0.0 and ranges from about 3% lower to 4% higher than Polars. + +The repeated corpus is a prefix of each annotation, so feature/attribute +distributions can differ from complete files. This demonstrates results for +gtfparse's complete pipeline, rather than a universal pandas-versus-Polars +engine comparison. Batched assembly bounds temporary Python attribute values +when pandas uses Arrow strings; it does not make the entire reader streaming. +Python/object string storage remains supported without this memory reduction. + +The full-file checks use pandas 3.0.6 and the same versions/thread count, with +one fresh process per reader. All six complete loads match content and column +order. These single observations demonstrate scaling and correctness, and do +not establish repeated full-file throughput. + +| Full gzip input | Rows | Polars s | 3.0.0 s | 3.0.1 s | Polars MiB | 3.0.0 MiB | 3.0.1 MiB | +| --- | ---: | ---: | ---: | ---: | ---: | ---: | ---: | +| Ensembl GRCh38.114 | 4,116,048 | 47.11 | 67.63 | 36.86 | 6504 | 7199 | 3639 | +| GENCODE v48 primary | 4,119,244 | 43.74 | 52.35 | 29.88 | 7091 | 6560 | 3698 | + +Here the optimized reader takes 22–32% less time and 44–48% less peak RSS than +Polars. Compared with 3.0.0, it takes 43–45% less time and 44–49% less peak RSS. +The shared workstation was running other workloads; RSS and wall times vary +between sweeps. Compare the matched observations above, not runs from different +measurement windows. The benefit applies to configured Arrow string storage. + +Selective reads and explicit Polars output match all contents in separate +one-pass comparisons; these checks do not establish repeated throughput for +those configurations. [optimization-results.json](optimization-results.json) +retains every final record, version, input hash, stage median and range. +The rejected unbatched full-file candidate is retained separately: its full +GENCODE peak RSS reached 5.2 GiB and 5.8 GiB on a repeat. That small-sample +optimization was replaced with bounded temporary attribute assembly before +this release. Its timings are excluded from the final result tables. + +## Correctness and compatibility + +The differential tests freeze the pre-optimization tokenization and compare +quoted/unquoted, custom quote delimiters, Unicode/whitespace, malformed fragments, +repeated/empty values, pre-split rows, missing-value sentinels and column +selection. Additional tests check configured Python/Arrow string storage, batch +boundaries, late-discovered columns, missing batches, fixed-field attribute +collisions, first-seen order and global progress counts. Existing tests cover streams, null fields, exact +integer coordinates, comments/BOM, aliases, converters, progress/cancellation, +optional Polars, dictionary output and writer round trips. + +The verification sweep compares 71 full API/dtype combinations on each pandas +version against 3.0.0, including all five real fixtures and configured string +storage. CI exercises Python 3.9+, minimum/current pandas and Arrow, the base +installation without Polars, optional Polars versions and packaged source tests. diff --git a/gtfparse/attribute_parsing.py b/gtfparse/attribute_parsing.py index 495156c..e60dbfc 100644 --- a/gtfparse/attribute_parsing.py +++ b/gtfparse/attribute_parsing.py @@ -13,7 +13,6 @@ import logging import re from collections import OrderedDict -from sys import intern logger = logging.getLogger(__name__) @@ -21,7 +20,9 @@ # re module so the low-level split column agrees with # attribute expansion. Unquoted values and single quotes are accepted as well. ATTRIBUTE_PATTERN = r"""[^\s;]+[ \t]+(?:"[^"]*"|'[^']*'|[^;]+)""" -_ATTRIBUTE_PAIRS = re.compile(ATTRIBUTE_PATTERN) +# Capture double-quoted values without their delimiters. Other values retain +# their original quoting for custom quote_char and pre-split input support. +_ATTRIBUTE_PAIRS = re.compile(r"""([^\s;]+)[ \t]+(?:"([^"]*)"|('[^']*'|[^;]+))""") def expand_attribute_strings( @@ -61,61 +62,51 @@ def expand_attribute_strings( n = len(attribute_strings) extra_columns = {} - column_order = [] - - # While parsing millions of repeated strings (e.g. "gene_id" and "TP53"), - # we can save a lot of memory by making sure there's only one string - # object per unique column name. Cache interned names locally as well. - column_interned_strings = {} if progress_callback is not None: progress_callback("attributes", 0, n) for i, kv_strings in enumerate(attribute_strings): if isinstance(kv_strings, str): - kv_strings = _ATTRIBUTE_PAIRS.findall(kv_strings) + pairs = _ATTRIBUTE_PAIRS.findall(kv_strings) elif kv_strings is None: - kv_strings = () - for kv in kv_strings: - # Split once: values such as transcript_support_level may include - # spaces, and whitespace between a key and its value may vary. - parts = kv.strip().split(None, 1) - - if len(parts) != 2: - continue - - column_name, value = parts - - try: - column_name = column_interned_strings[column_name] - except KeyError: - column_name = intern(column_name) - column_interned_strings[column_name] = column_name - + pairs = () + else: + # Already separated pairs retain their permissive split behavior. + pairs = ( + (parts[0], "", parts[1]) + for kv in kv_strings + if len(parts := kv.strip().split(None, 1)) == 2 + ) + for column_name, double_quoted, other in pairs: if usecols is not None and column_name not in usecols: continue - if len(value) >= 2 and value[0] in ('"', quote_char) and value[-1] == value[0]: - value = value[1:-1] - - try: - column = extra_columns[column_name] - # if an attribute is used repeatedly then - # keep track of all its values in a list - old_value = column[i] - if old_value is missing_value: - column[i] = value - else: - column[i] = "%s,%s" % (old_value, value) - except KeyError: + if other: + value = other.strip() + if not value: + continue + if len(value) >= 2 and value[0] in ('"', quote_char) and value[-1] == value[0]: + value = value[1:-1] + else: + value = double_quoted + + column = extra_columns.get(column_name) + if column is None: column = [missing_value] * n - column[i] = value extra_columns[column_name] = column - column_order.append(column_name) - - completed = i + 1 - if progress_callback is not None and (completed % 10_000 == 0 or completed == n): - progress_callback("attributes", completed, n) - - logger.info("Extracted GTF attributes: %s", column_order) - return OrderedDict((column_name, extra_columns[column_name]) for column_name in column_order) + column[i] = value + elif column[i] is missing_value: + column[i] = value + else: + # Preserve repeated attributes and the missing-value identity + # convention, including repeated empty quoted values. + column[i] = "%s,%s" % (column[i], value) + + if progress_callback is not None: + completed = i + 1 + if completed % 10_000 == 0 or completed == n: + progress_callback("attributes", completed, n) + + logger.info("Extracted GTF attributes: %s", list(extra_columns)) + return OrderedDict(extra_columns) diff --git a/gtfparse/read_gtf.py b/gtfparse/read_gtf.py index 42b1913..9dc4f0d 100644 --- a/gtfparse/read_gtf.py +++ b/gtfparse/read_gtf.py @@ -14,6 +14,7 @@ from os.path import exists import pandas as pd +import pyarrow as pa from ._polars import require_polars from ._read_csv import REQUIRED_COLUMNS as REQUIRED_COLUMNS @@ -147,6 +148,47 @@ def parse_gtf_pandas(*args, **kwargs): return result +_ATTRIBUTE_BATCH_SIZE = 250_000 + + +def _expand_attributes_as_arrow(attributes, usecols, progress_callback): + """Keep temporary Python values bounded while retaining Arrow column chunks.""" + total = len(attributes) + columns = {} + string_type = pa.large_string() + empty = pa.scalar("", type=string_type) + if progress_callback is not None: + progress_callback("attributes", 0, total) + + def report(stage, completed, _total): + absolute = start + completed + if completed and (absolute % 10_000 == 0 or absolute == total): + progress_callback(stage, absolute, total) + + for start in range(0, total, _ATTRIBUTE_BATCH_SIZE): + stop = min(start + _ATTRIBUTE_BATCH_SIZE, total) + values = attributes.iloc[start:stop].to_numpy(dtype=object, na_value=None) + expanded = expand_attribute_strings( + values, + usecols=usecols, + progress_callback=report if progress_callback is not None else None, + ) + del values + missing = columns.keys() - expanded.keys() + if missing: + blank = pa.repeat(empty, stop - start) + for name in missing: + columns[name].append(blank) + prefix = None + for name in list(expanded): + if name not in columns: + if start and prefix is None: + prefix = pa.repeat(empty, start) + columns[name] = [prefix] if start else [] + columns[name].append(pa.array(expanded.pop(name), type=string_type)) + return {name: pa.chunked_array(chunks, type=string_type) for name, chunks in columns.items()} + + def parse_gtf_and_expand_attributes( filepath_or_buffer, restrict_attribute_columns=None, features=None, *, progress_callback=None ): @@ -181,15 +223,26 @@ def parse_gtf_and_expand_attributes( elif restrict_attribute_columns: restrict_attribute_columns = set(restrict_attribute_columns) attributes = df.pop("attribute") - attributes = attributes.astype(object).where(attributes.notna(), None) - expanded = expand_attribute_strings( - attributes, - usecols=restrict_attribute_columns, - progress_callback=progress_callback, - ) + string_dtype = pd.Series([""]).dtype + arrow_strings = isinstance(string_dtype, pd.StringDtype) and string_dtype.storage == "pyarrow" + if arrow_strings: + expanded = _expand_attributes_as_arrow( + attributes, restrict_attribute_columns, progress_callback + ) + else: + expanded = expand_attribute_strings( + attributes.to_numpy(dtype=object, na_value=None), + usecols=restrict_attribute_columns, + progress_callback=progress_callback, + ) + # Release raw strings before assembling the final pandas columns. + del attributes # Assigning a colliding attribute replaces its fixed column, matching the # previous reader, while preserving the fixed columns' original positions. - for name, values in expanded.items(): + for name in list(expanded): + values = expanded.pop(name) + if arrow_strings: + values = pd.array(values, dtype=string_dtype) df[name] = values return df diff --git a/tasks/todo.md b/tasks/todo.md index 33a153d..f5622e8 100644 --- a/tasks/todo.md +++ b/tasks/todo.md @@ -379,3 +379,109 @@ into a fresh base environment loads from site-packages, installs no Polars, and round-trips all five real fixtures. Archive runner mismatch fixed as #88; shipped lint/tests pass with python -m pytest. Release status and published artifact verification will be recorded on the PR to keep clean master clean. + +# Follow-up: optimize general GTF loading beyond the Polars baseline + +## Specification + +The user requested a PR to improve the pandas/Arrow implementation and attempt +repeatable complete-load performance better than the old Polars implementation, +without narrowing supported inputs or API behavior. Version this as 3.0.1. + +Preserve all expanded/raw GTF semantics, fixed numeric/categorical and inferred +string dtypes, arbitrary/repeated/quoted attributes, column collisions/order, +missing-value conventions, custom quote/missing-value parameters, pre-split +attribute sequences, usecols/aliases/converters/version casts/biotype inference, +optional Polars/dict output, comments/BOM/exact field validation, gzip/short or +nonseekable caller-owned streams, callbacks and cancellation. Keep Python 3.9+, +minimum dependencies and the base installation without Polars working. Do not +change global pandas options or add a compiled/mandatory optional dependency. + +Profile complete reads and attribute expansion on actual Ensembl/GENCODE data. +Evaluate captured attribute pairs, fewer Python allocations/dictionary lookups, +and avoiding unnecessary raw-string conversion/copies; evaluate Arrow conversion +settings only if they help complete-load time or peak memory without semantic +changes. Keep the smallest robust implementation. Add equivalence tests for +optimized parsing against the original regex/split behavior, including malformed +and mixed quoting, empty/repeated fields, arbitrary whitespace and pre-split input. +Document and file any newly discovered existing bugs rather than silently fixing +behavior during an optimization. + +Preserve 3.0.0 and 2.9.1 baselines. Compare all three complete production pipelines +in fresh sequential processes with four threads, interleaved/reversed ordering, +three repeats, pandas 2.3.3 and 3.0.6, Ensembl/GENCODE 250k-row plain/gzip corpora. +Check full-content hashes outside timing. Also run a full GENCODE scaling check; +record actual corpus/version/ranges/RSS and distinguish repeated throughput from +single full-file observations. Include optional output and selective-load checks. +A failure to beat Polars on every case is an honest result, not permission to +weaken input validation or generality. Publish a worthwhile measured improvement +with its limits; do not claim pure CSV speed from differently scoped read stages. + +## Plan + +- [x] Create feature branch, read lessons/API/benchmarks, preserve 3.0.0 baseline. +- [x] Profile dominant costs and measure equivalent candidate implementations. +- [x] Implement the smallest measured improvements, preserving public behavior. +- [x] Add differential parser/API regression coverage and review edge cases. +- [x] Run lint/tests in normal, no-Polars, minimum and optional environments. +- [x] Record repeated complete-reader comparisons and full-file scaling evidence. +- [x] Update version/benchmark documentation and review final diff. +- [ ] Open PR, pass checks, merge, deploy from clean master and verify PyPI. +- [ ] Review remaining relevant issues and record the next candidate on the PR. + +## Review + +The optimized parser captures double-quoted values directly and removes the +split/intern lookup work on ordinary raw attributes, while preserving the legacy +fallback grammar and pre-split support. For configured Arrow strings, 250,000-row +batches retain compact Arrow chunks and release temporary Python values. Missing +prefixes/gaps, late columns, first-seen order, collisions and global progress are +preserved. Python/object storage keeps compatible full-list construction. + +The frozen legacy parser oracle covers custom quotes/sentinels, arbitrary +malformed fragments, repetitions, pre-split values and selection. 71 full API/dtype +comparisons against 3.0.0 pass on each pandas version (142 total). Configured +Python/Arrow storage, batch boundaries and fixed-field collisions pass. Final +script, compatibility-environment and packaging results follow below. + +The final repeated subset sweep completes all 72 fresh-process reads with +matching hashes. On pandas 3.0.6, median load time is 17–25% lower than 2.9.1 +Polars and 31–36% lower than 3.0.0. pandas 2.3.3 Ensembl medians improve, while +GENCODE wall times are mixed and highly variable; all runs and ranges remain in +the report. Subset peak RSS is 3–6% lower than 3.0.0 and about -3% to +4% relative +to Polars. Full-file scaling and final selective/optional checks follow below. + +Memory replan: the unbatched candidate's full GENCODE RSS was higher than the +3.0.0 observation, and a repeat remained high. Both existing 3.0.0 and that +candidate materialized Python values for the entire file despite compact final +Arrow strings. Filed #91 and replaced unbounded temporary attribute construction +with batches, retaining the public expansion contract and configured string +storage. Rejected full-file observations are retained separately, rather than +mixed into final medians. The first 100,000-row-batch GENCODE check reduced peak +RSS to 2.3 GiB and matched content; final comparisons use 250,000-row batches. + +Final release status will be recorded on the PR so clean master remains clean +for ./deploy.sh. + +Final validation: ./lint.sh passes. Normal ./test.sh passes 213 tests with +90% coverage. Base pandas 3.0.6/Arrow 25 and pandas 3.0.6/Arrow 18 pass 199 tests +plus 10 optional skips (96% coverage). Minimum Python 3.9/pandas 2.2.2/Arrow 18 +passes 199 plus 10 skips (88%; configured object strings omit the Arrow branch). +Minimum optional Polars 0.20.31 passes 212 plus one modern-only skip (97%, existing +native categorical-remapping warning). Tests treat DeprecationWarning as errors. + +All 84 final benchmark runs match expected content/order. Full Ensembl (4,116,048 +rows) takes 36.86 s/3639 MiB versus Polars 47.11 s/6504 MiB and 3.0.0 67.63 s/7199 +MiB. Full GENCODE (4,119,244 rows) takes 29.88 s/3698 MiB versus Polars 43.74 s/7091 +MiB and 3.0.0 52.35 s/6560 MiB. These are single observations per reader on the +shared workstation, distinct from the repeated subset medians. Final selective +exon/five-column and optional Polars-output checks also match all three releases. +84 final records and separately labeled development evidence are retained in +benchmarks/optimization-results.json. Version is bumped to 3.0.1. + +Packaging review: wheel and source distribution build successfully, have identical +3.0.1 dependency metadata, and pass strict Twine checks. The wheel excludes tests +and benchmarks; the source archive includes the new regression tests, runner and +retained evidence. Its shipped ./lint.sh and ./test.sh pass (199 plus 10 optional +skips, 96% coverage). Production code, test oracle and benchmark method reviewed; +release/checklist completion will be recorded on the PR after merge and PyPI. diff --git a/tests/test_attribute_optimization.py b/tests/test_attribute_optimization.py new file mode 100644 index 0000000..234c53e --- /dev/null +++ b/tests/test_attribute_optimization.py @@ -0,0 +1,128 @@ +"""Differential coverage for the 3.0.0 attribute parser's permissive grammar.""" + +import random +import re +from collections import OrderedDict +from io import StringIO + +import pytest + +from gtfparse import expand_attribute_strings, read_gtf + +# Freeze the pre-optimization tokenization independently of the captured regex. +LEGACY_PATTERN = re.compile(r"""[^\s;]+[ \t]+(?:"[^"]*"|'[^']*'|[^;]+)""") + + +def legacy_expand(rows, quote_char, missing_value, usecols): + columns = OrderedDict() + for i, row in enumerate(rows): + pairs = LEGACY_PATTERN.findall(row) if isinstance(row, str) else row or () + for pair in pairs: + parts = pair.strip().split(None, 1) + if len(parts) != 2: + continue + name, value = parts + if usecols is not None and name not in usecols: + continue + if len(value) >= 2 and value[0] in ('"', quote_char) and value[-1] == value[0]: + value = value[1:-1] + if name not in columns: + columns[name] = [missing_value] * len(rows) + previous = columns[name][i] + columns[name][i] = value if previous is missing_value else "%s,%s" % (previous, value) + return columns + + +@pytest.mark.parametrize("quote_char", ["'", '"', "~", ""]) +@pytest.mark.parametrize("missing_value", ["", None, "missing"]) +@pytest.mark.parametrize("usecols", [None, set(), {"a", "tag", "gene_id"}]) +def test_optimized_expansion_matches_legacy_grammar(quote_char, missing_value, usecols): + rows = [ + None, + "", + 'gene_id ""; gene_id "G1"; tag "a; b"; tag "";', + "a ' padded '; a '~custom~'; a ~custom~;", + 'a "unterminated; b value; a "close"trailing;', + "a ; b\t\t; a \u00a0 trimmed \r\n; malformed;", + "a \"é\n\t; quote'\"; a 'single \" quote';", + ["broken", 'a ""', 'a "next"', "gene_id\t'G1'", " a padded "], + [], + ] + rng = random.Random(85) + alphabet = "ab_ .;\t\n\r\"'~é\u00a0" + rows += ["".join(rng.choices(alphabet, k=rng.randrange(100))) for _ in range(500)] + expected = legacy_expand(rows, quote_char, missing_value, usecols) + actual = expand_attribute_strings( + rows, quote_char=quote_char, missing_value=missing_value, usecols=usecols + ) + assert isinstance(actual, OrderedDict) + assert list(actual) == list(expected) + assert actual == expected + + +def test_expanded_attribute_collisions_preserve_position_and_missing_values(): + text = ( + '1\ttest\tgene\t1\t10\t.\t+\t.\tgene_id "G1"; start "7"; note "a";\n' + '1\ttest\tgene\t11\t20\t.\t+\t.\tgene_id "G2"; note "b";\n' + ) + frame = read_gtf(StringIO(text)) + assert list(frame) == [ + "seqname", + "source", + "feature", + "start", + "end", + "score", + "strand", + "frame", + "gene_id", + "note", + ] + assert frame["start"].tolist() == ["7", ""] + assert frame["note"].tolist() == ["a", "b"] + + +@pytest.mark.parametrize("storage", ["python", "pyarrow"]) +def test_expanded_columns_follow_pandas_string_configuration(storage): + import pandas as pd + + text = ( + '1\ttest\tgene\t1\t10\t.\t+\t.\tgene_id "G1"; note "café; value";\n' + '1\ttest\tgene\t11\t20\t.\t+\t.\tgene_id "G2";\n' + ) + with pd.option_context("mode.string_storage", storage): + frame = read_gtf(StringIO(text)) + pd.testing.assert_series_equal(frame["gene_id"], pd.Series(["G1", "G2"], name="gene_id")) + pd.testing.assert_series_equal(frame["note"], pd.Series(["café; value", ""], name="note")) + assert pd.get_option("mode.string_storage") == storage + + +@pytest.mark.parametrize("storage", ["python", "pyarrow"]) +def test_batched_expansion_preserves_late_columns_gaps_collisions_and_progress( + storage, monkeypatch +): + import importlib + + import pandas as pd + + reader = importlib.import_module("gtfparse.read_gtf") + monkeypatch.setattr(reader, "_ATTRIBUTE_BATCH_SIZE", 10_000) + attrs = ['gene_id "G1"; tag "first"; tag "second";'] * 10_000 + attrs += ['gene_id "G2"; note "middle; value";'] * 10_000 + attrs += ['gene_id "G3"; start "42"; late "last";'] * 3 + text = "".join("1\ttest\tgene\t1\t100\t.\t+\t.\t%s\n" % a for a in attrs) + events = [] + with pd.option_context("mode.string_storage", storage): + frame = read_gtf(StringIO(text), progress_callback=lambda *event: events.append(event)) + assert list(frame)[-4:] == ["gene_id", "tag", "note", "late"] + assert list(frame).index("start") == 3 + assert frame["tag"].tolist() == ["first,second"] * 10_000 + [""] * 10_003 + assert frame["note"].tolist() == [""] * 10_000 + ["middle; value"] * 10_000 + [""] * 3 + assert frame["late"].tolist() == [""] * 20_000 + ["last"] * 3 + assert frame["start"].tolist() == [""] * 20_000 + ["42"] * 3 + assert [e for e in events if e[0] == "attributes"] == [ + ("attributes", 0, 20_003), + ("attributes", 10_000, 20_003), + ("attributes", 20_000, 20_003), + ("attributes", 20_003, 20_003), + ] From 22ca2df6d98743f5d92a0b6b3fc8a956105dd41a Mon Sep 17 00:00:00 2001 From: Alex Rubinsteyn Date: Tue, 6 Oct 2026 13:38:41 -0400 Subject: [PATCH 2/3] Reserve 3.0.2 for the independent optimization release --- benchmarks/README.md | 2 +- benchmarks/optimization-results.json | 8 +++++--- benchmarks/optimization.md | 13 +++++++++---- gtfparse/__init__.py | 2 +- tasks/lessons.md | 2 ++ tasks/todo.md | 10 +++++++--- 6 files changed, 25 insertions(+), 12 deletions(-) diff --git a/benchmarks/README.md b/benchmarks/README.md index 87711b7..5194e2a 100644 --- a/benchmarks/README.md +++ b/benchmarks/README.md @@ -4,7 +4,7 @@ The 3.0.0 migration uses PyArrow for fixed-column parsing and pandas for attribu processing and writing. Polars is an optional output adapter. This directory contains the measurement harness and the evidence for that decision. -The follow-up [3.0.1 optimization report](optimization.md) compares the optimized +The follow-up [3.0.2 optimization report](optimization.md) compares the optimized complete reader with both the 2.9.1 Polars and 3.0.0 Arrow/pandas releases. ## Reproduction diff --git a/benchmarks/optimization-results.json b/benchmarks/optimization-results.json index 2e04d7c..3a83831 100644 --- a/benchmarks/optimization-results.json +++ b/benchmarks/optimization-results.json @@ -1,10 +1,10 @@ { - "description": "Final 3.0.1 captured-pair parser and 250000-row batched Arrow attribute assembly; complete production pipelines.", + "description": "Captured-pair parser and 250000-row batched Arrow assembly measured as candidate 3.0.1; same runtime optimization ships independently as 3.0.2 to avoid the parallel documentation PR version.", "date": "2026-10-06", "baseline_sources": { "2.9.1-polars": "3e0912c", "3.0.0-arrow": "be449cbed70be8f515bb92b3eb2f43e55276917c", - "optimized": "perf/attribute-expansion PR against be449cb; version 3.0.1" + "optimized": "bd0cd44b145dc089968a77b4b6ca3bd614716ee2 (measured candidate 3.0.1); release 3.0.2 changes version numbering only" }, "method": { "threads": 4, @@ -7141,5 +7141,7 @@ "wall_seconds": 40.073447916001896 } } - } + }, + "release_version": "3.0.2", + "measured_optimization_version": "3.0.1" } diff --git a/benchmarks/optimization.md b/benchmarks/optimization.md index f4a4370..62c1951 100644 --- a/benchmarks/optimization.md +++ b/benchmarks/optimization.md @@ -1,9 +1,14 @@ -# Complete-load optimization in 3.0.1 +# Complete-load optimization in 3.0.2 -Version 3.0.1 retains the pandas default and optional Polars output introduced +Version 3.0.2 retains the pandas default and optional Polars output introduced in 3.0.0. It improves the shared Python attribute parser and the construction of expanded pandas columns while keeping the supported reader behavior. +The benchmark candidate was labeled 3.0.1 when measured. The concurrent +documentation PR targets that version, so this independent optimization +ships as 3.0.2. Raw records retain their measured version labels; +result tables refer to the release containing that implementation. + ## Changes - Capture attribute names and double-quoted values directly in the compiled @@ -79,7 +84,7 @@ pandas versions. Times and memory are fresh measurements from this sweep; compare readers within this table rather than mixing earlier timings from a shared workstation. -| pandas | Input (250k rows) | 2.9.1 Polars s | 3.0.0 Arrow s | 3.0.1 s | Polars MiB | 3.0.0 MiB | 3.0.1 MiB | +| pandas | Input (250k rows) | 2.9.1 Polars s | 3.0.0 Arrow s | 3.0.2 s | Polars MiB | 3.0.0 MiB | 3.0.2 MiB | | --- | --- | ---: | ---: | ---: | ---: | ---: | ---: | | 2.3.3 | ensembl-250k.gtf | 2.57 | 2.91 | 2.29 | 560 | 617 | 583 | | 2.3.3 | ensembl-250k.gtf.gz | 2.86 | 4.58 | 2.36 | 561 | 620 | 584 | @@ -110,7 +115,7 @@ one fresh process per reader. All six complete loads match content and column order. These single observations demonstrate scaling and correctness, and do not establish repeated full-file throughput. -| Full gzip input | Rows | Polars s | 3.0.0 s | 3.0.1 s | Polars MiB | 3.0.0 MiB | 3.0.1 MiB | +| Full gzip input | Rows | Polars s | 3.0.0 s | 3.0.2 s | Polars MiB | 3.0.0 MiB | 3.0.2 MiB | | --- | ---: | ---: | ---: | ---: | ---: | ---: | ---: | | Ensembl GRCh38.114 | 4,116,048 | 47.11 | 67.63 | 36.86 | 6504 | 7199 | 3639 | | GENCODE v48 primary | 4,119,244 | 43.74 | 52.35 | 29.88 | 7091 | 6560 | 3698 | diff --git a/gtfparse/__init__.py b/gtfparse/__init__.py index 20c94a5..d5c1712 100644 --- a/gtfparse/__init__.py +++ b/gtfparse/__init__.py @@ -24,7 +24,7 @@ ) from .write_gtf import write_gtf -__version__ = "3.0.0" +__version__ = "3.0.2" __all__ = [ "GENCODE_BIOTYPE_ALIASES", diff --git a/tasks/lessons.md b/tasks/lessons.md index edde6e1..39602b9 100644 --- a/tasks/lessons.md +++ b/tasks/lessons.md @@ -7,3 +7,5 @@ - When asked to close an unreproduced historical report, record the evidence and close it as unreproduced rather than leaving it open indefinitely or implying that an unverified fix shipped. +- When asked to finish a PR, prioritize its remaining checks, merge and + publication before further experiments or follow-up work. diff --git a/tasks/todo.md b/tasks/todo.md index f5622e8..9b230ff 100644 --- a/tasks/todo.md +++ b/tasks/todo.md @@ -386,7 +386,7 @@ artifact verification will be recorded on the PR to keep clean master clean. The user requested a PR to improve the pandas/Arrow implementation and attempt repeatable complete-load performance better than the old Polars implementation, -without narrowing supported inputs or API behavior. Version this as 3.0.1. +without narrowing supported inputs or API behavior. Version this as 3.0.2. Preserve all expanded/raw GTF semantics, fixed numeric/categorical and inferred string dtypes, arbitrary/repeated/quoted attributes, column collisions/order, @@ -477,11 +477,15 @@ MiB and 3.0.0 52.35 s/6560 MiB. These are single observations per reader on the shared workstation, distinct from the repeated subset medians. Final selective exon/five-column and optional Polars-output checks also match all three releases. 84 final records and separately labeled development evidence are retained in -benchmarks/optimization-results.json. Version is bumped to 3.0.1. +benchmarks/optimization-results.json. Version is bumped to 3.0.2. Packaging review: wheel and source distribution build successfully, have identical -3.0.1 dependency metadata, and pass strict Twine checks. The wheel excludes tests +3.0.2 dependency metadata, and pass strict Twine checks. The wheel excludes tests and benchmarks; the source archive includes the new regression tests, runner and retained evidence. Its shipped ./lint.sh and ./test.sh pass (199 plus 10 optional skips, 96% coverage). Production code, test oracle and benchmark method reviewed; release/checklist completion will be recorded on the PR after merge and PyPI. + +Release sequencing: documentation PR #93 targets 3.0.1. Keep this PR +independent of that unmerged work and ship 3.0.2. Benchmark records retain measured candidate version 3.0.1; runtime +parsing and assembly behavior is unchanged by version numbering. From 7fb46e7ed7cc7b0eab9d72cd09514c5a8224abd7 Mon Sep 17 00:00:00 2001 From: Alex Rubinsteyn Date: Tue, 6 Oct 2026 13:47:23 -0400 Subject: [PATCH 3/3] Exercise opt-in Arrow string batches on pandas 2 --- benchmarks/optimization.md | 4 +++- tasks/todo.md | 9 ++++++++- tests/test_attribute_optimization.py | 4 +++- 3 files changed, 14 insertions(+), 3 deletions(-) diff --git a/benchmarks/optimization.md b/benchmarks/optimization.md index 62c1951..c7f250d 100644 --- a/benchmarks/optimization.md +++ b/benchmarks/optimization.md @@ -142,7 +142,9 @@ quoted/unquoted, custom quote delimiters, Unicode/whitespace, malformed fragment repeated/empty values, pre-split rows, missing-value sentinels and column selection. Additional tests check configured Python/Arrow string storage, batch boundaries, late-discovered columns, missing batches, fixed-field attribute -collisions, first-seen order and global progress counts. Existing tests cover streams, null fields, exact +collisions, first-seen order and global progress counts. The batch regression +opts pandas 2 into inferred strings so both configured storage backends are +exercised there; default object-string behavior has separate coverage. Existing tests cover streams, null fields, exact integer coordinates, comments/BOM, aliases, converters, progress/cancellation, optional Polars, dictionary output and writer round trips. diff --git a/tasks/todo.md b/tasks/todo.md index 9b230ff..2ab82ed 100644 --- a/tasks/todo.md +++ b/tasks/todo.md @@ -464,7 +464,7 @@ Final release status will be recorded on the PR so clean master remains clean for ./deploy.sh. Final validation: ./lint.sh passes. Normal ./test.sh passes 213 tests with -90% coverage. Base pandas 3.0.6/Arrow 25 and pandas 3.0.6/Arrow 18 pass 199 tests +97% coverage. Base pandas 3.0.6/Arrow 25 and pandas 3.0.6/Arrow 18 pass 199 tests plus 10 optional skips (96% coverage). Minimum Python 3.9/pandas 2.2.2/Arrow 18 passes 199 plus 10 skips (88%; configured object strings omit the Arrow branch). Minimum optional Polars 0.20.31 passes 212 plus one modern-only skip (97%, existing @@ -489,3 +489,10 @@ release/checklist completion will be recorded on the PR after merge and PyPI. Release sequencing: documentation PR #93 targets 3.0.1. Keep this PR independent of that unmerged work and ship 3.0.2. Benchmark records retain measured candidate version 3.0.1; runtime parsing and assembly behavior is unchanged by version numbering. + +Coverage review: the pandas 2.3 flag initially reported a drop because its +default object strings omitted the Arrow batch branch. Opt the batch regression +into inferred strings, exercising configured Python/Arrow backends on pandas 2 +as well as pandas 3. Normal tests now pass 213 with 97% coverage; recent pandas +with minimum Arrow 18 passes 199 plus 10 optional skips (96%). Runtime code and +all retained benchmarks are unchanged. diff --git a/tests/test_attribute_optimization.py b/tests/test_attribute_optimization.py index 234c53e..10b3312 100644 --- a/tests/test_attribute_optimization.py +++ b/tests/test_attribute_optimization.py @@ -112,7 +112,9 @@ def test_batched_expansion_preserves_late_columns_gaps_collisions_and_progress( attrs += ['gene_id "G3"; start "42"; late "last";'] * 3 text = "".join("1\ttest\tgene\t1\t100\t.\t+\t.\t%s\n" % a for a in attrs) events = [] - with pd.option_context("mode.string_storage", storage): + # pandas 2 requires opting into inferred strings to exercise both storage + # backends; pandas 3 infers strings by default. + with pd.option_context("mode.string_storage", storage, "future.infer_string", True): frame = read_gtf(StringIO(text), progress_callback=lambda *event: events.append(event)) assert list(frame)[-4:] == ["gene_id", "tag", "note", "late"] assert list(frame).index("start") == 3