From 8c66c482b24b495d9170ef4f03caa81e9c1365be Mon Sep 17 00:00:00 2001 From: jialin Date: Fri, 5 Jul 2024 09:29:46 +0800 Subject: [PATCH] chore: dashboard load optimization --- src/components/echarts/bar-chart.tsx | 1 + src/components/echarts/h-bar.tsx | 1 + src/components/echarts/line-chart.tsx | 14 +- src/components/util-bar/index.less | 2 +- src/components/util-bar/index.tsx | 2 +- src/global.less | 4 + src/hooks/use-window-resize.ts | 19 +- .../components/resource-utilization.tsx | 14 +- .../components/usage-inner/index.tsx | 201 +++++++++++++++++ src/pages/dashboard/components/usage.tsx | 207 +----------------- 10 files changed, 238 insertions(+), 227 deletions(-) create mode 100644 src/pages/dashboard/components/usage-inner/index.tsx diff --git a/src/components/echarts/bar-chart.tsx b/src/components/echarts/bar-chart.tsx index 7d5424d7..78a72520 100644 --- a/src/components/echarts/bar-chart.tsx +++ b/src/components/echarts/bar-chart.tsx @@ -65,6 +65,7 @@ const BarChart: React.FC = (props) => { }); const optionsConfig = { ...options, + animation: false, title: { ...titleConfig, text: title diff --git a/src/components/echarts/h-bar.tsx b/src/components/echarts/h-bar.tsx index d2b7ed26..eb59fc4d 100644 --- a/src/components/echarts/h-bar.tsx +++ b/src/components/echarts/h-bar.tsx @@ -64,6 +64,7 @@ const BarChart: React.FC = (props) => { }); const optionsConfig = { ...options, + animation: false, title: { ...options.title, left: 'start', diff --git a/src/components/echarts/line-chart.tsx b/src/components/echarts/line-chart.tsx index 3a35be2c..45c98064 100644 --- a/src/components/echarts/line-chart.tsx +++ b/src/components/echarts/line-chart.tsx @@ -9,7 +9,7 @@ import { yAxis } from '@/components/echarts/config'; import _ from 'lodash'; -import { useEffect, useState } from 'react'; +import { memo } from 'react'; import { ChartProps } from './types'; const LineChart: React.FC = (props) => { @@ -23,7 +23,6 @@ const LineChart: React.FC = (props) => { smooth, title } = props; - const [dataOptions, setDataOptions] = useState({}); const options = { title: { @@ -49,7 +48,7 @@ const LineChart: React.FC = (props) => { series: [] }; - useEffect(() => { + const generateOptions = (): any => { const data = _.map(seriesData, (item: any) => { return { ...item, @@ -67,6 +66,7 @@ const LineChart: React.FC = (props) => { }); const optionsConfig = { ...options, + animation: false, title: { ...titleConfig, text: title @@ -80,9 +80,9 @@ const LineChart: React.FC = (props) => { }, series: data }; - console.log('optionsConfig========line=', optionsConfig); - setDataOptions(optionsConfig); - }, [seriesData, xAxisData, title]); + return optionsConfig; + }; + const dataOptions = generateOptions(); return ( = (props) => { ); }; -export default LineChart; +export default memo(LineChart); diff --git a/src/components/util-bar/index.less b/src/components/util-bar/index.less index 11039ce7..37604d7f 100644 --- a/src/components/util-bar/index.less +++ b/src/components/util-bar/index.less @@ -12,6 +12,6 @@ } .ant-progress.ant-progress-circle .ant-progress-text { - font-size: 24px; + font-size: 20px; } } diff --git a/src/components/util-bar/index.tsx b/src/components/util-bar/index.tsx index fc37680a..38206cf4 100644 --- a/src/components/util-bar/index.tsx +++ b/src/components/util-bar/index.tsx @@ -18,7 +18,7 @@ const UitilBar: React.FC = (props) => { gapDegree = 170, strokeWidth = 10, title, - size = 160, + size = 150, strokeColor, trailColor = 'rgba(221,221,221,.5)' } = props; diff --git a/src/global.less b/src/global.less index 9d18cac5..36efec7b 100644 --- a/src/global.less +++ b/src/global.less @@ -261,6 +261,10 @@ body { background-color: var(--color-fill-1); height: 100%; + .ant-pro-sider-logo { + padding-left: 20px; + } + .ant-pro-sider .ant-layout-sider-children { background-color: var(--color-fill-sider); // box-shadow: var(--box-shadow-base); diff --git a/src/hooks/use-window-resize.ts b/src/hooks/use-window-resize.ts index 40ec0d2a..1cbdf5e0 100644 --- a/src/hooks/use-window-resize.ts +++ b/src/hooks/use-window-resize.ts @@ -39,23 +39,26 @@ export default function useWindowResize() { setIsDesktop(true); setCurrentPoint('xl'); }, []); - const handleResize = _.throttle(() => { - setSize({ - width: window.innerWidth, - height: window.innerHeight - }); - }, 200); + const handleResize = useCallback( + _.throttle(() => { + setSize({ + width: window.innerWidth, + height: window.innerHeight + }); + }, 200), + [] + ); useEffect(() => { window.addEventListener('resize', handleResize); return () => { window.removeEventListener('resize', handleResize); }; - }, []); + }, [handleResize]); useEffect(() => { checkBreakpoint(size.width); - }, [size.width]); + }, [size.width, checkBreakpoint]); return { size, isMobile, isTablet, isDesktop, currentPoint }; } diff --git a/src/pages/dashboard/components/resource-utilization.tsx b/src/pages/dashboard/components/resource-utilization.tsx index 12c858da..5a7f52f5 100644 --- a/src/pages/dashboard/components/resource-utilization.tsx +++ b/src/pages/dashboard/components/resource-utilization.tsx @@ -2,7 +2,7 @@ import Chart from '@/components/echarts/chart'; import { getLocale, useIntl } from '@umijs/max'; import dayjs from 'dayjs'; import _ from 'lodash'; -import { useContext } from 'react'; +import { memo, useContext } from 'react'; import { DashboardContext } from '../config/dashboard-context'; const chartColorMap = { @@ -114,15 +114,10 @@ const UtilizationOvertime: React.FC = () => { const intl = useIntl(); const locale = getLocale(); let dataOptions: any = {}; - // const [dataOptions, setDataOptions] = useState(option); const data = useContext(DashboardContext)?.system_load?.history || {}; const typeList = ['gpu', 'cpu', 'memory', 'gpu_memory']; - const labelFormatter = (value: any) => { - return `${value}%`; - }; - const generateData = () => { const legendData: string[] = []; const xAxisData: string[] = []; @@ -130,7 +125,6 @@ const UtilizationOvertime: React.FC = () => { list = _.map(typeList, (item: string) => { const itemConfig = _.get(TypeKeyMap, item, {}); - console.log('itemConfig', itemConfig); const name = itemConfig.intl ? intl.formatMessage({ id: itemConfig.label }) : itemConfig.label; @@ -161,6 +155,7 @@ const UtilizationOvertime: React.FC = () => { dataOptions = { ...option, + animation: false, legend: { ...option.legend, data: legendData @@ -173,9 +168,6 @@ const UtilizationOvertime: React.FC = () => { }; }; generateData(); - // useEffect(() => { - // generateData(); - // }, [data, locale]); return ( <> @@ -184,4 +176,4 @@ const UtilizationOvertime: React.FC = () => { ); }; -export default UtilizationOvertime; +export default memo(UtilizationOvertime); diff --git a/src/pages/dashboard/components/usage-inner/index.tsx b/src/pages/dashboard/components/usage-inner/index.tsx new file mode 100644 index 00000000..0365d066 --- /dev/null +++ b/src/pages/dashboard/components/usage-inner/index.tsx @@ -0,0 +1,201 @@ +import PageTools from '@/components/page-tools'; + +import { useIntl } from '@umijs/max'; +import { Col, DatePicker, Row } from 'antd'; +import dayjs from 'dayjs'; +import _ from 'lodash'; +import { memo, useCallback, useContext } from 'react'; +import { DashboardContext } from '../../config/dashboard-context'; +import RequestTokenInner from './request-token-inner'; +import TopUser from './top-user'; + +const baseColorMap = { + baseL2: 'rgba(13,171,219,0.8)', + baseL1: 'rgba(0,34,255,0.8)', + base: 'rgba(0,85,255,0.8)', + baseR1: 'rgba(0,255,233,0.8)', + baseR2: 'rgba(48,0,255,0.8)', + baseR3: 'rgba(85,167,255,0.8)' +}; + +const getCurrentMonthDays = () => { + const now = dayjs(); + const daysInMonth = now.daysInMonth(); + const year = dayjs().year(); + const month = dayjs().month() + 1; + + const dates = []; + for (let day = 1; day <= daysInMonth; day++) { + dates.push(dayjs(`${year}-${month}-${day}`).format('YYYY-MM-DD')); + } + return dates; +}; + +const UsageInner: React.FC<{ paddingRight: string }> = ({ paddingRight }) => { + const intl = useIntl(); + const currentDate = dayjs(); + const currentMonthDays = getCurrentMonthDays(); + let requestData: { + name: string; + color: string; + areaStyle: any; + data: { time: string; value: number }[]; + }[] = []; + let tokenData: { time: string; value: number }[] = []; + let userData: { name: string; value: number }[] = []; + const xAxisData: string[] = currentMonthDays; + let topUserList: string[] = []; + + const { model_usage } = useContext(DashboardContext); + const data = model_usage || {}; + + const handleSelectDate = (date: any) => { + // fetchData?.(); + }; + + const generateData = useCallback(() => { + const requestList: { + name: string; + color: string; + areaStyle: any; + data: { time: string; value: number }[]; + } = { + name: 'API requests', + areaStyle: {}, + color: baseColorMap.base, + data: [] + }; + + const completionData: any = { + name: 'Completion tokens', + color: baseColorMap.base, + data: [] + }; + const prompData: any = { + name: 'Prompt tokens', + color: baseColorMap.baseR3, + data: [] + }; + + const topUserPrompt: any = { + name: 'Prompt tokens', + color: baseColorMap.baseR3, + data: [] + }; + const topUserCompletion: any = { + name: 'Completion tokens', + color: baseColorMap.base, + data: [] + }; + const users: string[] = []; + + _.each(xAxisData, (date: string) => { + // tokens data + const item = _.find(data.completion_token_history, (item: any) => { + return dayjs(item.timestamp * 1000).format('YYYY-MM-DD') === date; + }); + if (!item) { + completionData.data.push({ + titme: date, + value: 0 + }); + } else { + completionData.data.push({ + value: item.value, + time: dayjs(item.timestamp * 1000).format('YYYY-MM-DD') + }); + } + + const promptItem = _.find(data.prompt_token_history, (item: any) => { + return dayjs(item.timestamp * 1000).format('YYYY-MM-DD') === date; + }); + if (!promptItem) { + prompData.data.push({ + value: 0, + time: date + }); + } else { + prompData.data.push({ + value: promptItem.value, + time: dayjs(promptItem.timestamp * 1000).format('YYYY-MM-DD') + }); + } + + // ============== api request data ================= + const requestItem = _.find(data.api_request_history, (item: any) => { + return dayjs(item.timestamp * 1000).format('YYYY-MM-DD') === date; + }); + + if (!requestItem) { + requestList.data.push({ + time: date, + value: 0 + }); + } else { + requestList.data.push({ + time: dayjs(requestItem.timestamp * 1000).format('YYYY-MM-DD'), + value: requestItem.value + }); + } + }); + + // ========== top users ============ + + _.each(data.top_users, (item: any) => { + users.push(item.username); + topUserPrompt.data.push({ + name: item.username, + value: item.prompt_token_count + }); + topUserCompletion.data.push({ + name: item.username, + value: item.completion_token_count + }); + }); + + requestData = [requestList]; + userData = [topUserCompletion, topUserPrompt]; + topUserList = users; + tokenData = [completionData, prompData]; + }, [data, xAxisData]); + + generateData(); + + return ( + <> + {intl.formatMessage({ id: 'dashboard.usage' })}} + right={ + + } + /> + + + + + + + + + + ); +}; + +export default memo(UsageInner); diff --git a/src/pages/dashboard/components/usage.tsx b/src/pages/dashboard/components/usage.tsx index 83a16fe1..a5e677a5 100644 --- a/src/pages/dashboard/components/usage.tsx +++ b/src/pages/dashboard/components/usage.tsx @@ -1,214 +1,23 @@ -import PageTools from '@/components/page-tools'; import breakpoints from '@/config/breakpoints'; import useWindowResize from '@/hooks/use-window-resize'; -import { useIntl } from '@umijs/max'; -import { Col, DatePicker, Row } from 'antd'; -import dayjs from 'dayjs'; -import _ from 'lodash'; -import { useContext, useEffect, useState } from 'react'; -import { DashboardContext } from '../config/dashboard-context'; -import RequestTokenInner from './usage-inner/request-token-inner'; -import TopUser from './usage-inner/top-user'; - -const baseColorMap = { - baseL2: 'rgba(13,171,219,0.8)', - baseL1: 'rgba(0,34,255,0.8)', - base: 'rgba(0,85,255,0.8)', - baseR1: 'rgba(0,255,233,0.8)', - baseR2: 'rgba(48,0,255,0.8)', - baseR3: 'rgba(85,167,255,0.8)' -}; - -const getCurrentMonthDays = () => { - const now = dayjs(); - const daysInMonth = now.daysInMonth(); - const year = dayjs().year(); - const month = dayjs().month() + 1; - - const dates = []; - for (let day = 1; day <= daysInMonth; day++) { - dates.push(dayjs(`${year}-${month}-${day}`).format('YYYY-MM-DD')); - } - return dates; -}; +import { useEffect, useState } from 'react'; +import UserInner from './usage-inner'; const Usage = () => { - const intl = useIntl(); - const { size } = useWindowResize(); + const { + size: { width } + } = useWindowResize(); const [paddingRight, setPaddingRight] = useState('20px'); - console.log('usage========'); - const currentDate = dayjs(); - const currentMonthDays = getCurrentMonthDays(); - let requestData: { - name: string; - color: string; - areaStyle: any; - data: { time: string; value: number }[]; - }[] = []; - let tokenData: { time: string; value: number }[] = []; - let userData: { name: string; value: number }[] = []; - const xAxisData: string[] = currentMonthDays; - let topUserList: string[] = []; - - const { model_usage, fetchData } = useContext(DashboardContext); - const data = model_usage || {}; - - const handleSelectDate = (date: any) => { - // fetchData?.(); - }; - - const generateData = () => { - const requestList: { - name: string; - color: string; - areaStyle: any; - data: { time: string; value: number }[]; - } = { - name: 'API requests', - areaStyle: {}, - color: baseColorMap.base, - data: [] - }; - - const completionData: any = { - name: 'Completion tokens', - color: baseColorMap.base, - data: [] - }; - const prompData: any = { - name: 'Prompt tokens', - color: baseColorMap.baseR3, - data: [] - }; - - const topUserPrompt: any = { - name: 'Prompt tokens', - color: baseColorMap.baseR3, - data: [] - }; - const topUserCompletion: any = { - name: 'Completion tokens', - color: baseColorMap.base, - data: [] - }; - const users: string[] = []; - - _.each(xAxisData, (date: string) => { - // tokens data - const item = _.find(data.completion_token_history, (item: any) => { - return dayjs(item.timestamp * 1000).format('YYYY-MM-DD') === date; - }); - if (!item) { - completionData.data.push({ - titme: date, - value: 0 - }); - } else { - completionData.data.push({ - value: item.value, - time: dayjs(item.timestamp * 1000).format('YYYY-MM-DD') - }); - } - - const promptItem = _.find(data.prompt_token_history, (item: any) => { - return dayjs(item.timestamp * 1000).format('YYYY-MM-DD') === date; - }); - if (!promptItem) { - prompData.data.push({ - value: 0, - time: date - }); - } else { - prompData.data.push({ - value: promptItem.value, - time: dayjs(promptItem.timestamp * 1000).format('YYYY-MM-DD') - }); - } - - // ============== api request data ================= - const requestItem = _.find(data.api_request_history, (item: any) => { - return dayjs(item.timestamp * 1000).format('YYYY-MM-DD') === date; - }); - - if (!requestItem) { - requestList.data.push({ - time: date, - value: 0 - }); - } else { - requestList.data.push({ - time: dayjs(requestItem.timestamp * 1000).format('YYYY-MM-DD'), - value: requestItem.value - }); - } - }); - - // ========== top users ============ - - _.each(data.top_users, (item: any) => { - users.push(item.username); - topUserPrompt.data.push({ - name: item.username, - value: item.prompt_token_count - }); - topUserCompletion.data.push({ - name: item.username, - value: item.completion_token_count - }); - }); - - requestData = [requestList]; - userData = [topUserCompletion, topUserPrompt]; - topUserList = users; - tokenData = [completionData, prompData]; - }; - useEffect(() => { - if (size.width < breakpoints.xl) { + if (width < breakpoints.xl) { setPaddingRight('0'); } else { setPaddingRight('20px'); } - }, [size.width]); + }, [width]); - generateData(); - - return ( - <> - {intl.formatMessage({ id: 'dashboard.usage' })}} - right={ - - } - /> - - - - - - - - - - ); + return ; }; export default Usage;