Processing Large CSV Files in WebAssembly with Pascal
08-09-2026
In our previous post, Processing CSV Files in WebAssembly with Pascal, we explored the fundamentals of WebAssembly I/O: using shared linear memory to feed raw CSV bytes into a Pascal binary, parsing rows into an array of records, sorting by age, and streaming back a downloadable result.
That walkthrough used a conservative 64 KB buffer with 512 records. It worked great as a demonstration.
But what happens when you want to upload a 10 MB names.csv file containing
around 300 000 records?
If you run a 10 MB payload through that basic approach, the browser will freeze or crash. In this article, we explore how to scale Pascal WebAssembly to handle a large CSV file with unknown row counts, how to allocate and map 128 MB of linear memory, why zero-copy indexing is helpful, and how to run an in-place Quicksort in WebAssembly in seconds.
Table of Contents
- Why the 64 KB Approach Breaks at 10 MB
- Configuring 128 MB of WebAssembly Linear Memory
- Zero-Copy Indexing: The 12-Byte Record
- Handling Unknown Row Counts Efficiently
- In-Place Quicksort in Pascal (O(N log N))
- Zero-Copy JavaScript Bridge to Blob
- Interactive Live Demo (Expecting names.csv)
- The 1,000 Sample Names Dataset
- Full Pascal Source (namesort.pas)
- Full HTML & JavaScript Host (index.html)
Why the 64 KB Approach Breaks at 10 MB
When scaling from a toy example to a 10 MB file, four major bottlenecks appear simultaneously:
| Bottleneck | 64 KB Demo Approach | Failure Mode at 10 MB | Large File Architecture |
|---|---|---|---|
| Buffer Bounds | Fixed 64 KB static array | Immediate buffer overflow / truncation | 16 MB input & output linear buffers |
| Record Structs | name: String[64] (65 bytes each) |
300k rows = 20 MB just for struct copies | 12-byte TIndexRecord pointing into input |
| Sorting Algorithm | Insertion sort (O(N²)) | ~45,000,000,000 operations (browser tab hangs) | In-place Quicksort (O(N log N)) (<1s) |
| JS Data Handoff | TextDecoder.decode() to JS string |
Spikes V8 heap by 30 MB+ with GC pauses | Direct Uint8Array view passed into Blob |
Configuring 128 MB of WebAssembly Linear Memory
WebAssembly linear memory is allocated in pages of exactly 64 KB (65,536 bytes). To provide 128 MB of linear memory:
128 MB = 128 × 1024 KB ÷ 64 KB/page = 2,048 pages
By default, WasmPascal allocates a conservative 16 MB (256 pages) of module-exported linear memory.
Because our buffers require ~38 MB of static space, we tell WasmPascal to allocate 128 MB directly via
the {$M 128M} compiler directive at the top of our Pascal library:
{$M 128M} { Configures 2,048 pages (128 MB) of linear memory in WasmPascal }
Inside the Pascal module, we reserve three clean zones in the linear address space:
inputBuffer(16 MB): Holds the raw bytes of the uploadednames.csvfile.recordsTable (6 MB): Stores up to 500,000 compact 12-byte index descriptors.outputBuffer(16 MB): Receives the formatted, sorted CSV lines.
This entire layout consumes approximately 38 MB of static linear space, leaving over 90 MB of headroom for stack operations and scratch calculations within our 128 MB ceiling. Of course, for larger files, we could allocate more memory. In future article, I'll show how to dynamically grow memory as well. This pre-allocated approach though, works quite well for scenarios where you know a fair bit about the payload, as is the case in a lot of ETL workflows.
Zero-Copy Indexing: The 12-Byte Record
In standard Pascal, declaring a record like:
type
TPerson = record
name: String[64]; { 65 bytes: 1 length byte + 64 characters }
age: Integer; { 4 bytes }
end;
means that for every row in a 300,000-line CSV, your code must copy up to 64 bytes into a private record array. That produces over 20 megabytes of copied strings and millions of unnecessary memory writes.
Instead, we employ zero-copy slice indexing. The raw bytes already sit in
inputBuffer.
JavaScript has already done the hard work of reading all the data into memory, so why duplicate the
effort? We only
need to know where each name starts, how long it is, and its parsed integer age:
type
TIndexRecord = record
nameOffset: Integer; { byte offset in inputBuffer (4 bytes) }
nameLen: Integer; { length of the name slice (4 bytes) }
age: Integer; { parsed integer age (4 bytes) }
end;
Notice how compact this is: exactly 12 bytes per record! For 300,000 rows, our entire record index is only 3.6 MB. Scanning a row simply records the offset and length without copying anything.
Handling Unknown Row Counts Efficiently
When a user supplies an arbitrary names.csv, we don't know upfront whether it contains 50
rows,
1,000 rows, or 350,000 rows.
Because WebAssembly operates directly on flat memory, we have two straightforward strategies:
-
The Two-Pass Scan: A pre-scan loop counts the newline characters (
#10) ininputBuffer. In Pascal, scanning a 10 MB buffer for byte10if really fast. This gives us the exact row count before filling any data structures. -
Single-Pass Bounded Ingestion: We reserve capacity for
MAX_RECORDS = 500000. As we parse lines, we incrementrecordCount. If the file ends before the limit, we sort up torecordCount - 1.
In-Place Quicksort in Pascal (O(N log N))
Insertion sort is great for 512 items, but on 300,000 records it is disastrous:
Insertion Sort ops ≈ N² / 2 = (300,000)² / 2 ≈ 45,000,000,000 ops
An in-place Quicksort reduces this to:
Quicksort ops ≈ N × log&sub2;(N) ≈ 300,000 × 18.2 ≈ 5,460,000 ops
Because our records are only 12 bytes each, swapping them during partitioning involves copying three 32-bit integers. In WebAssembly, Quicksort across 300,000 records takes under 1 second on most machines:
procedure QuickSort(left, right: Integer);
var
i, j, pivot: Integer;
temp: TIndexRecord;
begin
i := left;
j := right;
pivot := records[(left + right) div 2].age;
repeat
while records[i].age < pivot do i := i + 1;
while records[j].age > pivot do j := j - 1;
if i <= j then
begin
temp := records[i];
records[i] := records[j];
records[j] := temp;
i := i + 1;
j := j - 1;
end;
until i > j;
if left < j then QuickSort(left, j);
if i < right then QuickSort(i, right);
end;
Zero-Copy JavaScript Bridge to Blob
Another common pitfall in web applications is converting large WebAssembly memory buffers into
JavaScript strings
via TextDecoder.decode() before downloading.
Decoding a 10 MB CSV string creates a huge intermediate string in the V8 heap, causing memory pressure
and garbage collection pauses.
Instead, we create a direct Uint8Array view over the output buffer in WebAssembly linear
memory,
and then pass that view straight into the browser's Blob constructor:
// 1. Direct copy of uploaded file into WASM memory
const fileData = await file.arrayBuffer();
const inputBytes = new Uint8Array(fileData);
const wasmMem = new Uint8Array(instance.exports.memory.buffer);
const inPtr = instance.exports.GetInputBuffer();
wasmMem.set(inputBytes, inPtr);
// 2. Run Pascal processing
const count = instance.exports.ProcessCSV(inputBytes.length);
// 3. Directly wrap WASM memory view into a Blob
const outPtr = instance.exports.GetOutputBuffer();
const outLen = instance.exports.GetOutputLength();
const outputView = new Uint8Array(instance.exports.memory.buffer, outPtr, outLen);
const blob = new Blob([outputView], { type: 'text/csv;charset=utf-8;' });
const downloadUrl = URL.createObjectURL(blob);
Interactive Live Demo (Expecting names.csv)
Try the interactive demo below. You can drag and drop a names.csv file, click to load our
bundled
1,000-name sample dataset, or even generate a massive 250,000-row (10 MB)
dataset
directly in your browser to benchmark the speed! Just bear in mind generating this dataset takes a
second or three...
The 1,000 Sample Names Dataset
To help you test this pipeline immediately, here is a complete dataset of 1,000 sample names and ages
formatted
specifically for names.csv. You can download the file with one click or view the raw
records below:
Click to expand/inspect the 1,000-record names.csv sample
names.csv (1,000 records):
Name,Age
Emma Morgan,64
Brenda Perez,60
Deborah Campbell,57
Ronald Clark,64
Susan Diaz,69
William Cook,62
Stephanie Phillips,57
Gregory Williams,63
Scott Thomas,76
Ashley Perez,58
Frank Collins,51
Betty Rodriguez,85
Emma Garcia,27
Timothy Miller,20
Samantha Sanchez,43
Susan Torres,43
Laura Green,19
Brandon Nelson,73
Brenda Robinson,23
Maria Flores,45
Brandon White,85
Angela Ortiz,41
Maria Miller,81
Raymond Collins,21
Eric Morales,63
Jack Allen,51
William Taylor,25
Nancy Green,28
Matthew Cruz,50
Michael Martin,72
Brian Garcia,73
Andrew Martin,25
Samantha Reyes,62
Edward Rodriguez,44
Amanda King,45
Matthew Moore,79
Ronald Diaz,50
Christopher Lewis,60
Ronald Harris,71
Christopher Stewart,59
Jennifer Brown,42
Samuel Parker,57
Ruth Cooper,58
Maria Phillips,63
Mark Flores,74
Justin Carter,66
Charles Scott,48
Deborah Hernandez,76
Alexander Smith,61
David Scott,80
Angela Roberts,35
Robert Cook,66
Betty Cruz,32
Christine Young,56
Michael Morales,45
Amanda Morgan,60
Emily Wilson,37
Nicholas Garcia,81
Donna Williams,37
Charles Reyes,28
Katherine Morales,76
Jack Williams,40
Matthew Lee,48
Dennis Lewis,23
Raymond Cruz,77
Catherine Phillips,57
Dennis Green,21
Alexander Diaz,63
Benjamin Wilson,39
David Johnson,56
Benjamin Harris,38
Debra Sanchez,31
David Lee,69
Brenda Young,25
Sharon Robinson,71
Kevin Reyes,78
Janet Harris,27
Elizabeth Rodriguez,35
George Wright,66
Patricia Smith,49
Linda Cooper,32
Katherine Gomez,53
Eric Torres,37
Alexander Smith,71
Joshua Morales,65
Robert Adams,19
Dennis Davis,29
Ruth Miller,65
Sharon Turner,68
Jacob Thompson,19
Amy White,42
Elizabeth Diaz,42
Barbara Gutierrez,38
Rebecca Lewis,28
Mark Cook,41
Sharon Williams,72
Eric Cooper,57
Susan Adams,54
Michael Morales,64
Dorothy Brown,64
Justin Nelson,45
Susan Morgan,21
Rachel Davis,69
Alexander Ortiz,68
Robert Phillips,18
Samuel Garcia,73
Patrick Collins,28
Dorothy Ortiz,75
Anna Rogers,45
Barbara Collins,64
Janet Mitchell,22
Charles Jackson,31
Sandra Evans,38
Sarah Sanchez,51
Deborah Morris,61
William Mitchell,45
Christopher Stewart,52
Helen Hernandez,53
Kathleen Allen,37
Carolyn Wilson,44
Charles Lee,37
Jennifer Smith,25
Donald Rivera,33
Michelle Sanchez,26
Carolyn Rogers,72
Emma Ortiz,66
Carolyn Phillips,29
Betty White,64
Catherine Ramirez,85
Gregory Davis,49
Richard Nguyen,58
Andrew Adams,55
Jennifer Allen,71
Dorothy Baker,29
Samuel Cooper,52
Jonathan Scott,22
Dorothy Miller,35
Jason Murphy,81
Samuel Baker,39
Scott Carter,84
Gregory Williams,74
Elizabeth Harris,67
Jack Flores,44
Angela Morales,70
Larry Edwards,34
Ronald Carter,67
Daniel Martinez,51
Kevin Taylor,50
Samuel Wright,85
Steven Wilson,30
Emma White,34
Brian Evans,34
Shirley Thomas,37
Nicholas Roberts,62
Christine Parker,20
Maria Hill,29
Deborah Roberts,83
Ryan Brown,31
Linda Walker,37
Sandra Rodriguez,21
Jack Davis,23
Justin Gutierrez,21
Brenda Green,37
Brandon Baker,49
Joshua Hill,61
Michelle Gomez,61
Catherine Thompson,22
Jonathan Gomez,30
Sharon Diaz,69
Sandra Edwards,27
Sandra Smith,84
Lisa Phillips,52
Dennis Baker,50
Laura Thompson,26
James Morgan,51
Kenneth Cruz,21
Samantha Torres,46
Angela Morris,68
Joseph Hall,24
Jerry Johnson,47
Nicholas King,76
Andrew Cruz,41
Eric Brown,58
Frank Reyes,69
Scott Jones,48
Benjamin Morris,41
Kathleen Scott,56
Brenda Lee,78
Jonathan Flores,68
Helen Reyes,85
Rebecca Parker,22
Charles Baker,31
Brandon Roberts,61
Susan Young,47
Melissa King,39
Benjamin Cruz,46
Kevin Wilson,81
Michelle Rodriguez,22
Anna Anderson,45
Alexander Robinson,42
Nicholas Parker,70
Debra Gonzalez,22
John Moore,47
Larry Johnson,63
Anna Morales,84
Emma Miller,43
William Gutierrez,59
Nicholas Taylor,61
Jonathan Morgan,52
Kenneth Cooper,76
Steven Wilson,74
Andrew Anderson,23
Robert Sanchez,53
Jack Scott,28
Christine Taylor,47
Karen Perez,30
Angela Moore,64
Patrick Wright,27
Nancy Wright,84
Timothy Allen,72
Patricia Parker,42
Emily Murphy,57
Alexander King,66
Jessica Ortiz,50
Lisa Green,82
Angela Nelson,81
Ryan Taylor,73
Janet Scott,74
Frank Taylor,83
Andrew Mitchell,24
Samantha Green,80
Dennis Martinez,52
Stephen Jackson,57
Joshua Perez,52
Edward White,60
Donald Hall,59
Jonathan Johnson,65
Laura Robinson,85
Kevin Morris,70
Sandra Taylor,47
Amanda Allen,44
Charles Hill,79
Gregory Phillips,24
Steven Nguyen,59
Patricia Perez,84
Kenneth Thomas,59
Catherine Miller,37
Barbara Rogers,44
Amy Harris,65
Timothy Perez,47
Margaret Young,20
Brenda Morgan,62
Lisa Morales,60
Joseph Flores,32
Brenda Torres,68
Robert Collins,53
Kathleen Turner,58
Joshua Lewis,34
Jacob Hill,72
Eric Williams,75
Carol Evans,66
Brian Stewart,26
Amy King,30
Jacob Baker,83
Brian Miller,46
Laura Turner,31
Angela Gonzalez,28
Jessica Ramirez,78
Jerry Gomez,75
Dorothy Young,59
Andrew Lopez,58
Kathleen Lewis,21
James Taylor,30
Amanda Sanchez,52
Eric Rivera,51
Shirley Phillips,36
Stephen Thompson,51
Mary Robinson,72
Jonathan Flores,20
Jack Lopez,81
Sharon Young,62
Stephen Evans,60
Sandra Adams,43
Elizabeth White,47
Dorothy Cooper,32
Jonathan Gonzalez,70
Gregory Lopez,34
Christopher Green,22
Betty Young,70
Jack Ramirez,67
Joseph Young,46
Mark Green,64
Joshua Walker,78
Dorothy Lopez,22
William Evans,74
David Brown,83
Jerry Anderson,64
Carolyn Perez,75
Anna Collins,70
Raymond Scott,19
Christine Smith,45
Kenneth Robinson,61
Raymond Brown,79
Sarah Lewis,50
David Jackson,56
Charles Parker,51
Timothy Murphy,63
Patricia Lopez,34
Mark Johnson,49
Edward Jones,47
Alexander Lee,51
Stephen Perez,49
Emily Murphy,45
Jonathan Miller,52
Kenneth Morris,78
Patricia Phillips,74
Dennis Green,30
Kimberly Torres,27
Elizabeth Torres,75
Paul Scott,23
Deborah Clark,85
Matthew Sanchez,22
Alexander Anderson,49
Benjamin Morgan,51
Kimberly Allen,60
Daniel Sanchez,74
Stephen Morales,35
David Jackson,31
Richard Parker,77
Michael Morgan,69
Elizabeth Mitchell,82
James Diaz,25
Deborah Davis,67
Mark Diaz,59
Katherine Gutierrez,51
Jonathan Allen,58
Matthew Reyes,23
Daniel Rogers,36
Dorothy Cruz,46
Robert Martinez,33
Pamela Jones,40
Jack Moore,66
Carol Hall,83
Joseph Robinson,75
Dennis Parker,72
Jack Flores,66
Lisa Walker,61
Scott Jackson,65
Paul Ramirez,56
Betty Baker,35
Samuel Green,76
Sharon Rodriguez,82
Ruth Walker,44
Katherine Scott,41
Stephanie Scott,45
George Lewis,34
Timothy Ramirez,71
Jerry Rodriguez,73
Anthony Cruz,38
Ryan Davis,18
John Cruz,52
Katherine Parker,34
Paul Walker,41
Pamela Baker,34
Raymond Gutierrez,58
Jack Nguyen,54
Amy Mitchell,63
Kimberly Brown,52
Frank Hall,82
Emily Morales,35
Brandon Ramirez,67
Charles Moore,26
Katherine Walker,31
Donald Green,60
Jason Rivera,39
Scott Clark,57
Mary Hill,63
Kimberly Stewart,22
Amanda Lewis,26
Pamela White,50
Andrew Martin,48
Debra Allen,55
Margaret Lopez,28
Michelle Miller,42
Alexander Parker,31
Janet Gomez,23
Shirley Roberts,34
Ryan Jones,40
Debra Garcia,48
Amanda Lee,45
Patricia Edwards,55
Thomas Cooper,85
Angela Lee,70
Paul Nelson,32
Kathleen White,78
Nicholas Thompson,85
Rachel Jackson,62
Dorothy Campbell,20
Emily Rodriguez,56
Rebecca Lopez,30
Betty Hernandez,72
Dorothy Hernandez,58
Stephen Cook,44
Ryan Wilson,74
Shirley Phillips,60
Daniel Phillips,46
Raymond Rodriguez,23
Kathleen Smith,40
Jennifer Allen,34
Matthew Garcia,18
Amy Torres,61
Benjamin Cooper,42
Charles White,35
John Wilson,48
Christopher Wilson,83
Brandon Morales,29
Sandra Young,38
Rebecca Rodriguez,66
Deborah Sanchez,42
Charles Green,18
Brenda White,64
Matthew Scott,67
Christopher Turner,84
Rebecca Phillips,31
Patricia Scott,55
Stephen Gonzalez,34
Jack Morris,71
Benjamin Hill,59
Thomas Gonzalez,21
Elizabeth Roberts,43
Richard Lopez,25
Justin Nguyen,44
Angela Murphy,53
Matthew Gonzalez,21
Ashley Taylor,65
William Gonzalez,74
John Murphy,19
Brian King,60
Raymond King,34
Nancy Carter,23
Elizabeth Cruz,38
Steven Hill,38
Benjamin White,32
Donna Cook,29
Michelle Perez,51
Jonathan Morgan,46
Melissa Stewart,77
Mary Walker,55
Justin Ramirez,59
Debra Thomas,52
Dorothy Smith,20
Jennifer Gonzalez,63
Andrew Rivera,75
Gary Nelson,63
Janet Allen,57
Karen Robinson,36
Dennis Martinez,32
Joseph Rivera,19
Dorothy Morales,62
Brandon Reyes,52
Jack Walker,24
Brandon Morgan,73
Amy Hill,24
Joseph Green,66
Deborah Moore,57
Helen Cook,23
Jonathan Jackson,49
Ruth Gomez,85
Betty Walker,47
Cynthia Hall,37
Gary Martinez,66
Edward Ramirez,23
Amanda Gutierrez,54
Anthony Diaz,39
Pamela Hill,53
Anna Brown,41
Mary Mitchell,56
Jennifer Walker,66
Samantha Ramirez,74
Sandra Hall,18
Debra Brown,77
Anna Parker,58
Michelle Johnson,33
Mark Jones,67
Sharon Roberts,79
Kenneth Lopez,83
Patrick Scott,59
Kathleen Lopez,39
Matthew Williams,30
Jessica Wright,51
Benjamin Allen,63
Christine Stewart,53
Michael King,64
Mary Stewart,41
Christine Thomas,31
Karen Parker,76
David Martinez,67
Helen Sanchez,34
Amanda Cooper,27
Janet Turner,29
Catherine Parker,53
Samuel Torres,29
Janet Ramirez,81
Dorothy Scott,69
Timothy Lewis,42
Jeffrey Roberts,61
Helen Thomas,27
Donald Wright,32
Lisa Roberts,84
Christine Martinez,51
Catherine Morales,62
George Gutierrez,38
Karen Anderson,30
Sarah Edwards,28
Christopher Martinez,76
Melissa Rodriguez,78
Jennifer Anderson,31
Stephanie Edwards,23
Donald Nelson,35
Elizabeth Wright,66
Steven Miller,47
Susan Lopez,42
Patrick Harris,84
Steven Morris,69
Lisa Miller,21
Charles Hill,46
Gary Martin,61
Emma Thompson,30
Gary Murphy,83
Ruth Stewart,76
Jonathan Williams,51
Cynthia Parker,61
Emma Rodriguez,82
Katherine Campbell,33
Frank Morris,28
Debra Miller,32
Amanda Hall,51
Larry Campbell,22
Kimberly Gutierrez,41
Sarah Rodriguez,31
Steven Gonzalez,79
Steven Edwards,33
Ryan Rivera,25
Sharon Davis,34
Sandra Garcia,77
Samantha Adams,25
Ruth Thomas,69
Sarah Clark,47
Mary Brown,84
Shirley Miller,81
Emma Cook,19
Jason Sanchez,28
Carol Edwards,25
Jessica Phillips,37
Kevin White,48
Kenneth Perez,83
Kevin Torres,59
Kenneth Parker,71
Jonathan Anderson,51
James Diaz,77
Charles Cook,60
Carol Roberts,55
Brandon Mitchell,82
Robert Adams,18
Michael Clark,50
Ruth Brown,34
Kenneth Martin,82
Kenneth Allen,48
Elizabeth White,32
Mary Jackson,55
Kimberly Cruz,54
Scott Moore,71
Jason Gutierrez,80
Brandon Cruz,18
Steven Jackson,57
Richard Smith,79
Mary Miller,74
Elizabeth Stewart,77
Debra Evans,62
Catherine Edwards,28
Jacob Thomas,64
Rebecca Edwards,66
Dorothy Gutierrez,35
Sandra Lee,67
Pamela Johnson,25
Susan Diaz,67
Gregory Morales,73
Charles Baker,37
Susan Roberts,84
Carol Scott,75
Charles Evans,18
Janet Wilson,38
George Williams,68
Emma Martinez,28
Raymond Rogers,48
Joseph Reyes,68
Amy Evans,40
Matthew Taylor,26
Ruth Young,22
Jason Phillips,26
Sandra Murphy,41
Joshua Wright,28
Mary Adams,28
William Moore,57
Ruth Taylor,55
Christopher Davis,27
Rebecca Johnson,25
Alexander Anderson,76
Rachel Garcia,58
Shirley Murphy,42
Angela Walker,29
Debra Cruz,31
Carol Perez,45
Jason Green,32
Andrew Gutierrez,46
Ashley Sanchez,78
Katherine White,72
Patricia Lee,33
Jacob Johnson,40
Stephen Green,74
Alexander Allen,26
Jennifer Jones,24
Samuel Carter,72
Brenda Smith,37
Ronald Flores,33
Benjamin Edwards,33
Linda Collins,50
Lisa Ortiz,34
Thomas Anderson,42
Jennifer Clark,61
Margaret Ortiz,29
William Flores,53
Samantha Gutierrez,59
Susan White,83
David Scott,40
Margaret Martinez,42
Sharon Hernandez,74
Rebecca Murphy,83
Rebecca Taylor,85
Maria Williams,26
James Anderson,39
Angela Campbell,23
Amy Murphy,21
Jessica Green,74
John Moore,65
Karen Allen,61
Michelle Anderson,24
Emily Miller,55
Pamela Nguyen,66
Raymond Allen,23
Elizabeth Morris,33
Jerry Hernandez,51
Kevin Walker,28
Kevin Lopez,79
Thomas Wilson,19
Andrew Moore,44
Patrick Green,55
Thomas Cook,75
Mark Parker,56
Robert Morris,54
Eric Parker,64
Anthony King,42
Sarah Davis,41
Melissa Davis,20
Anna Gomez,72
Katherine Thompson,22
Emma Turner,83
Dorothy Gomez,63
Raymond Mitchell,18
Ryan Scott,71
Frank Harris,32
Emma Carter,29
Thomas Carter,49
Linda Smith,25
Dennis Taylor,38
Anna Phillips,34
Pamela King,46
Sharon Nguyen,37
Susan Nelson,83
Sandra Thompson,43
Timothy Johnson,72
Janet Morris,51
Stephen Thompson,22
Emma Phillips,81
Rachel Thomas,53
Pamela Reyes,63
Paul Smith,24
Donald Cruz,18
Linda Lewis,73
Jack Rodriguez,24
Karen Rivera,22
Dennis Morales,41
Jerry Scott,56
Jacob Diaz,47
Kathleen Davis,64
David Cook,65
Joshua Nguyen,23
Gregory Campbell,30
Thomas Murphy,26
James Campbell,27
Donna Martinez,47
Dorothy Hernandez,52
Jeffrey Rodriguez,53
Donna White,68
Larry Nelson,82
Kevin Rivera,72
Mary Gonzalez,65
Kenneth Morales,79
Kevin Morales,39
Debra Thomas,66
Dennis Martin,78
Elizabeth Hall,68
Donald Anderson,76
Michelle Gonzalez,66
Justin Nguyen,50
Ashley Robinson,77
Sharon Scott,77
Lisa Parker,84
Sandra Martinez,45
Emma Parker,38
Betty Anderson,50
Debra Lopez,77
Rebecca Flores,73
Linda Cook,80
Janet Turner,23
Stephen Torres,44
Elizabeth Brown,26
Deborah Collins,66
Donna Cooper,62
Brian Nelson,77
Joshua Turner,19
Ashley Nelson,83
Patricia Morris,73
Charles Carter,43
Samantha Hall,43
Debra Walker,48
Jerry Davis,73
Gary Young,31
Maria King,24
Dennis Mitchell,50
Paul White,28
Emily Lee,25
Gregory Allen,70
Katherine Hall,62
Helen Baker,25
Charles Gomez,28
Kathleen Hall,57
Kathleen Smith,72
Kathleen Flores,27
Steven Thomas,46
Brenda Lopez,48
Brandon Rodriguez,21
Betty Miller,57
Kevin Miller,76
Kevin Harris,25
Laura Taylor,37
Nicole Gonzalez,65
Donna Adams,35
Richard Smith,65
Rebecca Thomas,76
Stephanie Robinson,57
Scott Collins,45
Steven Green,58
Eric Cooper,26
Brandon Hill,68
Katherine Nguyen,55
Linda Scott,49
Samuel Green,30
Joshua White,60
Charles Green,29
Amy Evans,45
Charles Parker,29
Stephanie Gonzalez,50
Raymond Wright,83
Joshua Flores,63
Alexander Murphy,78
Daniel Flores,41
Raymond Johnson,82
Shirley Thompson,43
Melissa Stewart,32
Samuel Brown,22
Nancy Stewart,21
Catherine Rodriguez,45
Richard Cruz,72
Mary White,40
Betty Walker,83
Sarah Morris,21
Jerry Reyes,52
Elizabeth Stewart,27
Christopher Hill,33
Dorothy Gutierrez,31
Ruth Perez,70
Rebecca Brown,45
Scott Nguyen,50
Alexander Diaz,83
Christopher Perez,83
Matthew Johnson,46
Anthony Taylor,21
Larry Nguyen,80
Jason Perez,46
Nancy Clark,35
Timothy Rogers,25
Carol Stewart,42
Angela Gonzalez,38
Anthony Rivera,79
Angela Cruz,56
Katherine Cooper,70
Jerry Diaz,81
Alexander Hernandez,44
Jacob Taylor,37
Debra Gutierrez,68
Alexander Roberts,62
Cynthia Parker,30
Kenneth Gonzalez,60
Benjamin Morgan,29
Steven Thomas,21
Charles Mitchell,54
Jerry Miller,37
Jennifer Flores,67
Deborah Perez,55
Paul Cooper,37
Catherine Thompson,36
Sandra Robinson,81
Janet Martin,44
Joshua Thomas,72
Jacob Gutierrez,76
Sandra Roberts,46
Paul Thomas,82
Raymond Smith,84
Debra Morales,66
Carol Cook,59
Barbara Green,64
Scott White,79
Patrick Scott,84
Eric Morgan,48
Kathleen Nguyen,46
Brandon Reyes,37
Debra Lopez,83
Rachel Jackson,22
Janet Walker,24
Katherine Moore,26
Dennis Stewart,39
Katherine Diaz,72
Maria Roberts,68
Anthony Jones,38
Elizabeth Moore,18
James Collins,61
Dorothy Jones,33
Donna Hall,23
Angela Gomez,44
Jason Walker,30
Brandon Cruz,35
Rachel Sanchez,26
Jack Nguyen,54
Mark Jackson,74
Samantha Thompson,20
Jonathan Phillips,23
Betty Collins,54
Paul Jones,32
Mary Campbell,48
Laura Davis,25
Benjamin Adams,19
Stephen Green,74
Karen Roberts,47
Brenda Murphy,41
Helen Flores,75
Barbara Rivera,50
Ryan Wilson,34
Elizabeth Wright,24
Frank Wilson,20
Nicholas Allen,73
Melissa Anderson,67
Melissa Evans,70
William Cooper,61
Jeffrey Campbell,25
Karen Sanchez,66
William Turner,74
Lisa Rodriguez,23
Robert Adams,43
Dennis Flores,49
Anna Reyes,34
Jennifer Nelson,36
Sandra Cruz,58
Janet Hill,46
Michelle Scott,30
Robert Reyes,71
James Davis,26
Nicholas Green,64
Ronald Smith,73
Dorothy Torres,39
Helen Phillips,74
Carolyn Collins,72
Michael Lee,34
William Garcia,65
Brian Hall,37
Karen Morris,31
Ronald Hill,28
Michael Brown,32
James Baker,85
Jerry King,33
Melissa Lewis,50
Steven Jackson,26
Jeffrey Torres,60
Alexander Phillips,51
Scott Nguyen,18
Jacob Sanchez,63
Patrick Johnson,72
Raymond Rodriguez,36
Karen Stewart,54
Ronald Roberts,21
Debra Gomez,75
Timothy Rodriguez,41
Jack Rodriguez,64
Angela Moore,22
Michelle Jones,40
Cynthia Anderson,52
Jeffrey Roberts,67
David King,32
Amy Carter,85
Susan Cook,85
Eric Martinez,80
Jacob Rogers,50
Robert Wilson,36
Rebecca Carter,83
Michael Hernandez,78
Amanda Rivera,66
Thomas White,45
Jennifer White,74
Emily Collins,27
Matthew Rodriguez,51
Ronald Hall,72
Kimberly Taylor,38
Sharon Morales,20
Richard Rodriguez,28
Janet Hill,46
Frank Lewis,58
Raymond Morgan,60
Anna Thompson,25
Betty Mitchell,77
Jennifer Gonzalez,47
Carolyn Mitchell,34
Kathleen Morris,79
Gregory Reyes,37
Richard Martin,38
Mark Perez,48
Ruth Jackson,63
Angela Nguyen,62
Michelle Clark,73
Amanda Williams,24
Ashley Morris,74
Robert Parker,34
Andrew Hernandez,41
Jennifer Torres,42
Patrick Ramirez,70
Kathleen Sanchez,68
Maria Nguyen,43
John Brown,52
Nancy Turner,33
Eric Torres,66
Samuel Hill,68
Debra Miller,52
Jerry Green,46
Ronald Johnson,75
Linda Young,44
Richard Morgan,34
Amy Hernandez,64
Andrew Lee,66
Ashley Morris,67
Mark Hernandez,33
Angela Morris,55
Betty Davis,78
Emily Nelson,41
Daniel Parker,50
Lisa Evans,75
Edward Sanchez,21
Melissa Allen,85
Nicholas Adams,72
Ryan White,84
Richard Perez,39
Ronald Moore,39
Carolyn Gomez,40
Patricia Robinson,63
Dennis Brown,38
Gregory Mitchell,79
Donna Stewart,18
Samantha Thomas,63
Patrick Diaz,18
Mark Murphy,63
Paul Miller,49
Anna Wright,56
Raymond Adams,69
Edward Baker,52
Thomas Cook,21
Kathleen Perez,64
Jerry Hernandez,40
Nancy Stewart,66
William Reyes,49
Timothy Collins,53
Angela Rogers,64
Daniel Lewis,48
Need 10 MB+ to test the limits? You can also generate 250,000 records locally using Python:
# Python 3 snippet to generate a 10MB names.csv file
import random
first = ["James", "Mary", "John", "Patricia", "Robert", "Jennifer", "Michael", "Linda", "William", "David"]
last = ["Smith", "Johnson", "Williams", "Brown", "Jones", "Garcia", "Miller", "Davis", "Rodriguez", "Martinez"]
with open("names.csv", "w") as f:
f.write("Name,Age\n")
for _ in range(250000):
f.write(f"{random.choice(first)} {random.choice(last)},{random.randint(18, 90)}\n")
print("names.csv created (~5.5 to 6.5 MB; double loop range for 12 MB)!")
Full Pascal Source (namesort.pas)
Here is the complete, self-contained Pascal source code. You can paste it directly into
wasmpascal.com, compile it to
WebAssembly,
and download namesort.wasm:
namesort.pas:
library namesort;
{$M 128M} { 128 MB linear memory (2,048 pages) for large buffer allocation }
{ ------------------------------------------------------------------ }
{ namesort.pas — High-Performance Large CSV Sorter in WebAssembly }
{ }
{ Ingests large CSV files (such as 10 MB names.csv with 300k+ rows). }
{ Uses 12-byte zero-copy index records instead of string copying. }
{ Employs in-place Quicksort O(N log N) for rapid sorting. }
{ }
{ Compile at https://wasmpascal.com/ -> Run -> Download .wasm }
{ Save as namesort.wasm alongside companion index.html. }
{ ------------------------------------------------------------------ }
const
MAX_INPUT = 16777216; { 16 MB input buffer }
MAX_OUTPUT = 16777216; { 16 MB output buffer }
MAX_RECORDS = 500000; { Up to 500,000 index records }
type
TIndexRecord = record
nameOffset: Integer; { byte offset in inputBuffer }
nameLen: Integer; { length of the name slice }
age: Integer; { parsed integer age }
end;
var
inputBuffer: array[0..MAX_INPUT - 1] of Char;
outputBuffer: array[0..MAX_OUTPUT - 1] of Char;
outputLen: Integer;
records: array[0..MAX_RECORDS - 1] of TIndexRecord;
recordCount: Integer;
function GetInputBuffer: Integer;
begin
GetInputBuffer := Integer(@inputBuffer[0]);
end;
function GetOutputBuffer: Integer;
begin
GetOutputBuffer := Integer(@outputBuffer[0]);
end;
function GetOutputLength: Integer;
begin
GetOutputLength := outputLen;
end;
function GetMaxInputSize: Integer;
begin
GetMaxInputSize := MAX_INPUT;
end;
procedure AppendChar(c: Char);
begin
if outputLen < MAX_OUTPUT then
begin
outputBuffer[outputLen] := c;
outputLen := outputLen + 1;
end;
end;
procedure AppendInt(n: Integer);
var
temp: array[0..15] of Char;
digits: Integer;
val: Integer;
d: Integer;
begin
if n = 0 then
begin
AppendChar('0');
Exit;
end;
if n < 0 then
begin
AppendChar('-');
val := -n;
end
else
val := n;
digits := 0;
while val > 0 do
begin
d := val mod 10;
temp[digits] := Chr(Ord('0') + d);
digits := digits + 1;
val := val div 10;
end;
while digits > 0 do
begin
digits := digits - 1;
AppendChar(temp[digits]);
end;
end;
procedure QuickSort(left, right: Integer);
var
i, j, pivot: Integer;
temp: TIndexRecord;
begin
i := left;
j := right;
pivot := records[(left + right) div 2].age;
repeat
while records[i].age < pivot do i := i + 1;
while records[j].age > pivot do j := j - 1;
if i <= j then
begin
temp := records[i];
records[i] := records[j];
records[j] := temp;
i := i + 1;
j := j - 1;
end;
until i > j;
if left < j then QuickSort(left, j);
if i < right then QuickSort(i, right);
end;
function ProcessCSV(inputLen: Integer): Integer;
var
pos: Integer;
nameStart: Integer;
nameLength: Integer;
curAge: Integer;
isFirstLine: Boolean;
hasAge: Boolean;
r, k: Integer;
begin
recordCount := 0;
outputLen := 0;
if (inputLen <= 0) or (inputLen > MAX_INPUT) then
begin
ProcessCSV := 0;
Exit;
end;
pos := 0;
isFirstLine := True;
while pos < inputLen do
begin
{ Skip blank characters or newline remnants }
while (pos < inputLen) and ((inputBuffer[pos] = ' ') or (inputBuffer[pos] = #13) or (inputBuffer[pos] = #10)) do
pos := pos + 1;
if pos >= inputLen then Break;
nameStart := pos;
{ Scan Name field until comma, newline, or carriage return }
while (pos < inputLen) and (inputBuffer[pos] <> ',') and (inputBuffer[pos] <> #10) and (inputBuffer[pos] <> #13) do
pos := pos + 1;
nameLength := pos - nameStart;
{ Strip surrounding quotes if present }
if (nameLength >= 2) and (inputBuffer[nameStart] = '"') and (inputBuffer[nameStart + nameLength - 1] = '"') then
begin
nameStart := nameStart + 1;
nameLength := nameLength - 2;
end;
{ Skip comma delimiter }
if (pos < inputLen) and (inputBuffer[pos] = ',') then
pos := pos + 1;
{ Skip trailing spaces after comma }
while (pos < inputLen) and (inputBuffer[pos] = ' ') do
pos := pos + 1;
{ Parse Age digits }
curAge := 0;
hasAge := False;
while (pos < inputLen) and (inputBuffer[pos] >= '0') and (inputBuffer[pos] <= '9') do
begin
curAge := curAge * 10 + (Ord(inputBuffer[pos]) - Ord('0'));
hasAge := True;
pos := pos + 1;
end;
{ Skip rest of line until next line }
while (pos < inputLen) and (inputBuffer[pos] <> #10) and (inputBuffer[pos] <> #13) do
pos := pos + 1;
while (pos < inputLen) and ((inputBuffer[pos] = #10) or (inputBuffer[pos] = #13)) do
pos := pos + 1;
{ Skip header line if detected }
if isFirstLine and ((not hasAge) or (nameLength = 4)) then
begin
if (inputBuffer[nameStart] in ['N', 'n']) and
(inputBuffer[nameStart+1] in ['A', 'a']) and
(inputBuffer[nameStart+2] in ['M', 'm']) and
(inputBuffer[nameStart+3] in ['E', 'e']) then
begin
isFirstLine := False;
Continue;
end;
end;
isFirstLine := False;
if (nameLength > 0) and hasAge and (recordCount < MAX_RECORDS) then
begin
records[recordCount].nameOffset := nameStart;
records[recordCount].nameLen := nameLength;
records[recordCount].age := curAge;
recordCount := recordCount + 1;
end;
end;
{ Sort index table in-place }
if recordCount > 1 then
QuickSort(0, recordCount - 1);
{ Construct sorted CSV output }
AppendChar('N'); AppendChar('a'); AppendChar('m'); AppendChar('e');
AppendChar(',');
AppendChar('A'); AppendChar('g'); AppendChar('e');
AppendChar(#10);
for r := 0 to recordCount - 1 do
begin
nameStart := records[r].nameOffset;
nameLength := records[r].nameLen;
for k := 0 to nameLength - 1 do
AppendChar(inputBuffer[nameStart + k]);
AppendChar(',');
AppendInt(records[r].age);
AppendChar(#10);
end;
ProcessCSV := recordCount;
end;
exports
GetInputBuffer name 'GetInputBuffer',
GetOutputBuffer name 'GetOutputBuffer',
GetOutputLength name 'GetOutputLength',
GetMaxInputSize name 'GetMaxInputSize',
ProcessCSV name 'ProcessCSV';
begin
end.
Full HTML & JavaScript Host (index.html)
Save this file as index.html next to your compiled namesort.wasm:
index.html:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>High-Speed Pascal CSV Sorter (names.csv)</title>
<style>
body { font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif; max-width: 760px; margin: 3rem auto; padding: 0 1rem; line-height: 1.5; }
.card { border: 1px solid #ccc; border-radius: 8px; padding: 1.5rem; background: #fafafa; }
.dropzone { border: 2px dashed #0284c7; border-radius: 6px; padding: 2rem; text-align: center; cursor: pointer; margin-bottom: 1rem; }
.btn { background: #0284c7; color: #fff; border: none; padding: 8px 16px; border-radius: 4px; cursor: pointer; font-size: 0.95rem; text-decoration: none; }
.status { font-family: monospace; padding: 0.5rem; background: #eee; border-radius: 4px; margin-top: 1rem; }
</style>
</head>
<body>
<h1>Pascal WebAssembly CSV Sorter</h1>
<div class="card">
<div class="dropzone" id="dropzone">Drag & Drop <strong>names.csv</strong> here or click to select</div>
<input type="file" id="fileInput" style="display:none;" accept=".csv,text/csv">
<a id="downloadBtn" class="btn" style="display:none;" download="names_sorted.csv">Download Sorted CSV</a>
<div class="status" id="status">Status: Loading WebAssembly module...</div>
</div>
<script>
(async function() {
const status = document.getElementById('status');
const dropzone = document.getElementById('dropzone');
const fileInput = document.getElementById('fileInput');
const downloadBtn = document.getElementById('downloadBtn');
let wasmInstance = null;
try {
const obj = await WebAssembly.instantiateStreaming(fetch('namesort.wasm'), {
wasmpascal_env: { heap_report: () => {} }
});
wasmInstance = obj.instance;
status.textContent = 'Status: WebAssembly ready! Drop names.csv to process.';
} catch (err) {
status.textContent = 'Status: Load via local web server to run WebAssembly (' + err + ')';
}
dropzone.onclick = () => fileInput.click();
dropzone.ondragover = (e) => { e.preventDefault(); dropzone.style.background = '#e0f2fe'; };
dropzone.ondragleave = () => { dropzone.style.background = ''; };
dropzone.ondrop = (e) => {
e.preventDefault();
dropzone.style.background = '';
if (e.dataTransfer.files.length) handleFile(e.dataTransfer.files[0]);
};
fileInput.onchange = (e) => {
if (e.target.files.length) handleFile(e.target.files[0]);
};
async function handleFile(file) {
if (!wasmInstance) return;
status.textContent = 'Status: Reading ' + file.name + '...';
const buf = await file.arrayBuffer();
const bytes = new Uint8Array(buf);
const exp = wasmInstance.exports;
const inAddr = exp.GetInputBuffer();
const memView = new Uint8Array(exp.memory.buffer);
memView.set(bytes, inAddr);
const t0 = performance.now();
const count = exp.ProcessCSV(bytes.length);
const elapsed = (performance.now() - t0).toFixed(2);
const outAddr = exp.GetOutputBuffer();
const outLen = exp.GetOutputLength();
const outBytes = new Uint8Array(exp.memory.buffer, outAddr, outLen);
const blob = new Blob([outBytes], { type: 'text/csv;charset=utf-8;' });
downloadBtn.href = URL.createObjectURL(blob);
downloadBtn.style.display = 'inline-block';
status.textContent = `Status: Sorted ${count} records in ${elapsed} ms! Click download button.`;
}
})();
</script>
</body>
</html>
Conclusion
Handling large CSV files in the browser isn't all that difficult:
- We configure 128 MB of linear memory to hold massive files without allocating tons of individual objects.
- We avoid string allocation overhead by storing 12-byte zero-copy index descriptors.
- We replace O(N²) algorithms with an in-place Quicksort that handles 300,000 rows easily.
- We stream raw memory directly to browser
Blobdownloads.
Give it a spin with your own names.csv datasets, or compile your own customized data
pipelines on
wasmpascal.com!