performance improvement

This commit is contained in:
hzrd149
2023-09-09 11:58:58 -05:00
parent 57e5229db3
commit 4bd6f3311a
3 changed files with 72 additions and 54 deletions

View File

@@ -5,9 +5,11 @@ export type MenuIconButtonProps = IconButtonProps & {
children: MenuListProps["children"]; children: MenuListProps["children"];
}; };
export const MenuIconButton = ({ children, ...props }: MenuIconButtonProps) => ( export function MenuIconButton({ children, ...props }: MenuIconButtonProps) {
<Menu isLazy> return (
<MenuButton as={IconButton} icon={<MoreIcon />} {...props} /> <Menu isLazy>
<MenuList>{children}</MenuList> <MenuButton as={IconButton} icon={<MoreIcon />} {...props} />
</Menu> <MenuList>{children}</MenuList>
); </Menu>
);
}

View File

@@ -1,4 +1,4 @@
import React from "react"; import { ReactNode, memo } from "react";
import { Text } from "@chakra-ui/react"; import { Text } from "@chakra-ui/react";
import { Kind } from "nostr-tools"; import { Kind } from "nostr-tools";
@@ -16,36 +16,44 @@ import EmbeddedArticle from "../../embed-event/event-types/embedded-article";
import { isReply } from "../../../helpers/nostr/events"; import { isReply } from "../../../helpers/nostr/events";
import ReplyNote from "./reply-note"; import ReplyNote from "./reply-note";
const RenderEvent = React.memo(({ event }: { event: NostrEvent }) => { function RenderEvent({ event }: { event: NostrEvent }) {
let content: ReactNode | null = null;
switch (event.kind) { switch (event.kind) {
case Kind.Text: case Kind.Text:
return isReply(event) ? <ReplyNote event={event} /> : <Note event={event} showReplyButton />; content = isReply(event) ? <ReplyNote event={event} /> : <Note event={event} showReplyButton />;
break;
case Kind.Repost: case Kind.Repost:
return <RepostNote event={event} />; content = <RepostNote event={event} />;
break;
case Kind.Article: case Kind.Article:
return <EmbeddedArticle article={event} />; content = <EmbeddedArticle article={event} />;
break;
case STREAM_KIND: case STREAM_KIND:
return <StreamNote event={event} />; content = <StreamNote event={event} />;
break;
case 2: case 2:
const safeUrl = safeRelayUrl(event.content); const safeUrl = safeRelayUrl(event.content);
return safeUrl ? <RelayCard url={safeUrl} /> : null; content = safeUrl ? <RelayCard url={safeUrl} /> : null;
break;
default: default:
return <Text>Unknown event kind: {event.kind}</Text>; content = <Text>Unknown event kind: {event.kind}</Text>;
break;
} }
});
const GenericNoteTimeline = React.memo(({ timeline }: { timeline: TimelineLoader }) => { return content && <ErrorBoundary>{content}</ErrorBoundary>;
}
const RenderEventMemo = memo(RenderEvent);
function GenericNoteTimeline({ timeline }: { timeline: TimelineLoader }) {
const notes = useSubject(timeline.timeline); const notes = useSubject(timeline.timeline);
return ( return (
<> <>
{notes.map((note) => ( {notes.map((note) => (
<ErrorBoundary key={note.id}> <RenderEventMemo key={note.id} event={note} />
<RenderEvent event={note} />
</ErrorBoundary>
))} ))}
</> </>
); );
}); }
export default GenericNoteTimeline; export default memo(GenericNoteTimeline);

View File

