Skip to content
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

Best of hour performances * 10 #355

Merged
merged 5 commits into from
Mar 1, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -105,3 +105,4 @@ dist
docker-compose-personal.yml
client/public/index.html
client/public/variables.js
db_data
Original file line number Diff line number Diff line change
Expand Up @@ -33,23 +33,14 @@ function getElementName(
>["data"][number],
id: string,
) {
if ("tracks" in result) {
return result.tracks.find(t => t.track.id === id)?.track.name;
}
if ("albums" in result) {
return result.albums.find(t => t.album.id === id)?.album.name;
}
if ("artists" in result) {
return result.artists.find(t => t.artist.id === id)?.artist.name;
}
return "";
return result.full_items[id]?.name;
}

function getElementData(
result: UnboxPromise<ReturnType<(typeof elementToCall)[Element]>>["data"],
index: number,
) {
const foundIndex = result.findIndex(r => r._id === index);
const foundIndex = result.findIndex(r => r.hour === index);
if (foundIndex === -1) {
return { x: index };
}
Expand All @@ -61,34 +52,13 @@ function getElementData(

const { total } = found;

if ("tracks" in found) {
return found.tracks.reduce<StackedBarProps["data"][number]>(
(acc, curr) => {
acc[curr.track.id] = Math.floor((curr.count / total) * 1000) / 10;
return acc;
},
{ x: index },
);
}
if ("albums" in found) {
return found.albums.reduce<StackedBarProps["data"][number]>(
(acc, curr) => {
acc[curr.album.id] = Math.floor((curr.count / total) * 1000) / 10;
return acc;
},
{ x: index },
);
}
if ("artists" in found) {
return found.artists.reduce<StackedBarProps["data"][number]>(
(acc, curr) => {
acc[curr.artist.id] = Math.floor((curr.count / total) * 1000) / 10;
return acc;
},
{ x: index },
);
}
return { x: index };
return found.items.reduce<StackedBarProps["data"][number]>(
(acc, curr) => {
acc[curr.itemId] = Math.floor((curr.total / total) * 1000) / 10;
return acc;
},
{ x: index },
);
}

function formatX(value: any) {
Expand Down Expand Up @@ -116,7 +86,7 @@ export default function BestOfHour({ className }: BestOfHourProps) {

const tooltipValue = useCallback<ValueFormatter<typeof data>>(
(payload, value, root) => {
const foundIndex = result?.findIndex(r => r._id === payload.x);
const foundIndex = result?.findIndex(r => r.hour === payload.x);
if (!result || foundIndex === undefined || foundIndex === -1) {
return null;
}
Expand Down
1 change: 0 additions & 1 deletion apps/client/src/components/InlineArtist/InlineArtist.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,6 @@ export default function InlineArtist<T extends HTMLTag = "div">({
...other
}: InlineArtistProps<T>) {
return (
// eslint-disable-next-line react/jsx-props-no-spreading
<Text title={artist.name} {...other}>
<Link to={`/artist/${artist.id}`} className={s.root}>
{artist.name}
Expand Down
134 changes: 92 additions & 42 deletions apps/client/src/scenes/Benchmarks/Benchmarks.tsx
Original file line number Diff line number Diff line change
@@ -1,15 +1,13 @@
import { useSelector } from "react-redux";
import {
Button,
CircularProgress,
IconButton,
LinearProgress,
Table,
TableCell,
TableHead,
TableRow,
} from "@mui/material";
import { HourglassTop, PlayArrow } from "@mui/icons-material";
import { PlayArrow } from "@mui/icons-material";
import { useState } from "react";
import Header from "../../components/Header";
import {
Expand All @@ -19,12 +17,16 @@ import {
import { api } from "../../services/apis/api";
import { Timesplit } from "../../services/types";
import TitleCard from "../../components/TitleCard";
import Text from "../../components/Text";

type Request = {
id: string;
interface Request<T> {
title: string;
request: () => Promise<any>;
};
prepare?: () => Promise<T>;
request: (prepared: T) => Promise<any>;
}

const NOT_FINISHED_REQUEST = -1;
const FAILED_REQUEST = -2;

export default function Benchmarks() {
const { interval } = useSelector(selectRawIntervalDetail);
Expand All @@ -37,105 +39,144 @@ export default function Benchmarks() {
return null;
}

const requests: Request[] = [
const NB = 30;
const OFFSET = 0;

const requests = [
{
id: "getTracks",
title: "Get tracks",
request: () => api.getTracks(interval.start, interval.end, 20, 1),
request: () => api.getTracks(interval.start, interval.end, 20, OFFSET),
},
{
id: "getMostListened",
title: "Get most listened",
request: () =>
api.mostListened(interval.start, interval.end, Timesplit.all),
},
{
id: "getMostListenedArtists",
title: "Get most listened artists",
request: () =>
api.mostListenedArtist(interval.start, interval.end, Timesplit.all),
},
{
id: "getSongsPer",
title: "Get songs per",
request: () => api.songsPer(interval.start, interval.end, Timesplit.all),
},
{
id: "getTimePer",
title: "Get time per",
request: () => api.timePer(interval.start, interval.end, Timesplit.all),
},
{
id: "getFeatRatio",
title: "Get feat ratio",
request: () => api.featRatio(interval.start, interval.end, Timesplit.all),
},
{
id: "getAlbumDateRatio",
title: "Get album date ratio",
request: () =>
api.albumDateRatio(interval.start, interval.end, Timesplit.all),
},
{
id: "getPopularityPer",
title: "Get popularity per",
request: () =>
api.popularityPer(interval.start, interval.end, Timesplit.all),
},
{
id: "getDifferentArtistsPer",
title: "Get different artists per",
request: () =>
api.differentArtistsPer(interval.start, interval.end, Timesplit.all),
},
{
id: "getTimePerHourOfDay",
title: "Get time per hour of day",
request: () => api.timePerHourOfDay(interval.start, interval.end),
},
{
id: "getBestSongs",
title: "Get best songs",
request: () => api.getBestSongs(interval.start, interval.end, 30, 1),
request: () => api.getBestSongs(interval.start, interval.end, NB, OFFSET),
},
{
id: "getBestArtists",
title: "Get best artists",
request: () => api.getBestArtists(interval.start, interval.end, 30, 1),
request: () =>
api.getBestArtists(interval.start, interval.end, NB, OFFSET),
},
{
id: "getBestAlbums",
title: "Get best albums",
request: () => api.getBestAlbums(interval.start, interval.end, 30, 1),
request: () =>
api.getBestAlbums(interval.start, interval.end, NB, OFFSET),
},
{
id: "getBestSongsOfHour",
title: "Get best songs of hour",
request: () => api.getBestSongsOfHour(interval.start, interval.end),
},
{
id: "getBestAlbumsOfHour",
title: "Get best albums of hour",
request: () => api.getBestAlbumsOfHour(interval.start, interval.end),
},
{
id: "getBestArtistsOfHour",
title: "Get best artists of hour",
request: () => api.getBestArtistsOfHour(interval.start, interval.end),
},
{
id: "getLongestSessions",
title: "Get longest sessions",
request: () => api.getLongestSessions(interval.start, interval.end),
},
];
{
title: "Get artist page",
prepare: async () => {
const { data: bestArtists } = await api.getBestArtists(
interval.start,
interval.end,
1,
0,
);
const [bestArtist] = bestArtists;
return bestArtist?.artist.id;
},
request: async (bestArtistId: string) => api.getArtistStats(bestArtistId),
},
{
title: "Get album page",
prepare: async () => {
const { data: bestAlbums } = await api.getBestAlbums(
interval.start,
interval.end,
1,
0,
);
const [bestAlbum] = bestAlbums;
return bestAlbum?.album.id;
},
request: async (bestAlbumId: string) => api.getAlbumStats(bestAlbumId),
},
{
title: "Get track page",
prepare: async () => {
const { data: bestTracks } = await api.getBestSongs(
interval.start,
interval.end,
1,
0,
);
const [bestTrack] = bestTracks;
return bestTrack?.track.id;
},
request: async (bestTrackId: string) => api.getTrackStats(bestTrackId),
},
] as const satisfies Request<any>[];

const run = async (req: Request) => {
setElapsedTime(prev => ({ ...prev, [req.id]: -1 }));
const start = Date.now();
await req.request();
const run = async (req: Request<any>) => {
setElapsedTime(prev => ({ ...prev, [req.title]: NOT_FINISHED_REQUEST }));
let prepared = undefined;
if (req.prepare) {
prepared = await req.prepare();
}
if (!prepared && req.prepare) {
setElapsedTime(prev => ({ ...prev, [req.title]: FAILED_REQUEST }));
return;
}
let start = Date.now();
const { data: result } = await req.request(prepared);
console.log("Result", result);
const end = Date.now();
setElapsedTime(prev => ({ ...prev, [req.id]: end - start }));
setElapsedTime(prev => ({ ...prev, [req.title]: end - start }));
};

const runAll = async () => {
Expand All @@ -151,7 +192,11 @@ export default function Benchmarks() {
<Header title="Benchmarks" subtitle="Analyze server queries time" />
<TitleCard
title="Benchmarks"
right={<Button onClick={runAll}>Run All</Button>}>
right={
<Button variant="contained" onClick={runAll}>
Run All
</Button>
}>
<Table>
<TableHead>
<TableCell>Request</TableCell>
Expand All @@ -165,18 +210,23 @@ export default function Benchmarks() {
</TableHead>
{requests.map(req => {
let elapsed;
if (elapsedTime[req.id] === -1) {
const requestTimeElapsed = elapsedTime[req.title];
if (requestTimeElapsed === NOT_FINISHED_REQUEST) {
elapsed = <i>Loading...</i>;
} else if (elapsedTime[req.id]) {
elapsed = `${elapsedTime[req.id]}ms`;
} else if (requestTimeElapsed === FAILED_REQUEST) {
elapsed = <i>Failed</i>;
} else if (requestTimeElapsed) {
elapsed = `${requestTimeElapsed}ms`;
}

return (
<TableRow>
<TableRow key={req.title}>
<TableCell component="th" scope="row">
{req.title}
<Text>{req.title}</Text>
</TableCell>
<TableCell align="right">
<Text>{elapsed}</Text>
</TableCell>
<TableCell align="right">{elapsed}</TableCell>
<TableCell
padding="none"
align="right"
Expand Down
Loading