latency-test.ts 3.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687
  1. // NOTE:
  2. // - requires the env vars HTTP_PORT and AUTH_TOKENS (at least 1 token to bypass rate limiting) to be set
  3. // - requires geniURL to run in a different process (or using the command pnpm run latency-test)
  4. //
  5. // - requests are sent sequentially on purpose to avoid rate limiting on genius.com's side
  6. import "dotenv/config";
  7. import _axios from "axios";
  8. import percentile from "percentile";
  9. import k from "kleur";
  10. import type { Stringifiable } from "svcorelib";
  11. import queries from "./latency-test-queries.json" with { type: "json" };
  12. const settings = {
  13. /** Amount of requests to send in total. */
  14. amount: 10,
  15. /** Base URL to send requests to. `{{QUERY}}` will be replaced with a random query from the `latency-test-queries.json` file. */
  16. url: `http://127.0.0.1:${process.env.HTTP_PORT ?? 8074}/v2/search/top?q={{QUERY}}`,
  17. /** Whether to log all requests to the console. */
  18. logRequests: true,
  19. };
  20. const axios = _axios.create({ timeout: 20_000 });
  21. async function run() {
  22. console.log(`\n\n>>> Running latency test with ${settings.amount} requests...\n`);
  23. const startTs = Date.now();
  24. const times = [] as number[];
  25. for(let i = 0; i < settings.amount; i++) {
  26. i === 0 && console.log(`> Sent 0 of ${settings.amount} requests`);
  27. const start = Date.now();
  28. try {
  29. const url = settings.url.replace("{{QUERY}}", queries[Math.floor(Math.random() * queries.length)]);
  30. settings.logRequests && console.log(" *", url);
  31. await axios.get(url, {
  32. headers: {
  33. "Cache-Control": "no-cache",
  34. Authorization: `Bearer ${process.env.AUTH_TOKENS!.split(",")[0]}`,
  35. },
  36. });
  37. }
  38. catch(e) {
  39. console.error("Failed to send request:", e);
  40. }
  41. finally {
  42. times.push(Date.now() - start);
  43. i % 10 === 0 && i !== 0 && console.log(`> Sent ${i} of ${settings.amount} requests`);
  44. }
  45. }
  46. const min = times.reduce((a, c) => Math.min(a, c), Infinity).toFixed(0);
  47. const avg = (times.reduce((a, c) => a + c, 0) / times.length).toFixed(0);
  48. const max = times.reduce((a, c) => Math.max(a, c), 0).toFixed(0);
  49. const getPerc = (perc: number, times: number[]) => {
  50. const res = percentile(perc, times);
  51. if(Array.isArray(res)) return res[0];
  52. return res;
  53. };
  54. const logVal = (label: string, value: Stringifiable, kleurFunc?: (str: string) => void) => {
  55. const valStr = `${label}:\t${String(value).padStart(4, " ")} ms`;
  56. console.log(kleurFunc ? kleurFunc(valStr) : valStr);
  57. }
  58. console.log(`\n>>> Latency test finished sending all ${settings.amount} requests after ${((Date.now() - startTs) / 1000).toFixed(2)}s - Results:`);
  59. console.log();
  60. logVal("5th%", getPerc(5, times), k.gray);
  61. logVal("10th%", getPerc(10, times), k.gray);
  62. logVal("25th%", getPerc(25, times), k.gray);
  63. logVal("80th%", getPerc(80, times));
  64. logVal("90th%", getPerc(90, times));
  65. logVal("95th%", getPerc(95, times));
  66. logVal("97th%", getPerc(97, times), k.bold);
  67. logVal("98th%", getPerc(98, times));
  68. logVal("99th%", getPerc(99, times));
  69. console.log();
  70. logVal("min", min);
  71. logVal("avg", avg, k.bold);
  72. logVal("max", max);
  73. console.log();
  74. }
  75. run();