@@ -72,20 +72,26 @@ class TimeMeasure implements RelayMeasure, PersistentMeasure {
} }
addTime(time: number, date: Date = new Date()) { addTime(time: number, date: Date = new Date()) {
this.measures.unshift([time, date]); this.measures.unshift([time, date]);
this.averageCache = null;
} }
getCount(since?: Date) { getCount() {
const points = since ? this.measures.filter((m) => m[1] > since) : this.measures; return this.measures.length;
return points.length;
} }
getAverage(since?: Date, undef: number = Infinity) {
const points = since ? this.measures.filter((m) => m[1] > since) : this.measures; /** cache the average since it gets called a lot */
if (points.length === 0) return undef; private averageCache: number | null = null;
const total = points.reduce((total, [time]) => total + time, 0); getAverage(undef: number = Infinity) {
return total / points.length; if (this.measures.length === 0) return undef;
if (this.averageCache !== null) {
const total = this.measures.reduce((total, [time]) => total + time, 0);
this.averageCache = total / this.measures.length;
}
return this.averageCache;
} }
reset() { reset() {
this.measures = []; this.measures = [];
this.averageCache = null;
return this; return this;
} }
prune(cutOff: Date): this { prune(cutOff: Date): this {
@@ -94,6 +100,7 @@ class TimeMeasure implements RelayMeasure, PersistentMeasure {
if (!last) break; if (!last) break;
if (last[1] >= cutOff) { if (last[1] >= cutOff) {
this.measures.push(last); this.measures.push(last);
this.averageCache = null;
break; break;
} }
} }
@@ -103,6 +110,7 @@ class TimeMeasure implements RelayMeasure, PersistentMeasure {
load(data: any) { load(data: any) {
if (!Array.isArray(data)) return this; if (!Array.isArray(data)) return this;
this.measures = data; this.measures = data;
this.averageCache = null;
return this; return this;
} }
save() { save() {
@@ -128,25 +136,25 @@ class RelayScoreboardService {
// for (const [relay, measure] of this.relayTimeouts) measure.prune(cutOff); // for (const [relay, measure] of this.relayTimeouts) measure.prune(cutOff);
} }
getAverageResponseTime(relay: string, since?: Date) { getAverageResponseTime(relay: string) {
return this.relayResponseTimes.get(relay).getAverage(since); return this.relayResponseTimes.get(relay).getAverage();
} }
getAverageEjectTime(relay: string, since?: Date) { getAverageEjectTime(relay: string) {
return this.relayEjectTime.get(relay).getAverage(since); return this.relayEjectTime.get(relay).getAverage();
} }
getAverageConnectionTime(relay: string, since?: Date) { getAverageConnectionTime(relay: string) {
return this.relayConnectionTime.get(relay).getAverage(since); return this.relayConnectionTime.get(relay).getAverage();
} }
// getTimeoutCount(relay: string, since?: Date) { // getTimeoutCount(relay: string) {
// return this.relayTimeouts.get(relay).getCount(since); // return this.relayTimeouts.get(relay).getCount();
// } // }
hasConnected(relay: string, since?: Date) { hasConnected(relay: string) {
return this.relayConnectionTime.get(relay).getCount(since) > 0; return this.relayConnectionTime.get(relay).getCount() > 0;
} }
getResponseTimeScore(relay: string, since?: Date) { getResponseTimeScore(relay: string) {
const responseTime = this.getAverageResponseTime(relay, since); const responseTime = this.getAverageResponseTime(relay);
const connected = this.hasConnected(relay, since); const connected = this.hasConnected(relay);
// no points if we have never connected // no points if we have never connected
if (!connected) return 0; if (!connected) return 0;
@@ -154,8 +162,8 @@ class RelayScoreboardService {
// 1 point (max 10) for ever 10 ms under 1000. negative points for over 1000 // 1 point (max 10) for ever 10 ms under 1000. negative points for over 1000
return clamp(Math.round(-(responseTime - 1000) / 100), -10, 10); return clamp(Math.round(-(responseTime - 1000) / 100), -10, 10);
} }
getConnectionTimeScore(relay: string, since?: Date) { getConnectionTimeScore(relay: string) {
const connectionTime = this.getAverageConnectionTime(relay, since); const connectionTime = this.getAverageConnectionTime(relay);
// no points if we have never connected // no points if we have never connected
if (connectionTime === Infinity) return 0; if (connectionTime === Infinity) return 0;
@@ -163,9 +171,9 @@ class RelayScoreboardService {
// 1 point (max 10) for ever 10 ms under 1000. negative points for over 1000 // 1 point (max 10) for ever 10 ms under 1000. negative points for over 1000
return clamp(Math.round(-(connectionTime - 1000) / 100), -10, 10); return clamp(Math.round(-(connectionTime - 1000) / 100), -10, 10);
} }
getEjectTimeScore(relay: string, since?: Date) { getEjectTimeScore(relay: string) {
const ejectTime = this.getAverageEjectTime(relay, since); const ejectTime = this.getAverageEjectTime(relay);
const connected = this.hasConnected(relay, since); const connected = this.hasConnected(relay);
// no points if we have never connected // no points if we have never connected
if (!connected) return 0; if (!connected) return 0;
@@ -177,18 +185,18 @@ class RelayScoreboardService {
if (ejectTime > 1000 * 200) score += 5; if (ejectTime > 1000 * 200) score += 5;
return score; return score;
} }
// getTimeoutsScore(relay: string, since?: Date) { // getTimeoutsScore(relay: string) {
// const timeouts = this.getTimeoutCount(relay, since); // const timeouts = this.getTimeoutCount(relay);
// // subtract 5 points for ever time its timed out // // subtract 5 points for ever time its timed out
// return -(timeouts * 5); // return -(timeouts * 5);
// } // }
getRelayScore(relay: string, since?: Date) { getRelayScore(relay: string) {
let score = 0; let score = 0;
score += this.getResponseTimeScore(relay, since); score += this.getResponseTimeScore(relay);
score += this.getConnectionTimeScore(relay, since); score += this.getConnectionTimeScore(relay);
score += this.getEjectTimeScore(relay, since); score += this.getEjectTimeScore(relay);
// score += this.getTimeoutsScore(relay, since); // score += this.getTimeoutsScore(relay);
return score; return score;
} }