csvlite vs Polars · measured 29 September 2026
Faster than Polars.
Without writing Polars.
Same files, same laptop, CSV to answer. Median of 5 runs.
typical2.2× fastermedian of 35 measured queries
best case5.6× fasterDate range, 1 GB
1 GB2.0–5.6×faster on every query
10 GB · 9 queries9 of 9answered in 8 GB; Polars ran out of memory on 1
Every query
10 MB
53,596 rows · 15 columns · File in page cache
| Query | csvlite | Polars | Bars | vs Polars |
|---|---|---|---|---|
| Text matchregion = north | 10 ms | 19 ms | 1.9× faster | |
| Regex searchdescription has the word café | 14 ms | 21 ms | 1.4× faster | |
| Number rangeamount 25,000–75,000 | 10 ms | 18 ms | 1.9× faster | |
| Date rangeoccurred_at in a range | 10 ms | 21 ms | 2.2× faster | |
| Sort textevery row by region | 10 ms | 21 ms | 2.2× faster | |
| Sort numbersevery row by amount | 10 ms | 20 ms | 2.0× faster | |
| Sort datesevery row by occurred_at | 12 ms | 23 ms | 1.9× faster | |
| Group + sumcount, sum(amount) by region, status | 12 ms | 20 ms | 1.7× faster | |
| Group + distinct…plus distinct descriptions | 12 ms | 22 ms | 1.8× faster |
Chart data
| After | csvlite | Polars | Polars, read_csv first |
|---|---|---|---|
| Open | 10 ms | 0.0 ms | 7.8 ms |
| Text match | 12 ms | 19 ms | 9.4 ms |
| Regex search | 18 ms | 39 ms | 13 ms |
| Number range | 20 ms | 57 ms | 16 ms |
| Date range | 23 ms | 78 ms | 22 ms |
| Sort text | 25 ms | 99 ms | 25 ms |
| Sort numbers | 27 ms | 119 ms | 28 ms |
| Sort dates | 30 ms | 142 ms | 34 ms |
| Group + sum | 34 ms | 162 ms | 39 ms |
| Group + distinct | 40 ms | 184 ms | 44 ms |
100 MB
532,923 rows · 15 columns · File in page cache
| Query | csvlite | Polars | Bars | vs Polars |
|---|---|---|---|---|
| Text matchregion = north | 15 ms | 64 ms | 4.4× faster | |
| Regex searchdescription has the word café | 32 ms | 88 ms | 2.7× faster | |
| Number rangeamount 25,000–75,000 | 21 ms | 79 ms | 3.8× faster | |
| Date rangeoccurred_at in a range | 19 ms | 90 ms | 4.7× faster | |
| Sort textevery row by region | 29 ms | 80 ms | 2.7× faster | |
| Sort numbersevery row by amount | 26 ms | 76 ms | 2.9× faster | |
| Sort datesevery row by occurred_at | 27 ms | 90 ms | 3.4× faster | |
| Group + sumcount, sum(amount) by region, status | 29 ms | 86 ms | 3.0× faster | |
| Group + distinct…plus distinct descriptions | 39 ms | 95 ms | 2.5× faster |
Chart data
| After | csvlite | Polars | Polars, read_csv first |
|---|---|---|---|
| Open | 11 ms | 0.0 ms | 34 ms |
| Text match | 14 ms | 64 ms | 37 ms |
| Regex search | 35 ms | 152 ms | 62 ms |
| Number range | 45 ms | 230 ms | 75 ms |
| Date range | 53 ms | 320 ms | 104 ms |
| Sort text | 69 ms | 400 ms | 121 ms |
| Sort numbers | 83 ms | 475 ms | 140 ms |
| Sort dates | 97 ms | 565 ms | 172 ms |
| Group + sum | 114 ms | 651 ms | 204 ms |
| Group + distinct | 140 ms | 746 ms | 236 ms |
1 GB
5,300,205 rows · 15 columns · File in page cache
| Query | csvlite | Polars | Bars | vs Polars |
|---|---|---|---|---|
| Text matchregion = north | 90 ms | 376 ms | 4.2× faster | |
| Regex searchdescription has the word café | 264 ms | 613 ms | 2.3× faster | |
| Number rangeamount 25,000–75,000 | 172 ms | 473 ms | 2.7× faster | |
| Date rangeoccurred_at in a range | 139 ms | 779 ms | 5.6× faster | |
| Sort textevery row by region | 226 ms | 535 ms | 2.4× faster | |
| Sort numbersevery row by amount | 197 ms | 551 ms | 2.8× faster | |
| Sort datesevery row by occurred_at | 191 ms | 766 ms | 4.0× faster | |
| Group + sumcount, sum(amount) by region, status | 236 ms | 620 ms | 2.6× faster | |
| Group + distinct…plus distinct descriptions | 362 ms | 716 ms | 2.0× faster |
Chart data
| After | csvlite | Polars | Polars, read_csv first |
|---|---|---|---|
| Open | 69 ms | 0.0 ms | 372 ms |
| Text match | 99 ms | 376 ms | 389 ms |
| Regex search | 303 ms | 989 ms | 656 ms |
| Number range | 413 ms | 1.5 s | 775 ms |
| Date range | 491 ms | 2.2 s | 1.2 s |
| Sort text | 654 ms | 2.8 s | 1.4 s |
| Sort numbers | 791 ms | 3.3 s | 1.6 s |
| Sort dates | 920 ms | 4.1 s | 2.1 s |
| Group + sum | 1.1 s | 4.7 s | 2.4 s |
| Group + distinct | 1.4 s | 5.4 s | 2.7 s |
10 GB
53,002,050 rows · 15 columns · Cold cache: evicted from memory before every run
| Query | csvlite | Polars | Bars | vs Polars |
|---|---|---|---|---|
| Text matchregion = north | 4.6 s | 7.6 s | 1.6× faster | |
| Regex searchdescription has the word café | 6.2 s | 10 s | 1.7× faster | |
| Number rangeamount 25,000–75,000 | 5.3 s | 8.6 s | 1.6× faster | |
| Date rangeoccurred_at in a range | 5.0 s | 8.7 s | 1.7× faster | |
| Sort textevery row by region | 9.1 s | 9.9 s | on par | |
| Sort numbersevery row by amount | 6.4 s | 9.7 s | 1.5× faster | |
| Sort datesevery row by occurred_at | 6.3 s | 9.1 s | 1.4× faster | |
| Group + sumcount, sum(amount) by region, status | 5.7 s | 11 sout of memory in 1 of 5 runs | 1.9× faster | |
| Group + distinct…plus distinct descriptions | 7.2 s | out of memory | only csvlite |
Chart data
| After | csvlite | Polars | Polars, read_csv first |
|---|---|---|---|
| Open | 3.1 s | — | — |
| Text match | 4.7 s | — | — |
| Regex search | 7.8 s | — | — |
| Number range | 9.9 s | — | — |
| Date range | 12 s | — | — |
| Sort text | 18 s | — | — |
| Sort numbers | 21 s | — | — |
| Sort dates | 24 s | — | — |
| Group + sum | 27 s | — | — |
| Group + distinct | 31 s | — | — |
The code you’d write
As benchmarked
Text matchcsvlite 90 msPolars 376 msat 1 GB
(pl.scan_csv("data.csv", infer_schema=False,
empty_string_is_null=False)
.select((pl.col("region") == "north").sum())
.collect())csvliteAdd filter · region = north
Sort numberscsvlite 197 msPolars 551 msat 1 GB
(pl.scan_csv("data.csv", infer_schema=False,
empty_string_is_null=False)
.select(pl.col("amount").cast(pl.Float64, strict=False)
.arg_sort(nulls_last=True))
.collect())csvliteClick the amount header
Group + sumcsvlite 236 msPolars 620 msat 1 GB
(pl.scan_csv("data.csv", infer_schema=False,
empty_string_is_null=False)
.group_by("region", "status")
.agg(pl.len(),
pl.col("amount").cast(pl.Float64, strict=False).sum())
.collect())csvlitePivot · region, status · Sum of amount
- Machine
- Intel Core i7-11850H · 32 GB RAM · NVMe SSD · Linux. Every run capped at 8 GB of memory.
- Versions
- csvlite 1.0.0 · DuckDB 1.5.5 · Polars 1.44.2 · pandas 3.0.6. All columns read as text.
- Timing
- CSV to answer, fresh process per run, startup excluded. ≤1 GB warm; 10 GB cold. Out of memory: one capped attempt. Polars, read_csv first: the same queries after loading the CSV into Polars, a separate five-run cohort.
- Data
- Generated analytics CSV. All 1064 raw runs (plus load-first) · csvlite-only benchmarks
All four tools · vs pandas · vs DuckDB