From f0740cb6cab4705629eca9bf3d7d5b249d187224 Mon Sep 17 00:00:00 2001 From: Kieran Date: Wed, 14 Jun 2023 02:00:14 +0100 Subject: [PATCH] optimize performance --- packages/app/src/Feed/TimelineFeed.ts | 67 ++++++++++---------------- packages/system/src/Query.ts | 11 +++-- packages/system/src/RequestBuilder.ts | 8 +-- packages/system/src/RequestSplitter.ts | 14 +++--- packages/system/src/Utils.ts | 10 ++++ 5 files changed, 56 insertions(+), 54 deletions(-) diff --git a/packages/app/src/Feed/TimelineFeed.ts b/packages/app/src/Feed/TimelineFeed.ts index c08badba..e9ceb7f3 100644 --- a/packages/app/src/Feed/TimelineFeed.ts +++ b/packages/app/src/Feed/TimelineFeed.ts @@ -26,8 +26,6 @@ export default function useTimelineFeed(subject: TimelineSubject, options: Timel window: options.window, now: options.now ?? unixNow(), }); - const [trackingEvents, setTrackingEvent] = useState([]); - const [trackingParentEvents, setTrackingParentEvents] = useState([]); const pref = useLogin().preferences; const createBuilder = useCallback(() => { @@ -132,34 +130,8 @@ export default function useTimelineFeed(subject: TimelineSubject, options: Timel latest.clear(); }, [options.relay]); - const subNext = useMemo(() => { - const rb = new RequestBuilder(`timeline-related:${subject.type}:${subject.discriminator}`); - if (trackingEvents.length > 0) { - rb.withFilter() - .kinds( - pref.enableReactions - ? [EventKind.Reaction, EventKind.Repost, EventKind.ZapReceipt] - : [EventKind.ZapReceipt, EventKind.Repost] - ) - .tag("e", trackingEvents); - } - if (trackingParentEvents.length > 0) { - rb.withFilter().ids(trackingParentEvents); - } - return rb.numFilters > 0 ? rb : null; - }, [trackingEvents, pref, subject.type]); - - const related = useRequestBuilder(FlatNoteStore, subNext); - - useEffect(() => { - if (main.data && main.data.length > 0) { - setTrackingEvent(s => { - const ids = (main.data ?? []).map(a => a.id); - if (ids.some(a => !s.includes(a))) { - return Array.from(new Set([...s, ...ids])); - } - return s; - }); + function getParentEvents() { + if (main.data) { const repostsByKind6 = main.data .filter(a => a.kind === EventKind.Repost && a.content === "") .map(a => a.tags.find(b => b[0] === "e")) @@ -172,18 +144,31 @@ export default function useTimelineFeed(subject: TimelineSubject, options: Timel .map(a => a.tags.find(tagFilterOfTextRepost(a))) .filter(a => a) .map(a => unwrap(a)[1]); - const reposts = [...repostsByKind6, ...repostsByKind1]; - if (reposts.length > 0) { - setTrackingParentEvents(s => { - if (reposts.some(a => !s.includes(a))) { - const temp = new Set([...s, ...reposts]); - return Array.from(temp); - } - return s; - }); - } + return [...repostsByKind6, ...repostsByKind1]; } - }, [main]); + return []; + } + + const subNext = useMemo(() => { + const rb = new RequestBuilder(`timeline-related:${subject.type}:${subject.discriminator}`); + const trackingEvents = main.data?.map(a => a.id) ?? []; + if (trackingEvents.length > 0) { + rb.withFilter() + .kinds( + pref.enableReactions + ? [EventKind.Reaction, EventKind.Repost, EventKind.ZapReceipt] + : [EventKind.ZapReceipt, EventKind.Repost] + ) + .tag("e", trackingEvents); + } + const trackingParentEvents = getParentEvents(); + if (trackingParentEvents.length > 0) { + rb.withFilter().ids(trackingParentEvents); + } + return rb.numFilters > 0 ? rb : null; + }, [main.data, pref, subject.type]); + + const related = useRequestBuilder(FlatNoteStore, subNext); return { main: main.data, diff --git a/packages/system/src/Query.ts b/packages/system/src/Query.ts index 20ce8070..d7849654 100644 --- a/packages/system/src/Query.ts +++ b/packages/system/src/Query.ts @@ -1,7 +1,7 @@ import { v4 as uuid } from "uuid"; import debug from "debug"; import { Connection, ReqFilter, Nips, TaggedRawEvent } from "."; -import { unixNowMs, unwrap } from "./Utils"; +import { reqFilterEq, unixNowMs, unwrap } from "./Utils"; import { NoteStore } from "./NoteCollection"; import { flatMerge } from "./RequestMerger"; import { BuiltRawReqFilter } from "./RequestBuilder"; @@ -46,7 +46,6 @@ class QueryTrace { forceEose() { this.eose = unixNowMs(); this.#wasForceClosed = true; - this.#fnProgress(); this.sendClose(); } @@ -163,7 +162,13 @@ export class Query implements QueryBase { } get flatFilters() { - return this.#tracing.flatMap(a => a.filters).flatMap(expandFilter); + const f: Array = []; + for (const x of this.#tracing.flatMap(a => a.filters)) { + if (!f.some(a => reqFilterEq(a, x))) { + f.push(x); + } + } + return f.flatMap(expandFilter); } get feed() { diff --git a/packages/system/src/RequestBuilder.ts b/packages/system/src/RequestBuilder.ts index 0bc23a53..84ff6043 100644 --- a/packages/system/src/RequestBuilder.ts +++ b/packages/system/src/RequestBuilder.ts @@ -96,11 +96,11 @@ export class RequestBuilder { /** * Detects a change in request from a previous set of filters */ - buildDiff(relays: RelayCache, filters: Array): Array { + buildDiff(relays: RelayCache, prev: Array): Array { const start = unixNowMs(); - const next = this.#builders.flatMap(f => expandFilter(f.filter)) - const diff = diffFilters(filters, next); + const next = this.#builders.flatMap(f => expandFilter(f.filter)); + const diff = diffFilters(prev, next); const ts = (unixNowMs() - start); this.#log("buildDiff %s %d ms", this.id, ts); if (diff.changed) { @@ -205,7 +205,7 @@ export class RequestFilterBuilder { tag(key: "e" | "p" | "d" | "t" | "r", value?: Array) { if (!value) return this; - this.#filter[`#${key}`] = value; + this.#filter[`#${key}`] = appendDedupe(this.#filter[`#${key}`], value); return this; } diff --git a/packages/system/src/RequestSplitter.ts b/packages/system/src/RequestSplitter.ts index 8863776b..d3cee5c3 100644 --- a/packages/system/src/RequestSplitter.ts +++ b/packages/system/src/RequestSplitter.ts @@ -6,21 +6,23 @@ export function diffFilters(prev: Array, next: Array flatFilterEq(a, next[x])); + prev = [...prev]; + next = [...next]; + for (const n of next) { + const px = prev.findIndex(a => flatFilterEq(a, n)); if (px !== -1) { prev.splice(px, 1); } else { - added.push(next[x]); + added.push(n); } } if (calcRemoved) { - for (let x = 0; x < prev.length; x++) { - const px = next.findIndex(a => flatFilterEq(a, prev[x])); + for (const p of prev) { + const px = next.findIndex(a => flatFilterEq(a, p)); if (px !== -1) { next.splice(px, 1); } else { - removed.push(prev[x]); + removed.push(p); } } } diff --git a/packages/system/src/Utils.ts b/packages/system/src/Utils.ts index 485888f3..68082c65 100644 --- a/packages/system/src/Utils.ts +++ b/packages/system/src/Utils.ts @@ -86,6 +86,16 @@ export function flatFilterEq(a: FlatReqFilter, b: FlatReqFilter): boolean { && a["#r"] === b["#r"]; } +export function countMembers(a: any) { + let ret = 0; + for (const [k, v] of Object.entries(a)) { + if (Array.isArray(v)) { + ret += v.length; + } + } + return ret; +} + export function equalProp(a: string | number | Array | undefined, b: string | number | Array | undefined) { if ((a !== undefined && b === undefined) || (a === undefined && b !== undefined)) { return false;