276 lines
15 KiB
TypeScript
276 lines
15 KiB
TypeScript
import {
|
|
Stack,
|
|
Group,
|
|
Card,
|
|
Accordion,
|
|
Text,
|
|
Table,
|
|
RingProgress,
|
|
ScrollArea,
|
|
Space
|
|
} from "@mantine/core";
|
|
import {marginTopBottom} from "~/styles.ts";
|
|
import {PerformanceTestFilter} from "~/components/subs/PerformanceTestFilter.tsx";
|
|
import { ResponsiveTableContainer } from "~/components/subs/ResponsiveTableContainer";
|
|
import React, {useEffect, useRef, useState} from "react";
|
|
import type {BookInfo, PerformanceGetListData} from "~/utils/models.ts";
|
|
import { proxy, useSnapshot } from 'valtio';
|
|
import {convertNumber, showErrorMessage, sleep} from "~/utils/utils.ts";
|
|
import {apiPerformanceGetList, apiPerformanceUploadData} from "~/utils/compare_api.ts";
|
|
import Charts from "~/components/Charts.tsx";
|
|
import {getTestExampleData, pushTestExampleData} from "~/exapleData.ts";
|
|
import {BookTable} from "~/components/subs/BookInfoTable.tsx";
|
|
import {confirmExportData} from "~/components/subs/confirms.tsx";
|
|
|
|
// const performanceDataState = proxy<PerformanceGetListData[]>([]);
|
|
|
|
export default function Component({isPushTest, performanceDataState}: { isPushTest: boolean, performanceDataState: PerformanceGetListData[] }) {
|
|
const [startsCount, setStartsCount] = useState(200)
|
|
const [endsCount, setEndsCount] = useState(100000)
|
|
const [addCount, setAddCount] = useState(200)
|
|
const [avgCount, setAvgCount] = useState(3)
|
|
const [maxExampleCount, setMaxExampleCount] = useState(30)
|
|
|
|
const [isStarting, setIsStarting] = useState(false)
|
|
const [requestStopping, setRequestStopping] = useState(false)
|
|
const requestStoppingRef = useRef(requestStopping);
|
|
requestStoppingRef.current = requestStopping;
|
|
|
|
const [currentCount, setCurrentCount] = useState(0)
|
|
const [currentIdx, setCurrentIdx] = useState(0)
|
|
const [currentAvgCount, setCurrentAvgCount] = useState(0)
|
|
|
|
const [hideServerDeserialize, setHideServerDeserialize] = useState(!isPushTest)
|
|
const [hideServerSerialize, setHideServerSerialize] = useState(isPushTest)
|
|
const [chartsSize, setChartsSize] = useState(6)
|
|
|
|
const performanceDataSnap = useSnapshot(performanceDataState);
|
|
|
|
useEffect(() => {
|
|
getExampleData()
|
|
}, [])
|
|
|
|
const exportData = () => {
|
|
if (!performanceDataSnap) return
|
|
confirmExportData(performanceDataSnap as PerformanceGetListData[], isPushTest ? "performance_test_push_data" : "performance_test_get_list_data")
|
|
}
|
|
|
|
const updateFilter = (startsCount: number, endsCount: number, addCount: number, avgCount: number, maxExampleCount: number, hideServerDeserialize: boolean, hideServerSerialize: boolean, chartsSize: number) => {
|
|
setStartsCount(startsCount);
|
|
setEndsCount(endsCount);
|
|
setAddCount(addCount);
|
|
setAvgCount(avgCount);
|
|
setMaxExampleCount(maxExampleCount);
|
|
setHideServerDeserialize(hideServerDeserialize);
|
|
setHideServerSerialize(hideServerSerialize);
|
|
setChartsSize(chartsSize);
|
|
}
|
|
|
|
const onClickStart = () => {
|
|
StartTest()
|
|
.finally(() => setIsStarting(false))
|
|
}
|
|
|
|
const OnClickStop = () => {
|
|
if (!isStarting) return
|
|
setRequestStopping(true)
|
|
}
|
|
|
|
const getCurrentSingleStep = (queryIdx: number | undefined) => {
|
|
if (!isStarting) return queryIdx;
|
|
if (queryIdx !== currentIdx) return queryIdx;
|
|
let value = currentAvgCount / avgCount * 100;
|
|
return <RingProgress
|
|
sections={[{ value, color: 'blue' }]}
|
|
transitionDuration={250}
|
|
label={<Text ta="center">{currentAvgCount} / {avgCount}</Text>}
|
|
/>
|
|
|
|
}
|
|
|
|
const getExampleData = () => {
|
|
performanceDataState.splice(0);
|
|
let exampleData = isPushTest ? pushTestExampleData : getTestExampleData
|
|
for (let i = 0; i < exampleData.length; i++) {
|
|
// @ts-ignore
|
|
performanceDataState.push(exampleData[i])
|
|
}
|
|
}
|
|
|
|
const StartTest = async () => {
|
|
setIsStarting(true)
|
|
setRequestStopping(false)
|
|
|
|
if (addCount <= 0) {
|
|
showErrorMessage("Step Count must be greater than 0", "Invalid Step Count");
|
|
return;
|
|
}
|
|
|
|
if (startsCount > endsCount) {
|
|
showErrorMessage("Starts Count can not be greater than Ends Count", "Invalid Starts Count");
|
|
return;
|
|
}
|
|
|
|
let currentForCount = startsCount;
|
|
let idx = 0;
|
|
performanceDataState.splice(0);
|
|
|
|
while (true) {
|
|
setCurrentCount(currentForCount);
|
|
setCurrentIdx(idx)
|
|
|
|
for (let i = 0; i < avgCount; i++) {
|
|
try {
|
|
if (requestStoppingRef.current) {
|
|
setRequestStopping(false)
|
|
return
|
|
}
|
|
|
|
let response = isPushTest ?
|
|
await apiPerformanceUploadData(currentForCount, idx) :
|
|
await apiPerformanceGetList(currentForCount, maxExampleCount, idx)
|
|
|
|
if (response.success && response.data) {
|
|
const checkLastIndex = performanceDataState.length - 1
|
|
if (performanceDataState.length > 0 && performanceDataState[checkLastIndex].idx === response.data.idx) {
|
|
const lastData = performanceDataState[checkLastIndex]
|
|
performanceDataState[checkLastIndex].grpc.client_networking_ping = (lastData.grpc.client_networking_ping + response.data.grpc.client_networking_ping) / 2;
|
|
performanceDataState[checkLastIndex].grpc.client_request_cpu = (lastData.grpc.client_request_cpu + response.data.grpc.client_request_cpu) / 2;
|
|
performanceDataState[checkLastIndex].grpc.client_request_time = (lastData.grpc.client_request_time + response.data.grpc.client_request_time) / 2;
|
|
performanceDataState[checkLastIndex].grpc.networking_size.request_size = (lastData.grpc.networking_size.request_size + response.data.grpc.networking_size.request_size) / 2;
|
|
performanceDataState[checkLastIndex].grpc.networking_size.response_size = (lastData.grpc.networking_size.response_size + response.data.grpc.networking_size.response_size) / 2;
|
|
performanceDataState[checkLastIndex].grpc.server_deserialize_cpu = (lastData.grpc.server_deserialize_cpu + response.data.grpc.server_deserialize_cpu) / 2;
|
|
performanceDataState[checkLastIndex].grpc.server_deserialize_time = (lastData.grpc.server_deserialize_time + response.data.grpc.server_deserialize_time) / 2;
|
|
performanceDataState[checkLastIndex].grpc.server_serialize_cpu = (lastData.grpc.server_serialize_cpu + response.data.grpc.server_serialize_cpu) / 2;
|
|
performanceDataState[checkLastIndex].grpc.server_serialize_time = (lastData.grpc.server_serialize_time + response.data.grpc.server_serialize_time) / 2;
|
|
performanceDataState[checkLastIndex].grpc.server_protocol_total_time = (lastData.grpc.server_protocol_total_time + response.data.grpc.server_protocol_total_time) / 2;
|
|
|
|
performanceDataState[checkLastIndex].rest.client_networking_ping = (lastData.rest.client_networking_ping + response.data.rest.client_networking_ping) / 2;
|
|
performanceDataState[checkLastIndex].rest.client_request_cpu = (lastData.rest.client_request_cpu + response.data.rest.client_request_cpu) / 2;
|
|
performanceDataState[checkLastIndex].rest.client_request_time = (lastData.rest.client_request_time + response.data.rest.client_request_time) / 2;
|
|
performanceDataState[checkLastIndex].rest.networking_size.request_size = (lastData.rest.networking_size.request_size + response.data.rest.networking_size.request_size) / 2;
|
|
performanceDataState[checkLastIndex].rest.networking_size.response_size = (lastData.rest.networking_size.response_size + response.data.rest.networking_size.response_size) / 2;
|
|
performanceDataState[checkLastIndex].rest.server_deserialize_cpu = (lastData.rest.server_deserialize_cpu + response.data.rest.server_deserialize_cpu) / 2;
|
|
performanceDataState[checkLastIndex].rest.server_deserialize_time = (lastData.rest.server_deserialize_time + response.data.rest.server_deserialize_time) / 2;
|
|
performanceDataState[checkLastIndex].rest.server_serialize_cpu = (lastData.rest.server_serialize_cpu + response.data.rest.server_serialize_cpu) / 2;
|
|
performanceDataState[checkLastIndex].rest.server_serialize_time = (lastData.rest.server_serialize_time + response.data.rest.server_serialize_time) / 2;
|
|
performanceDataState[checkLastIndex].rest.server_protocol_total_time = (lastData.rest.server_protocol_total_time + response.data.rest.server_protocol_total_time) / 2;
|
|
}
|
|
else {
|
|
performanceDataState.push(response.data)
|
|
}
|
|
}
|
|
}
|
|
catch (error: any) {
|
|
showErrorMessage(error.toString(), "Error during performance test");
|
|
}
|
|
finally {
|
|
setCurrentAvgCount(i + 1)
|
|
}
|
|
}
|
|
idx++;
|
|
setCurrentIdx(idx)
|
|
await sleep(200)
|
|
|
|
if (currentForCount >= endsCount) {
|
|
break;
|
|
}
|
|
|
|
currentForCount += addCount;
|
|
if (currentForCount > endsCount) {
|
|
currentForCount = endsCount;
|
|
}
|
|
}
|
|
}
|
|
|
|
const rows = performanceDataSnap.map(item => (
|
|
<Table.Tr key={`${item.idx}_${item.request_count}`}>
|
|
<Table.Td>{getCurrentSingleStep(item.idx)}</Table.Td>
|
|
<Table.Td>{item.request_count}</Table.Td>
|
|
<Table.Td>{convertNumber(item.grpc.client_networking_ping, 1000, 2)} / {convertNumber(item.rest.client_networking_ping, 1000, 2)}</Table.Td>
|
|
<Table.Td>{convertNumber(item.grpc.client_request_cpu, 1, 2)} / {convertNumber(item.rest.client_request_cpu, 1, 2)}</Table.Td>
|
|
<Table.Td>{convertNumber(item.grpc.client_request_time, 1, 2)} / {convertNumber(item.rest.client_request_time, 1, 2)}</Table.Td>
|
|
<Table.Td>{convertNumber(item.grpc.server_deserialize_cpu, 1, 2)} / {convertNumber(item.rest.server_deserialize_cpu, 1, 2)}</Table.Td>
|
|
<Table.Td>{convertNumber(item.grpc.server_deserialize_time, 1000, 4)} / {convertNumber(item.rest.server_deserialize_time, 1000, 4)}</Table.Td>
|
|
<Table.Td>{convertNumber(item.grpc.server_serialize_cpu, 1, 2)} / {convertNumber(item.rest.server_serialize_cpu, 1, 2)}</Table.Td>
|
|
<Table.Td>{convertNumber(item.grpc.server_serialize_time, 1000, 4)} / {convertNumber(item.rest.server_serialize_time, 1000, 4)}</Table.Td>
|
|
<Table.Td>{convertNumber(item.grpc.networking_size.request_size, 1 / 1024, 4)} / {convertNumber(item.rest.networking_size.request_size, 1 / 1024, 4)}</Table.Td>
|
|
<Table.Td>{convertNumber(item.grpc.networking_size.response_size, 1 / 1024, 4)} / {convertNumber(item.rest.networking_size.response_size, 1 / 1024, 4)}</Table.Td>
|
|
</Table.Tr>
|
|
))
|
|
|
|
return (
|
|
<Stack>
|
|
<Card padding="lg" radius="md" withBorder style={marginTopBottom}>
|
|
|
|
<Card.Section withBorder>
|
|
<Accordion variant="filled" chevronPosition="left" defaultValue="advanced-filter">
|
|
<Accordion.Item value="advanced-filter">
|
|
<Accordion.Control>
|
|
<Group>
|
|
<Text>Config</Text>
|
|
</Group>
|
|
</Accordion.Control>
|
|
<Accordion.Panel>
|
|
<PerformanceTestFilter onChange={updateFilter} onClickStart={onClickStart} onClickStop={OnClickStop} onClickExportData={exportData}
|
|
isStarting={isStarting} currentCount={currentCount} requestStopping={requestStopping} isPushTest={isPushTest} />
|
|
</Accordion.Panel>
|
|
</Accordion.Item>
|
|
</Accordion>
|
|
</Card.Section>
|
|
|
|
<Card.Section withBorder>
|
|
<Charts data={performanceDataSnap.flatMap(item => item || []) as PerformanceGetListData[]}
|
|
gridSpan={chartsSize} hideServerDeserialize={hideServerDeserialize} hideServerSerialize={hideServerSerialize} />
|
|
</Card.Section>
|
|
|
|
<Card.Section>
|
|
<ResponsiveTableContainer minWidth={600}>
|
|
<Table striped highlightOnHover withColumnBorders withTableBorder>
|
|
<Table.Thead>
|
|
<Table.Tr>
|
|
<Table.Th colSpan={2}></Table.Th>
|
|
<Table.Th colSpan={3}>Client (gRPC / Rest)</Table.Th>
|
|
<Table.Th colSpan={2}>Server Deserialization (gRPC / Rest)</Table.Th>
|
|
<Table.Th colSpan={2}>Server Serialization (gRPC / Rest)</Table.Th>
|
|
<Table.Th colSpan={2}>Networking Pack Size (gRPC / Rest)</Table.Th>
|
|
</Table.Tr>
|
|
<Table.Tr key="header">
|
|
<Table.Th>Index</Table.Th>
|
|
<Table.Th>Count</Table.Th>
|
|
<Table.Th>Ping (ms)</Table.Th>
|
|
<Table.Th>CPU (%)</Table.Th>
|
|
<Table.Th>Time (s)</Table.Th>
|
|
<Table.Th>CPU (%)</Table.Th>
|
|
<Table.Th>Time (ms)</Table.Th>
|
|
<Table.Th>CPU (%)</Table.Th>
|
|
<Table.Th>Time (ms)</Table.Th>
|
|
<Table.Th>Request (KB)</Table.Th>
|
|
<Table.Th>Response (KB)</Table.Th>
|
|
</Table.Tr>
|
|
</Table.Thead>
|
|
<Table.Tbody>
|
|
{rows}
|
|
</Table.Tbody>
|
|
</Table>
|
|
</ResponsiveTableContainer>
|
|
|
|
{/*<Pagination withEdges total={staffInfo.total_pages} value={currPage} onChange={setCurrPage} mt="sm"*/}
|
|
{/* style={{justifyItems: "flex-end", ...marginRightBottom}}/>*/}
|
|
</Card.Section>
|
|
|
|
{!isPushTest &&
|
|
<Card.Section>
|
|
<Space h="lg"/>
|
|
<Text ta="center" fw={700}>Example Books Data</Text>
|
|
<ScrollArea w="100%">
|
|
<BookTable books={(performanceDataSnap && performanceDataSnap.length > 0 ? performanceDataSnap[performanceDataSnap.length - 1].rest.response_data || [] : []) as BookInfo[]} />
|
|
</ScrollArea>
|
|
</Card.Section>
|
|
}
|
|
</Card>
|
|
</Stack>
|
|
)
|
|
}
|
|
|