Skip to content

Add Deno test app #6

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Draft
wants to merge 11 commits into
base: master
Choose a base branch
from
1 change: 1 addition & 0 deletions .eslintrc.json
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
"sourceType": "module",
"project": ["./tsconfig.eslint.json"]
},
"ignorePatterns": ["test/deno/*.ts"],
"plugins": ["@typescript-eslint"],
"rules": {
"comma-dangle": "off",
Expand Down
3 changes: 3 additions & 0 deletions test/deno/.vscode/extensions.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
{
"recommendations": ["denoland.vscode-deno"]
}
10 changes: 10 additions & 0 deletions test/deno/.vscode/settings.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
{
"editor.formatOnSave": true,
"editor.defaultFormatter": "denoland.vscode-deno",
"deno.enable": true,
"deno.config": "./deno.json",
"deno.lint": true,
"deno.suggest.imports.hosts": {
"https://deno.land": true
}
}
140 changes: 140 additions & 0 deletions test/deno/csv-parser.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,140 @@
import pako from 'https://deno.land/x/[email protected]/pako.js';

// @deno-types = "../../lib/types/csv.d.ts"
import {
Column,
ColumnHeader,
CSV,
CsvLoaderOptions,
DataType,
isNumber,
LoadStatistics,
} from '../../lib/csv.js';
import type { NumberColumn } from '../../lib/types/types/column/numberColumn.d.ts';

// Run with `deno run --config ./deno.json --allow-read --allow-net=api.varg.dev csv-parser.ts`

const conf = JSON.parse(await Deno.readTextFile('../conf.json'));

const options = new CsvLoaderOptions({
includesHeader: true,
delimiter: ',',
});

function onOpened(this: CSV, tag: string, columns: ColumnHeader[]): void {
console.log(
tag,
`opened source, detected ${columns.length} columns:\n` +
columns.map((c) => `${c.name}: ${DataType[c.type]}`).join('\n'),
);
this.load({
columns: columns.map((c) => c.type),
generatedColumns: [],
});
}

type Stats = {
tag: string;
rows: number;
kB: number;
time: number;
rowsPerSecond: number;
kBPerSecond: number;
};
const statistics = new Array<Stats>();

function onDone(
this: CSV,
tag: string,
done: () => void,
columns: Column[],
stats: LoadStatistics,
): void {
let columnsStats = '=== column stats: ===\n';
columnsStats += columns
.map((c) => {
let text = `${c.name}: ${c.length} rows`;
const asNum = c as NumberColumn;

if (isNumber(c.type)) text += `, min ${asNum.min}, max ${asNum.max}`;

return text;
})
.join('\n');

const timeMS = stats.performance.find((s) => s.label === 'open')!.delta +
stats.performance.find((s) => s.label === 'load')!.delta;
const timeS = timeMS / 1000;
const kB = stats.bytes / 1000;
const rows = columns[0].length;
const kRows = rows / 1000;

statistics.push({
tag,
rows,
kB,
time: timeS,
rowsPerSecond: rows / timeS,
kBPerSecond: kB / timeS,
});

const loaderStats = '=== loader stats: ===\n' +
`source bytes: ${stats.bytes}\n` +
`source chunks: ${stats.chunks}\n` +
`number of workers: ${stats.workers}\n` +
`read rows: ${rows}\n` +
`kB / worker: ${(kB / stats.workers).toFixed(3)}\n` +
`chunks / worker: ${(stats.chunks / stats.workers).toFixed(3)}\n` +
`total time in s: ${timeS.toFixed(3)}\n` +
`kB / s: ${(kB / timeS).toFixed(3)}\n` +
`kRows / s: ${(kRows / timeS).toFixed(3)}\n`;

console.log(tag, `done.\n${columnsStats}\n${loaderStats}`);

console.groupCollapsed('=== performance stats: ===');
stats.performance.forEach((m) => console.log(`${m.label}: ${m.delta} ms`));
console.groupEnd();

done();
}

function createLoader(tag: string, done: () => void): CSV {
const loader = new CSV(options);

loader.on('opened', onOpened.bind(loader, tag));
loader.on('columns', (columns: Column[]) => {
console.log(tag, 'received columns');
loader.on('done', onDone.bind(loader, tag, done, columns));
});
loader.on('data', (progress: number) => {
console.log(tag, `received new data. progress: ${progress}`);
});
loader.on('error', (msg: string) => {
console.log(tag, 'error:', msg);
done();
});

console.log(tag, 'created');

return loader;
}

function testUrl(tag: string, url: string): Promise<void> {
return new Promise<void>((resolve) => {
createLoader(tag, resolve).open(url);
});
}

function testGzipped(testCase: string, file: Uint8Array): Promise<void> {
return new Promise<void>((resolve) => {
createLoader(testCase, resolve).open((pako.inflate(file) as Uint8Array).buffer);
});
}

await testUrl('[remote url stream]', conf.url);
await testGzipped('[1m gzip buffer]', await Deno.readFile('../data/1m.csv.gz'));
// await testUrl('[10m url stream]', await Deno.readFile('../data/10m.csv'));
// await testUrl('[50m url stream]', await Deno.readFile('../data/50m.csv'));
// await testUrl('[100m url stream]', await Deno.readFile('../data/100m.csv'));

console.table(statistics);
15 changes: 15 additions & 0 deletions test/deno/deno.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
{
"fmt": {
"options": {
"indentWidth": 4,
"lineWidth": 100,
"singleQuote": true
}
},
"compilerOptions": {
"lib": [
"deno.ns",
"dom"
]
}
}