chore: refactor watch system resource hook (#2048)

This commit is contained in:
Louis 2024-02-16 13:22:21 +07:00 committed by GitHub
parent 42da19a463
commit 63cffca51e
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
6 changed files with 82 additions and 38 deletions

View File

@ -1,3 +1,5 @@
import { useEffect } from 'react'
import { import {
Badge, Badge,
Button, Button,
@ -31,6 +33,11 @@ import { useMainViewState } from '@/hooks/useMainViewState'
import { serverEnabledAtom } from '@/helpers/atoms/LocalServer.atom' import { serverEnabledAtom } from '@/helpers/atoms/LocalServer.atom'
import { downloadedModelsAtom } from '@/helpers/atoms/Model.atom' import { downloadedModelsAtom } from '@/helpers/atoms/Model.atom'
import {
cpuUsageAtom,
gpusAtom,
ramUtilitizedAtom,
} from '@/helpers/atoms/SystemBar.atom'
const menuLinks = [ const menuLinks = [
{ {
@ -47,9 +54,12 @@ const menuLinks = [
const BottomBar = () => { const BottomBar = () => {
const { activeModel, stateModel } = useActiveModel() const { activeModel, stateModel } = useActiveModel()
const { ram, cpu, gpus } = useGetSystemResources() const { watch, stopWatching } = useGetSystemResources()
const progress = useAtomValue(appDownloadProgress) const progress = useAtomValue(appDownloadProgress)
const downloadedModels = useAtomValue(downloadedModelsAtom) const downloadedModels = useAtomValue(downloadedModelsAtom)
const gpus = useAtomValue(gpusAtom)
const cpu = useAtomValue(cpuUsageAtom)
const ramUtilitized = useAtomValue(ramUtilitizedAtom)
const { setMainViewState } = useMainViewState() const { setMainViewState } = useMainViewState()
const downloadStates = useAtomValue(modelDownloadStateAtom) const downloadStates = useAtomValue(modelDownloadStateAtom)
@ -67,6 +77,16 @@ const BottomBar = () => {
return sum return sum
} }
useEffect(() => {
// Watch for resource update
watch()
return () => {
stopWatching()
}
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [])
return ( return (
<div className="fixed bottom-0 left-16 z-20 flex h-12 w-[calc(100%-64px)] items-center justify-between border-t border-border bg-background/80 px-3"> <div className="fixed bottom-0 left-16 z-20 flex h-12 w-[calc(100%-64px)] items-center justify-between border-t border-border bg-background/80 px-3">
<div className="flex flex-shrink-0 items-center gap-x-2"> <div className="flex flex-shrink-0 items-center gap-x-2">
@ -127,7 +147,7 @@ const BottomBar = () => {
<div className="flex items-center gap-x-3"> <div className="flex items-center gap-x-3">
<div className="flex items-center gap-x-2"> <div className="flex items-center gap-x-2">
<SystemItem name="CPU:" value={`${cpu}%`} /> <SystemItem name="CPU:" value={`${cpu}%`} />
<SystemItem name="Mem:" value={`${ram}%`} /> <SystemItem name="Mem:" value={`${ramUtilitized}%`} />
</div> </div>
{gpus.length > 0 && ( {gpus.length > 0 && (
<Tooltip> <Tooltip>

View File

@ -3,6 +3,7 @@
import { Fragment, ReactNode } from 'react' import { Fragment, ReactNode } from 'react'
import useAssistants from '@/hooks/useAssistants' import useAssistants from '@/hooks/useAssistants'
import useGetSystemResources from '@/hooks/useGetSystemResources'
import useModels from '@/hooks/useModels' import useModels from '@/hooks/useModels'
import useThreads from '@/hooks/useThreads' import useThreads from '@/hooks/useThreads'
@ -14,6 +15,8 @@ const DataLoader: React.FC<Props> = ({ children }) => {
useModels() useModels()
useThreads() useThreads()
useAssistants() useAssistants()
useGetSystemResources()
console.debug('Load Data...')
return <Fragment>{children}</Fragment> return <Fragment>{children}</Fragment>
} }

View File

@ -282,11 +282,9 @@ export default function EventHandler({ children }: { children: ReactNode }) {
} }
useEffect(() => { useEffect(() => {
console.log('Registering events')
if (window.core?.events) { if (window.core?.events) {
events.on(MessageEvent.OnMessageResponse, onNewMessageResponse) events.on(MessageEvent.OnMessageResponse, onNewMessageResponse)
events.on(MessageEvent.OnMessageUpdate, onMessageResponseUpdate) events.on(MessageEvent.OnMessageUpdate, onMessageResponseUpdate)
events.on(ModelEvent.OnModelReady, onModelReady) events.on(ModelEvent.OnModelReady, onModelReady)
events.on(ModelEvent.OnModelFail, onModelInitFailed) events.on(ModelEvent.OnModelFail, onModelInitFailed)
events.on(ModelEvent.OnModelStopped, onModelStopped) events.on(ModelEvent.OnModelStopped, onModelStopped)

View File

@ -41,14 +41,14 @@ const EventListenerWrapper = ({ children }: PropsWithChildren) => {
) )
useEffect(() => { useEffect(() => {
console.log('EventListenerWrapper: registering event listeners...') console.debug('EventListenerWrapper: registering event listeners...')
events.on(DownloadEvent.onFileDownloadUpdate, onFileDownloadUpdate) events.on(DownloadEvent.onFileDownloadUpdate, onFileDownloadUpdate)
events.on(DownloadEvent.onFileDownloadError, onFileDownloadError) events.on(DownloadEvent.onFileDownloadError, onFileDownloadError)
events.on(DownloadEvent.onFileDownloadSuccess, onFileDownloadSuccess) events.on(DownloadEvent.onFileDownloadSuccess, onFileDownloadSuccess)
return () => { return () => {
console.log('EventListenerWrapper: unregistering event listeners...') console.debug('EventListenerWrapper: unregistering event listeners...')
events.off(DownloadEvent.onFileDownloadUpdate, onFileDownloadUpdate) events.off(DownloadEvent.onFileDownloadUpdate, onFileDownloadUpdate)
events.off(DownloadEvent.onFileDownloadError, onFileDownloadError) events.off(DownloadEvent.onFileDownloadError, onFileDownloadError)
events.off(DownloadEvent.onFileDownloadSuccess, onFileDownloadSuccess) events.off(DownloadEvent.onFileDownloadSuccess, onFileDownloadSuccess)

View File

@ -2,8 +2,10 @@ import { atom } from 'jotai'
export const totalRamAtom = atom<number>(0) export const totalRamAtom = atom<number>(0)
export const usedRamAtom = atom<number>(0) export const usedRamAtom = atom<number>(0)
export const availableRamAtom = atom<number>(0)
export const cpuUsageAtom = atom<number>(0) export const cpuUsageAtom = atom<number>(0)
export const ramUtilitizedAtom = atom<number>(0)
export const gpusAtom = atom<Record<string, never>[]>([])
export const nvidiaTotalVramAtom = atom<number>(0) export const nvidiaTotalVramAtom = atom<number>(0)

View File

@ -1,4 +1,4 @@
import { useEffect, useState } from 'react' import { useCallback, useEffect, useState } from 'react'
import { ExtensionTypeEnum, MonitoringExtension } from '@janhq/core' import { ExtensionTypeEnum, MonitoringExtension } from '@janhq/core'
@ -6,25 +6,27 @@ import { useSetAtom } from 'jotai'
import { extensionManager } from '@/extension/ExtensionManager' import { extensionManager } from '@/extension/ExtensionManager'
import { import {
availableRamAtom,
cpuUsageAtom, cpuUsageAtom,
totalRamAtom, totalRamAtom,
usedRamAtom, usedRamAtom,
nvidiaTotalVramAtom, nvidiaTotalVramAtom,
gpusAtom,
ramUtilitizedAtom,
} from '@/helpers/atoms/SystemBar.atom' } from '@/helpers/atoms/SystemBar.atom'
export default function useGetSystemResources() { export default function useGetSystemResources() {
const [ram, setRam] = useState<number>(0) const [intervalId, setIntervalId] = useState<
const [cpu, setCPU] = useState<number>(0) NodeJS.Timeout | number | undefined
>(undefined)
const [gpus, setGPUs] = useState<Record<string, never>[]>([])
const setTotalRam = useSetAtom(totalRamAtom) const setTotalRam = useSetAtom(totalRamAtom)
const setGpus = useSetAtom(gpusAtom)
const setUsedRam = useSetAtom(usedRamAtom) const setUsedRam = useSetAtom(usedRamAtom)
const setAvailableRam = useSetAtom(availableRamAtom)
const setCpuUsage = useSetAtom(cpuUsageAtom) const setCpuUsage = useSetAtom(cpuUsageAtom)
const setTotalNvidiaVram = useSetAtom(nvidiaTotalVramAtom) const setTotalNvidiaVram = useSetAtom(nvidiaTotalVramAtom)
const setRamUtilitized = useSetAtom(ramUtilitizedAtom)
const getSystemResources = async () => { const getSystemResources = useCallback(async () => {
if ( if (
!extensionManager.get<MonitoringExtension>( !extensionManager.get<MonitoringExtension>(
ExtensionTypeEnum.SystemMonitoring ExtensionTypeEnum.SystemMonitoring
@ -38,23 +40,20 @@ export default function useGetSystemResources() {
const resourceInfor = await monitoring?.getResourcesInfo() const resourceInfor = await monitoring?.getResourcesInfo()
const currentLoadInfor = await monitoring?.getCurrentLoad() const currentLoadInfor = await monitoring?.getCurrentLoad()
const ram =
(resourceInfor?.mem?.usedMemory ?? 0) /
(resourceInfor?.mem?.totalMemory ?? 1)
if (resourceInfor?.mem?.usedMemory) setUsedRam(resourceInfor.mem.usedMemory) if (resourceInfor?.mem?.usedMemory) setUsedRam(resourceInfor.mem.usedMemory)
if (resourceInfor?.mem?.totalMemory) if (resourceInfor?.mem?.totalMemory)
setTotalRam(resourceInfor.mem.totalMemory) setTotalRam(resourceInfor.mem.totalMemory)
setRam(Math.round(ram * 100)) const ramUtilitized =
if (resourceInfor.mem.totalMemory && resourceInfor.mem.usedMemory) ((resourceInfor?.mem?.usedMemory ?? 0) /
setAvailableRam( (resourceInfor?.mem?.totalMemory ?? 1)) *
resourceInfor.mem.totalMemory - resourceInfor.mem.usedMemory 100
) setRamUtilitized(Math.round(ramUtilitized))
setCPU(Math.round(currentLoadInfor?.cpu?.usage ?? 0))
setCpuUsage(Math.round(currentLoadInfor?.cpu?.usage ?? 0)) setCpuUsage(Math.round(currentLoadInfor?.cpu?.usage ?? 0))
const gpus = currentLoadInfor?.gpu ?? [] const gpus = currentLoadInfor?.gpu ?? []
setGPUs(gpus) setGpus(gpus)
let totalNvidiaVram = 0 let totalNvidiaVram = 0
if (gpus.length > 0) { if (gpus.length > 0) {
@ -65,27 +64,49 @@ export default function useGetSystemResources() {
) )
} }
setTotalNvidiaVram(totalNvidiaVram) setTotalNvidiaVram(totalNvidiaVram)
} }, [
setUsedRam,
setTotalRam,
setRamUtilitized,
setCpuUsage,
setGpus,
setTotalNvidiaVram,
])
useEffect(() => { const watch = () => {
getSystemResources() getSystemResources()
// Fetch interval - every 2s // Fetch interval - every 2s
// TODO: Will we really need this? const itv = setInterval(() => {
// There is a possibility that this will be removed and replaced by the process event hook?
const intervalId = setInterval(() => {
getSystemResources() getSystemResources()
}, 5000) }, 2000)
setIntervalId(itv)
}
const stopWatching = useCallback(() => {
if (intervalId) clearInterval(intervalId)
}, [intervalId])
// clean up interval useEffect(() => {
return () => clearInterval(intervalId) getSystemResources()
// eslint-disable-next-line react-hooks/exhaustive-deps // Component did unmount
}, []) // Stop watching if any
return () => {
stopWatching()
}
}, [getSystemResources, stopWatching])
return { return {
totalRamAtom, /**
ram, * Fetch resource informations once
cpu, */
gpus, getSystemResources,
/**
* Fetch & watch for resource update
*/
watch,
/**
* Stop watching
*/
stopWatching,
} }
} }