Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

update: ハードウェア使用率更新処理の修正 #5

Closed
wants to merge 1 commit into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions src/atom/chart.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
import { atom } from "jotai";

export const cpuUsageHistoryAtom = atom<number[]>([]);
export const memoryUsageHistoryAtom = atom<number[]>([]);
export const graphicUsageHistoryAtom = atom<number[]>([]);
6 changes: 5 additions & 1 deletion src/atom/main.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,8 @@
import type { Settings } from "@/types/settingsType";
import { atom } from "jotai";

export const settingsAtom = atom<Settings | null>(null);
export const settingsAtom = atom<Settings>({
language: "en",
theme: "light",
display_targets: [],
});
6 changes: 6 additions & 0 deletions src/consts/chart.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
export const chartConfig = {
/**
* グラフの履歴の長さ(秒)
*/
historyLengthSec: 60,
} as const;
61 changes: 61 additions & 0 deletions src/hooks/useHardwareData.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
import {
cpuUsageHistoryAtom,
graphicUsageHistoryAtom,
memoryUsageHistoryAtom,
} from "@/atom/chart";
import { chartConfig } from "@/consts/chart";
import {
getCpuUsage,
getGpuUsage,
getMemoryUsage,
} from "@/services/hardwareService";
import type { ChartDataType } from "@/types/chartType";
import { type PrimitiveAtom, useSetAtom } from "jotai";
import { useEffect } from "react";

type AtomActionMapping = {
atom: PrimitiveAtom<number[]>;
action: () => Promise<number>;
};

/**
* ハードウェア使用率の履歴を更新する
*/
export const useUsageUpdater = (dataType: ChartDataType) => {
const mapping: Record<ChartDataType, AtomActionMapping> = {
cpu: {
atom: cpuUsageHistoryAtom,
action: getCpuUsage,
},
memory: {
atom: memoryUsageHistoryAtom,
action: getMemoryUsage,
},
gpu: {
atom: graphicUsageHistoryAtom,
action: getGpuUsage,
},
};

const setHistory = useSetAtom(mapping[dataType].atom);
const getUsage = mapping[dataType].action;

useEffect(() => {
const intervalId = setInterval(async () => {
const usage = await getUsage();
setHistory((prev) => {
const newHistory = [...prev, usage];

// 履歴保持数に満たない場合は0で埋める
const paddedHistory = Array(
Math.max(chartConfig.historyLengthSec - newHistory.length, 0),
)
.fill(null)
.concat(newHistory);
return paddedHistory.slice(-chartConfig.historyLengthSec);
});
}, 1000);

return () => clearInterval(intervalId);
}, [setHistory, getUsage]);
};
99 changes: 42 additions & 57 deletions src/template/Chart.tsx
Original file line number Diff line number Diff line change
@@ -1,76 +1,61 @@
import {
cpuUsageHistoryAtom,
graphicUsageHistoryAtom,
memoryUsageHistoryAtom,
} from "@/atom/chart";
import { settingsAtom } from "@/atom/main";
import LineChart from "@/components/LineChart";
import {
getCpuMemoryHistory,
getCpuUsageHistory,
getGpuUsageHistory,
} from "@/services/hardwareService";
import { chartConfig } from "@/consts/chart";
import { useUsageUpdater } from "@/hooks/useHardwareData";

import { useAtom } from "jotai";
import { useCallback, useEffect, useMemo, useState } from "react";
import { useMemo } from "react";

const ChartTemplate = () => {
const [cpuData, setCpuData] = useState<number[]>([]);
const [memoryData, setMemoryData] = useState<number[]>([]);
const [gpuData, setGpuData] = useState<number[]>([]);
const [labels, setLabels] = useState<string[]>([]);
const labels = Array(chartConfig.historyLengthSec).fill("");

const [settings] = useAtom(settingsAtom);
const CpuUsageChart = () => {
const [cpuUsageHistory] = useAtom(cpuUsageHistoryAtom);
useUsageUpdater("cpu");

const fetchData = useCallback(async () => {
const seconds = 60;
return (
<LineChart labels={labels} chartData={cpuUsageHistory} dataType="cpu" />
);
};

const newCpuDataPromise = settings?.display_targets.includes("cpu")
? getCpuUsageHistory(seconds)
: Promise.resolve([]);
const newMemoryDataPromise = settings?.display_targets.includes("memory")
? getCpuMemoryHistory(seconds)
: Promise.resolve([]);
const newGpuDataPromise = settings?.display_targets.includes("gpu")
? getGpuUsageHistory(seconds)
: Promise.resolve([]);
const MemoryUsageChart = () => {
const [memoryUsageHistory] = useAtom(memoryUsageHistoryAtom);
useUsageUpdater("memory");

return (
<LineChart
labels={labels}
chartData={memoryUsageHistory}
dataType="memory"
/>
);
};

const [newCpuData, newMemoryData, newGpuData] = await Promise.all([
newCpuDataPromise,
newMemoryDataPromise,
newGpuDataPromise,
]);
const GpuUsageChart = () => {
const [graphicUsageHistory] = useAtom(graphicUsageHistoryAtom);
useUsageUpdater("gpu");

if (cpuData.length < seconds) {
setCpuData([...cpuData, newCpuData[newCpuData.length - 1]]);
setMemoryData([...memoryData, newMemoryData[newMemoryData.length - 1]]);
setGpuData([...gpuData, newGpuData[newGpuData.length - 1]]);
setLabels([...labels, ""]);
} else {
setCpuData([...cpuData.slice(1), newCpuData[newCpuData.length - 1]]);
setMemoryData([
...memoryData.slice(1),
newMemoryData[newMemoryData.length - 1],
]);
setGpuData([...gpuData.slice(1), newGpuData[newGpuData.length - 1]]);
setLabels([...labels.slice(1), ""]);
}
}, [settings, cpuData, memoryData, gpuData, labels]);
return (
<LineChart labels={labels} chartData={graphicUsageHistory} dataType="gpu" />
);
};

useEffect(() => {
const interval = setInterval(fetchData, 1000);
return () => clearInterval(interval);
}, [fetchData]);
const ChartTemplate = () => {
const [settings] = useAtom(settingsAtom);

const renderedCharts = useMemo(() => {
return (
<>
{settings?.display_targets.includes("cpu") && (
<LineChart labels={labels} chartData={cpuData} dataType="cpu" />
)}
{settings?.display_targets.includes("memory") && (
<LineChart labels={labels} chartData={memoryData} dataType="memory" />
)}
{settings?.display_targets.includes("gpu") && (
<LineChart labels={labels} chartData={gpuData} dataType="gpu" />
)}
{settings?.display_targets.includes("cpu") && <CpuUsageChart />}
{settings?.display_targets.includes("memory") && <MemoryUsageChart />}
{settings?.display_targets.includes("gpu") && <GpuUsageChart />}
</>
);
}, [labels, cpuData, memoryData, gpuData, settings]);
}, [settings]);

return <div className="chart-container">{renderedCharts}</div>;
};
Expand Down
4 changes: 3 additions & 1 deletion src/types/settingsType.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
import type { ChartDataType } from "./chartType";

export type Settings = {
language: string;
theme: "light" | "dark";
display_targets: "cpu" | "memory" | "gpu";
display_targets: Array<ChartDataType>;
};