bun-scikit 0.1.1 → 0.1.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +2 -2
- package/docs/README.md +1 -0
- package/package.json +2 -3
- package/prebuilt/linux-x64/bun_scikit_kernels.so +0 -0
- package/prebuilt/linux-x64/bun_scikit_node_addon.node +0 -0
- package/prebuilt/windows-x64/bun_scikit_kernels.dll +0 -0
- package/prebuilt/windows-x64/bun_scikit_node_addon.node +0 -0
- package/scripts/check-benchmark-health.ts +101 -1
- package/src/native/zigKernels.ts +14 -0
- package/binding.gyp +0 -21
package/README.md
CHANGED
|
@@ -62,8 +62,8 @@ bun install bun-scikit
|
|
|
62
62
|
|
|
63
63
|
Postinstall behavior:
|
|
64
64
|
|
|
65
|
-
-
|
|
66
|
-
-
|
|
65
|
+
- Prebuilt native binaries for `linux-x64` and `windows-x64` are bundled in the npm package.
|
|
66
|
+
- No `bun pm trust` step is required for normal install/use.
|
|
67
67
|
- macOS prebuilt binaries are currently not published.
|
|
68
68
|
|
|
69
69
|
## Usage
|
package/docs/README.md
CHANGED
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "bun-scikit",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.3",
|
|
4
4
|
"description": "A scikit-learn-inspired machine learning library for Bun/TypeScript.",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"module": "index.ts",
|
|
@@ -30,10 +30,10 @@
|
|
|
30
30
|
},
|
|
31
31
|
"files": [
|
|
32
32
|
"index.ts",
|
|
33
|
+
"prebuilt",
|
|
33
34
|
"src",
|
|
34
35
|
"zig",
|
|
35
36
|
"scripts",
|
|
36
|
-
"binding.gyp",
|
|
37
37
|
"docs/native-abi.md",
|
|
38
38
|
"README.md",
|
|
39
39
|
"LICENSE"
|
|
@@ -43,7 +43,6 @@
|
|
|
43
43
|
"bun": ">=1.3.9"
|
|
44
44
|
},
|
|
45
45
|
"scripts": {
|
|
46
|
-
"install": "bun run scripts/install-native.ts",
|
|
47
46
|
"test": "bun test",
|
|
48
47
|
"typecheck": "bunx tsc --noEmit",
|
|
49
48
|
"bench": "bun run bench/heart.bench.ts",
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
@@ -31,6 +31,8 @@ interface BenchmarkSnapshot {
|
|
|
31
31
|
regression: {
|
|
32
32
|
results: [RegressionBenchmarkResult, RegressionBenchmarkResult];
|
|
33
33
|
comparison: {
|
|
34
|
+
fitSpeedupVsSklearn: number;
|
|
35
|
+
predictSpeedupVsSklearn: number;
|
|
34
36
|
mseDeltaVsSklearn: number;
|
|
35
37
|
r2DeltaVsSklearn: number;
|
|
36
38
|
};
|
|
@@ -38,16 +40,46 @@ interface BenchmarkSnapshot {
|
|
|
38
40
|
classification: {
|
|
39
41
|
results: [ClassificationBenchmarkResult, ClassificationBenchmarkResult];
|
|
40
42
|
comparison: {
|
|
43
|
+
fitSpeedupVsSklearn: number;
|
|
44
|
+
predictSpeedupVsSklearn: number;
|
|
41
45
|
accuracyDeltaVsSklearn: number;
|
|
42
46
|
f1DeltaVsSklearn: number;
|
|
43
47
|
};
|
|
44
48
|
};
|
|
45
49
|
treeClassification: {
|
|
46
|
-
models: [
|
|
50
|
+
models: [
|
|
51
|
+
TreeModelComparison & {
|
|
52
|
+
comparison: TreeModelComparison["comparison"] & {
|
|
53
|
+
fitSpeedupVsSklearn: number;
|
|
54
|
+
predictSpeedupVsSklearn: number;
|
|
55
|
+
};
|
|
56
|
+
},
|
|
57
|
+
TreeModelComparison & {
|
|
58
|
+
comparison: TreeModelComparison["comparison"] & {
|
|
59
|
+
fitSpeedupVsSklearn: number;
|
|
60
|
+
predictSpeedupVsSklearn: number;
|
|
61
|
+
};
|
|
62
|
+
},
|
|
63
|
+
];
|
|
47
64
|
};
|
|
48
65
|
};
|
|
49
66
|
}
|
|
50
67
|
|
|
68
|
+
function speedupThreshold(
|
|
69
|
+
envName: string,
|
|
70
|
+
defaultValue: number,
|
|
71
|
+
): number {
|
|
72
|
+
const raw = process.env[envName];
|
|
73
|
+
if (!raw) {
|
|
74
|
+
return defaultValue;
|
|
75
|
+
}
|
|
76
|
+
const parsed = Number(raw);
|
|
77
|
+
if (!Number.isFinite(parsed) || parsed <= 0) {
|
|
78
|
+
throw new Error(`${envName} must be a positive number when set. Got: ${raw}`);
|
|
79
|
+
}
|
|
80
|
+
return parsed;
|
|
81
|
+
}
|
|
82
|
+
|
|
51
83
|
const pathArgIndex = Bun.argv.indexOf("--input");
|
|
52
84
|
const inputPath =
|
|
53
85
|
pathArgIndex !== -1 && pathArgIndex + 1 < Bun.argv.length
|
|
@@ -59,6 +91,23 @@ const snapshot = JSON.parse(await readFile(inputPath, "utf-8")) as BenchmarkSnap
|
|
|
59
91
|
const [bunRegression, sklearnRegression] = snapshot.suites.regression.results;
|
|
60
92
|
const [bunClassification, sklearnClassification] = snapshot.suites.classification.results;
|
|
61
93
|
const [decisionTree, randomForest] = snapshot.suites.treeClassification.models;
|
|
94
|
+
const minRegressionFitSpeedup = speedupThreshold("BENCH_MIN_REGRESSION_FIT_SPEEDUP", 1.1);
|
|
95
|
+
const minRegressionPredictSpeedup = speedupThreshold("BENCH_MIN_REGRESSION_PREDICT_SPEEDUP", 1.1);
|
|
96
|
+
const minClassificationFitSpeedup = speedupThreshold("BENCH_MIN_CLASSIFICATION_FIT_SPEEDUP", 1.3);
|
|
97
|
+
const minClassificationPredictSpeedup = speedupThreshold(
|
|
98
|
+
"BENCH_MIN_CLASSIFICATION_PREDICT_SPEEDUP",
|
|
99
|
+
1.3,
|
|
100
|
+
);
|
|
101
|
+
const minDecisionTreeFitSpeedup = speedupThreshold("BENCH_MIN_DECISION_TREE_FIT_SPEEDUP", 1.2);
|
|
102
|
+
const minDecisionTreePredictSpeedup = speedupThreshold(
|
|
103
|
+
"BENCH_MIN_DECISION_TREE_PREDICT_SPEEDUP",
|
|
104
|
+
1.5,
|
|
105
|
+
);
|
|
106
|
+
const minRandomForestFitSpeedup = speedupThreshold("BENCH_MIN_RANDOM_FOREST_FIT_SPEEDUP", 2.0);
|
|
107
|
+
const minRandomForestPredictSpeedup = speedupThreshold(
|
|
108
|
+
"BENCH_MIN_RANDOM_FOREST_PREDICT_SPEEDUP",
|
|
109
|
+
2.0,
|
|
110
|
+
);
|
|
62
111
|
|
|
63
112
|
for (const result of [
|
|
64
113
|
bunRegression,
|
|
@@ -99,6 +148,18 @@ if (Math.abs(snapshot.suites.regression.comparison.mseDeltaVsSklearn) > 0.01) {
|
|
|
99
148
|
);
|
|
100
149
|
}
|
|
101
150
|
|
|
151
|
+
if (snapshot.suites.regression.comparison.fitSpeedupVsSklearn < minRegressionFitSpeedup) {
|
|
152
|
+
throw new Error(
|
|
153
|
+
`Regression fit speedup too low: ${snapshot.suites.regression.comparison.fitSpeedupVsSklearn} < ${minRegressionFitSpeedup}.`,
|
|
154
|
+
);
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
if (snapshot.suites.regression.comparison.predictSpeedupVsSklearn < minRegressionPredictSpeedup) {
|
|
158
|
+
throw new Error(
|
|
159
|
+
`Regression predict speedup too low: ${snapshot.suites.regression.comparison.predictSpeedupVsSklearn} < ${minRegressionPredictSpeedup}.`,
|
|
160
|
+
);
|
|
161
|
+
}
|
|
162
|
+
|
|
102
163
|
if (Math.abs(snapshot.suites.regression.comparison.r2DeltaVsSklearn) > 0.01) {
|
|
103
164
|
throw new Error(
|
|
104
165
|
`Regression R2 delta too large: ${snapshot.suites.regression.comparison.r2DeltaVsSklearn}.`,
|
|
@@ -117,6 +178,21 @@ if (Math.abs(snapshot.suites.classification.comparison.f1DeltaVsSklearn) > 0.05)
|
|
|
117
178
|
);
|
|
118
179
|
}
|
|
119
180
|
|
|
181
|
+
if (snapshot.suites.classification.comparison.fitSpeedupVsSklearn < minClassificationFitSpeedup) {
|
|
182
|
+
throw new Error(
|
|
183
|
+
`Classification fit speedup too low: ${snapshot.suites.classification.comparison.fitSpeedupVsSklearn} < ${minClassificationFitSpeedup}.`,
|
|
184
|
+
);
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
if (
|
|
188
|
+
snapshot.suites.classification.comparison.predictSpeedupVsSklearn <
|
|
189
|
+
minClassificationPredictSpeedup
|
|
190
|
+
) {
|
|
191
|
+
throw new Error(
|
|
192
|
+
`Classification predict speedup too low: ${snapshot.suites.classification.comparison.predictSpeedupVsSklearn} < ${minClassificationPredictSpeedup}.`,
|
|
193
|
+
);
|
|
194
|
+
}
|
|
195
|
+
|
|
120
196
|
if (Math.abs(decisionTree.comparison.accuracyDeltaVsSklearn) > 0.08) {
|
|
121
197
|
throw new Error(
|
|
122
198
|
`DecisionTree accuracy delta too large: ${decisionTree.comparison.accuracyDeltaVsSklearn}.`,
|
|
@@ -127,6 +203,18 @@ if (Math.abs(decisionTree.comparison.f1DeltaVsSklearn) > 0.08) {
|
|
|
127
203
|
throw new Error(`DecisionTree F1 delta too large: ${decisionTree.comparison.f1DeltaVsSklearn}.`);
|
|
128
204
|
}
|
|
129
205
|
|
|
206
|
+
if (decisionTree.comparison.fitSpeedupVsSklearn < minDecisionTreeFitSpeedup) {
|
|
207
|
+
throw new Error(
|
|
208
|
+
`DecisionTree fit speedup too low: ${decisionTree.comparison.fitSpeedupVsSklearn} < ${minDecisionTreeFitSpeedup}.`,
|
|
209
|
+
);
|
|
210
|
+
}
|
|
211
|
+
|
|
212
|
+
if (decisionTree.comparison.predictSpeedupVsSklearn < minDecisionTreePredictSpeedup) {
|
|
213
|
+
throw new Error(
|
|
214
|
+
`DecisionTree predict speedup too low: ${decisionTree.comparison.predictSpeedupVsSklearn} < ${minDecisionTreePredictSpeedup}.`,
|
|
215
|
+
);
|
|
216
|
+
}
|
|
217
|
+
|
|
130
218
|
if (Math.abs(randomForest.comparison.accuracyDeltaVsSklearn) > 0.08) {
|
|
131
219
|
throw new Error(
|
|
132
220
|
`RandomForest accuracy delta too large: ${randomForest.comparison.accuracyDeltaVsSklearn}.`,
|
|
@@ -137,4 +225,16 @@ if (Math.abs(randomForest.comparison.f1DeltaVsSklearn) > 0.08) {
|
|
|
137
225
|
throw new Error(`RandomForest F1 delta too large: ${randomForest.comparison.f1DeltaVsSklearn}.`);
|
|
138
226
|
}
|
|
139
227
|
|
|
228
|
+
if (randomForest.comparison.fitSpeedupVsSklearn < minRandomForestFitSpeedup) {
|
|
229
|
+
throw new Error(
|
|
230
|
+
`RandomForest fit speedup too low: ${randomForest.comparison.fitSpeedupVsSklearn} < ${minRandomForestFitSpeedup}.`,
|
|
231
|
+
);
|
|
232
|
+
}
|
|
233
|
+
|
|
234
|
+
if (randomForest.comparison.predictSpeedupVsSklearn < minRandomForestPredictSpeedup) {
|
|
235
|
+
throw new Error(
|
|
236
|
+
`RandomForest predict speedup too low: ${randomForest.comparison.predictSpeedupVsSklearn} < ${minRandomForestPredictSpeedup}.`,
|
|
237
|
+
);
|
|
238
|
+
}
|
|
239
|
+
|
|
140
240
|
console.log("Benchmark comparison health checks passed.");
|
package/src/native/zigKernels.ts
CHANGED
|
@@ -191,9 +191,16 @@ function candidateLibraryPaths(): string[] {
|
|
|
191
191
|
const extension = suffix;
|
|
192
192
|
const fileName = `bun_scikit_kernels.${extension}`;
|
|
193
193
|
const explicitPath = process.env.BUN_SCIKIT_ZIG_LIB;
|
|
194
|
+
const platformPackagedPath =
|
|
195
|
+
process.platform === "win32"
|
|
196
|
+
? resolve(import.meta.dir, "../../prebuilt/windows-x64", fileName)
|
|
197
|
+
: process.platform === "linux"
|
|
198
|
+
? resolve(import.meta.dir, "../../prebuilt/linux-x64", fileName)
|
|
199
|
+
: null;
|
|
194
200
|
|
|
195
201
|
const candidates = [
|
|
196
202
|
explicitPath,
|
|
203
|
+
platformPackagedPath,
|
|
197
204
|
resolve(process.cwd(), "dist", "native", fileName),
|
|
198
205
|
resolve(process.cwd(), "native", fileName),
|
|
199
206
|
resolve(import.meta.dir, "../../dist/native", fileName),
|
|
@@ -204,8 +211,15 @@ function candidateLibraryPaths(): string[] {
|
|
|
204
211
|
}
|
|
205
212
|
|
|
206
213
|
function candidateAddonPaths(): string[] {
|
|
214
|
+
const platformPackagedPath =
|
|
215
|
+
process.platform === "win32"
|
|
216
|
+
? resolve(import.meta.dir, "../../prebuilt/windows-x64", "bun_scikit_node_addon.node")
|
|
217
|
+
: process.platform === "linux"
|
|
218
|
+
? resolve(import.meta.dir, "../../prebuilt/linux-x64", "bun_scikit_node_addon.node")
|
|
219
|
+
: null;
|
|
207
220
|
const candidates = [
|
|
208
221
|
process.env.BUN_SCIKIT_NODE_ADDON,
|
|
222
|
+
platformPackagedPath,
|
|
209
223
|
resolve(process.cwd(), "dist", "native", "bun_scikit_node_addon.node"),
|
|
210
224
|
resolve(process.cwd(), "build", "Release", "bun_scikit_node_addon.node"),
|
|
211
225
|
resolve(import.meta.dir, "../../dist/native", "bun_scikit_node_addon.node"),
|
package/binding.gyp
DELETED
|
@@ -1,21 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"targets": [
|
|
3
|
-
{
|
|
4
|
-
"target_name": "bun_scikit_node_addon",
|
|
5
|
-
"sources": [ "src/native/node-addon/bun_scikit_addon.cpp" ],
|
|
6
|
-
"include_dirs": [
|
|
7
|
-
"<!@(node -p \"require('node-addon-api').include\")"
|
|
8
|
-
],
|
|
9
|
-
"dependencies": [
|
|
10
|
-
"<!(node -p \"require('node-addon-api').gyp\")"
|
|
11
|
-
],
|
|
12
|
-
"defines": [ "NAPI_DISABLE_CPP_EXCEPTIONS" ],
|
|
13
|
-
"cflags_cc!": [ "-fno-exceptions" ],
|
|
14
|
-
"msvs_settings": {
|
|
15
|
-
"VCCLCompilerTool": {
|
|
16
|
-
"ExceptionHandling": 0
|
|
17
|
-
}
|
|
18
|
-
}
|
|
19
|
-
}
|
|
20
|
-
]
|
|
21
|
-
}
|