mirror of
https://github.com/PR0M3TH3AN/bitvid.git
synced 2026-10-27 07:52:24 +00:00
Merge pull request #2238 from PR0M3TH3AN/perf/kids-scoring-allocation-15408833110746768753
⚡ Optimize object allocation in kids scoring loop
This commit is contained in:
3 files changed
+156
-15
No files matched your search
@@ -0,0 +1,63 @@
|
||||
// benchmarks/kids_scoring_bench.js
|
||||
import { createKidsScorerStage } from "../js/feedEngine/kidsScoring.js";
|
||||
import { performance } from "perf_hooks";
|
||||
|
||||
async function runBenchmark() {
|
||||
const itemCount = 200000;
|
||||
const items = [];
|
||||
|
||||
// Create mock items with diverse data to exercise different paths
|
||||
for (let i = 0; i < itemCount; i++) {
|
||||
items.push({
|
||||
video: {
|
||||
id: `v${i}`,
|
||||
pubkey: `pubkey${i % 100}`,
|
||||
duration: 300 + (i % 600), // 5 to 15 minutes
|
||||
tags: [
|
||||
["t", "kids"],
|
||||
["t", "learning"],
|
||||
["t", i % 2 === 0 ? "preschool" : "science"],
|
||||
],
|
||||
viewCount: i * 10,
|
||||
created_at: Date.now() / 1000 - (i % 10000),
|
||||
moderation: { trustedCount: i % 5 },
|
||||
},
|
||||
metadata: {},
|
||||
});
|
||||
}
|
||||
|
||||
const context = {
|
||||
runtime: {
|
||||
ageGroup: "preschool",
|
||||
trustedAuthors: ["pubkey1", "pubkey2"],
|
||||
},
|
||||
addWhy: () => {}, // Mock addWhy
|
||||
};
|
||||
|
||||
const scorer = createKidsScorerStage();
|
||||
|
||||
console.log(`Starting kids scoring benchmark with ${itemCount} items...`);
|
||||
|
||||
// Warmup
|
||||
await scorer([...items.slice(0, 1000)], context);
|
||||
|
||||
const iterations = 100;
|
||||
let totalTime = 0;
|
||||
|
||||
for (let i = 0; i < iterations; i++) {
|
||||
// Reset metadata for each run to be cleaner
|
||||
items.forEach(item => item.metadata = {});
|
||||
|
||||
const start = performance.now();
|
||||
await scorer(items, context);
|
||||
const end = performance.now();
|
||||
totalTime += (end - start);
|
||||
|
||||
if (i % 5 === 0) process.stdout.write(".");
|
||||
}
|
||||
|
||||
const avgTime = totalTime / iterations;
|
||||
console.log(`\nAverage time per run: ${avgTime.toFixed(4)}ms`);
|
||||
}
|
||||
|
||||
runBenchmark().catch(console.error);
|
||||
@@ -391,27 +391,32 @@ export function createKidsScorerStage({
|
||||
const videoId = typeof video.id === "string" ? video.id : null;
|
||||
const pubkey = typeof video.pubkey === "string" ? video.pubkey : null;
|
||||
|
||||
const positiveComponents = [
|
||||
{ key: "age-appropriateness", value: ageAppropriateness },
|
||||
{ key: "educational-boost", value: educationalBoost },
|
||||
{ key: "author-trust", value: authorTrust },
|
||||
{ key: "popularity", value: popularityWithinKids },
|
||||
{ key: "freshness", value: freshness },
|
||||
];
|
||||
let maxKey = "age-appropriateness";
|
||||
let maxValue = ageAppropriateness;
|
||||
|
||||
let dominantPositive = positiveComponents[0];
|
||||
for (const component of positiveComponents) {
|
||||
if (component.value > dominantPositive.value) {
|
||||
dominantPositive = component;
|
||||
}
|
||||
if (educationalBoost > maxValue) {
|
||||
maxKey = "educational-boost";
|
||||
maxValue = educationalBoost;
|
||||
}
|
||||
if (authorTrust > maxValue) {
|
||||
maxKey = "author-trust";
|
||||
maxValue = authorTrust;
|
||||
}
|
||||
if (popularityWithinKids > maxValue) {
|
||||
maxKey = "popularity";
|
||||
maxValue = popularityWithinKids;
|
||||
}
|
||||
if (freshness > maxValue) {
|
||||
maxKey = "freshness";
|
||||
maxValue = freshness;
|
||||
}
|
||||
|
||||
if (dominantPositive.value > 0) {
|
||||
if (maxValue > 0) {
|
||||
context?.addWhy?.({
|
||||
stage: stageName,
|
||||
type: "score",
|
||||
reason: dominantPositive.key,
|
||||
value: dominantPositive.value,
|
||||
reason: maxKey,
|
||||
value: maxValue,
|
||||
score: kidsScore,
|
||||
videoId,
|
||||
pubkey,
|
||||
|
||||
@@ -0,0 +1,73 @@
|
||||
import test from "node:test";
|
||||
import assert from "node:assert/strict";
|
||||
import { createKidsScorerStage } from "../../js/feedEngine/kidsScoring.js";
|
||||
|
||||
test("kids scorer correctly identifies dominant positive component", async () => {
|
||||
const stage = createKidsScorerStage({
|
||||
weights: {
|
||||
w_age: 0.2,
|
||||
w_edu: 0.2,
|
||||
w_author: 0.2,
|
||||
w_pop: 0.2,
|
||||
w_fresh: 0.2,
|
||||
w_risk: 0
|
||||
}
|
||||
});
|
||||
|
||||
// Create an item where one component is clearly dominant
|
||||
// Age appropriateness: 1.0 (perfect duration + tags)
|
||||
// Others: 0
|
||||
const items = [
|
||||
{
|
||||
video: {
|
||||
id: "v1",
|
||||
pubkey: "pk1",
|
||||
duration: 300, // 5 min (perfect for toddler/preschool)
|
||||
tags: [["t", "preschool"], ["t", "learning"]], // Matches preferred
|
||||
created_at: Date.now() / 1000 - 10000000, // Old
|
||||
viewCount: 0
|
||||
},
|
||||
metadata: {},
|
||||
},
|
||||
];
|
||||
|
||||
const why = [];
|
||||
const context = {
|
||||
runtime: {
|
||||
ageGroup: "preschool",
|
||||
trustedAuthors: []
|
||||
},
|
||||
addWhy: (detail) => why.push(detail)
|
||||
};
|
||||
|
||||
await stage(items, context);
|
||||
|
||||
assert.equal(why.length, 1);
|
||||
assert.equal(why[0].reason, "age-appropriateness");
|
||||
assert.ok(why[0].value > 0);
|
||||
});
|
||||
|
||||
test("kids scorer picks educational-boost when dominant", async () => {
|
||||
const stage = createKidsScorerStage({
|
||||
educationalTags: ["math"],
|
||||
weights: { w_age: 0, w_edu: 1, w_author: 0, w_pop: 0, w_fresh: 0, w_risk: 0 }
|
||||
});
|
||||
|
||||
const items = [{
|
||||
video: {
|
||||
id: "v2",
|
||||
tags: [["t", "math"]],
|
||||
duration: 300
|
||||
},
|
||||
metadata: {}
|
||||
}];
|
||||
|
||||
const why = [];
|
||||
await stage(items, {
|
||||
runtime: { educationalTags: ["math"] },
|
||||
addWhy: (d) => why.push(d)
|
||||
});
|
||||
|
||||
assert.equal(why.length, 1);
|
||||
assert.equal(why[0].reason, "educational-boost");
|
||||
});
|
||||
Reference in new issue
Block a user