diff --git a/benchmarks/README.md b/benchmarks/README.md index 06379db..5194e2a 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.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 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..3a83831 --- /dev/null +++ b/benchmarks/optimization-results.json @@ -0,0 +1,7147 @@ +{ + "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": "bd0cd44b145dc089968a77b4b6ca3bd614716ee2 (measured candidate 3.0.1); release 3.0.2 changes version numbering only" + }, + "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 + } + } + }, + "release_version": "3.0.2", + "measured_optimization_version": "3.0.1" +} diff --git a/benchmarks/optimization.md b/benchmarks/optimization.md new file mode 100644 index 0000000..c7f250d --- /dev/null +++ b/benchmarks/optimization.md @@ -0,0 +1,154 @@ +# Complete-load optimization in 3.0.2 + +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 + 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.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 | +| 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.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 | + +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. 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. + +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/__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/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/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 33a153d..2ab82ed 100644 --- a/tasks/todo.md +++ b/tasks/todo.md @@ -379,3 +379,120 @@ 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.2. + +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 +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 +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.2. + +Packaging review: wheel and source distribution build successfully, have identical +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. + +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 new file mode 100644 index 0000000..10b3312 --- /dev/null +++ b/tests/test_attribute_optimization.py @@ -0,0 +1,130 @@ +"""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 = [] + # 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 + 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), + ]