diff --git a/Changelog.md b/Changelog.md
index 9b36edfd9..924602514 100644
--- a/Changelog.md
+++ b/Changelog.md
@@ -23,5 +23,6 @@
🚀 优化改进
- 应用内更新日志支持解析并渲染 HTML 标签
+- 性能优化前后端在渲染流量图时的资源
diff --git a/src/components/connection/connection-table.tsx b/src/components/connection/connection-table.tsx
index 7309e2fac..d99d01d9d 100644
--- a/src/components/connection/connection-table.tsx
+++ b/src/components/connection/connection-table.tsx
@@ -3,13 +3,13 @@ import { Box, IconButton, Tooltip } from "@mui/material";
import {
ColumnDef,
ColumnSizingState,
- SortingState,
- VisibilityState,
flexRender,
getCoreRowModel,
getSortedRowModel,
+ SortingState,
Updater,
useReactTable,
+ VisibilityState,
} from "@tanstack/react-table";
import { useVirtualizer } from "@tanstack/react-virtual";
import dayjs from "dayjs";
@@ -43,6 +43,50 @@ const reconcileColumnOrder = (
return [...filtered, ...missing];
};
+const createConnectionRow = (each: IConnectionsItem) => {
+ const { metadata, rulePayload } = each;
+ const chains = [...each.chains].reverse().join(" / ");
+ const rule = rulePayload ? `${each.rule}(${rulePayload})` : each.rule;
+ const destination = metadata.destinationIP
+ ? `${metadata.destinationIP}:${metadata.destinationPort}`
+ : `${metadata.remoteDestination}:${metadata.destinationPort}`;
+
+ return {
+ id: each.id,
+ host: metadata.host
+ ? `${metadata.host}:${metadata.destinationPort}`
+ : `${metadata.remoteDestination}:${metadata.destinationPort}`,
+ download: each.download,
+ upload: each.upload,
+ dlSpeed: each.curDownload,
+ ulSpeed: each.curUpload,
+ chains,
+ rule,
+ process: truncateStr(metadata.process || metadata.processPath),
+ time: each.start,
+ source: `${metadata.sourceIP}:${metadata.sourcePort}`,
+ remoteDestination: destination,
+ type: `${metadata.type}(${metadata.network})`,
+ connectionData: each,
+ };
+};
+
+type ConnectionRow = ReturnType;
+
+const areRowsEqual = (a: ConnectionRow, b: ConnectionRow) =>
+ a.host === b.host &&
+ a.download === b.download &&
+ a.upload === b.upload &&
+ a.dlSpeed === b.dlSpeed &&
+ a.ulSpeed === b.ulSpeed &&
+ a.chains === b.chains &&
+ a.rule === b.rule &&
+ a.process === b.process &&
+ a.time === b.time &&
+ a.source === b.source &&
+ a.remoteDestination === b.remoteDestination &&
+ a.type === b.type;
+
interface Props {
connections: IConnectionsItem[];
onShowDetail: (data: IConnectionsItem) => void;
@@ -105,35 +149,6 @@ export const ConnectionTable = (props: Props) => {
},
);
- const createConnectionRow = (each: IConnectionsItem) => {
- const { metadata, rulePayload } = each;
- const chains = [...each.chains].reverse().join(" / ");
- const rule = rulePayload ? `${each.rule}(${rulePayload})` : each.rule;
- const Destination = metadata.destinationIP
- ? `${metadata.destinationIP}:${metadata.destinationPort}`
- : `${metadata.remoteDestination}:${metadata.destinationPort}`;
- return {
- id: each.id,
- host: metadata.host
- ? `${metadata.host}:${metadata.destinationPort}`
- : `${metadata.remoteDestination}:${metadata.destinationPort}`,
- download: each.download,
- upload: each.upload,
- dlSpeed: each.curDownload,
- ulSpeed: each.curUpload,
- chains,
- rule,
- process: truncateStr(metadata.process || metadata.processPath),
- time: each.start,
- source: `${metadata.sourceIP}:${metadata.sourcePort}`,
- remoteDestination: Destination,
- type: `${metadata.type}(${metadata.network})`,
- connectionData: each,
- };
- };
-
- type ConnectionRow = ReturnType;
-
type ColumnField = Exclude;
interface BaseColumn {
@@ -209,7 +224,7 @@ export const ConnectionTable = (props: Props) => {
width: 100,
minWidth: 80,
align: "right",
- cell: (row) => dayjs(row.time).fromNow(),
+ // cell filled later with shared relativeNow ticker
},
{
field: "source",
@@ -366,30 +381,68 @@ export const ConnectionTable = (props: Props) => {
}));
}, [columns, columnVisibilityModel]);
- const connRows = useMemo(
- () => connections.map((each) => createConnectionRow(each)),
- [connections],
- );
+ const prevRowsRef = useRef