const { MatrixClient } = require("matrix-bot-sdk"); /** * This is a test for the response times for various endpoints querying the * members in a room so that they can be banned. * * Below are some results from MatrixHQ using a home connection with only 26Mbps down. * Which is probably a major limiting factor of these results given the size just encoding the usernames * in MatrixHQ alone. * * /joined_members: total time elapsed 29.655seconds, mean time 5931ms, median time 4744ms * /state: total time elapsed 141.353seconds, mean time 28270.6ms, median time 23354ms * /members: total time elapsed 164.845seconds, mean time 32969ms, median time 28258ms * * To run the script use `yarn ts-node -P tsconfig.json test/scripts/memberQueryTest.ts`. */ // const accessToken = "redacted"; const client = new MatrixClient("https://matrix-client.matrix.org", accessToken); const roomId = "!OGEhHVWSdvArJzumhm:matrix.org"; enum MemberFetchMethod { JoinedMembers = "/joined_members", Members = "/members", State = "/state", } const shuffledMethods = [MemberFetchMethod.JoinedMembers, MemberFetchMethod.Members, MemberFetchMethod.State] .reduce((acc: MemberFetchMethod[], method: MemberFetchMethod) => { return [...acc, ...[...Array(5)].map(_ => method)] }, []); // shuffle https://stackoverflow.com/a/12646864 for (let i = shuffledMethods.length - 1; i > 0; i--) { const j = Math.floor(Math.random() * (i + 1)); [shuffledMethods[i], shuffledMethods[j]] = [shuffledMethods[j], shuffledMethods[i]]; } async function fetchStateWithMethod(method: MemberFetchMethod) { switch (method) { case MemberFetchMethod.JoinedMembers: return await client.getJoinedRoomMembers(roomId); case MemberFetchMethod.Members: return await client.getRoomMembers(roomId, undefined, undefined, ['leave', 'ban']); case MemberFetchMethod.State: return await client.getRoomState(roomId); default: throw new TypeError(); } } const times = new Map([ [MemberFetchMethod.JoinedMembers, []], [MemberFetchMethod.Members, []], [MemberFetchMethod.State, []] ]); function addTime(method: MemberFetchMethod, time: number) { const entry = times.get(method); if (entry === undefined) { throw new TypeError() } entry.push(time); } function getTimes(method: MemberFetchMethod) { return times.get(method); } // https://stackoverflow.com/a/70806192 function calculateMedian (arr: number[]): number | undefined { if (!arr.length) return undefined; const s = [...arr].sort((a, b) => a - b); const mid = Math.floor(s.length / 2); return s.length % 2 === 0 ? ((s[mid - 1] + s[mid]) / 2) : s[mid]; }; (async () => { for (const method of shuffledMethods) { const start = Date.now(); await fetchStateWithMethod(method); const elapsedMs = Date.now() - start; addTime(method, elapsedMs); } for (const method of [MemberFetchMethod.JoinedMembers, MemberFetchMethod.Members, MemberFetchMethod.State]) { const times = getTimes(method)!; const sum = times.reduce((a, b) => a + b, 0); const mean = (sum / times.length) || 0; const median = calculateMedian(times); console.log(`${method}: total time elapsed ${sum / 1000}seconds, mean time ${mean}ms, median time ${median}ms`); } })();