fix: correct memory display to use actual usage instead of cache-inclusive

memory.used from systeminformation includes disk cache/buffers,
showing ~91% when actual usage is ~18%. Now uses (total - available)
which matches htop/free output. Also added PB/EB units to formatBytes.
This commit is contained in:
Fringg
2026-02-23 19:27:18 +03:00
parent e8acfee3e4
commit 67bacd3e7a
4 changed files with 18 additions and 12 deletions

View File

@@ -411,8 +411,8 @@ export default function AdminBanSystem() {
const formatBytes = (bytes: number) => { const formatBytes = (bytes: number) => {
if (bytes === 0) return '0 B'; if (bytes === 0) return '0 B';
const k = 1024; const k = 1024;
const sizes = ['B', 'KB', 'MB', 'GB', 'TB']; const sizes = ['B', 'KB', 'MB', 'GB', 'TB', 'PB', 'EB'];
const i = Math.floor(Math.log(bytes) / Math.log(k)); const i = Math.min(Math.floor(Math.log(bytes) / Math.log(k)), sizes.length - 1);
return `${parseFloat((bytes / Math.pow(k, i)).toFixed(2))} ${sizes[i]}`; return `${parseFloat((bytes / Math.pow(k, i)).toFixed(2))} ${sizes[i]}`;
}; };

View File

@@ -42,8 +42,8 @@ const BackIcon = () => (
const formatBytes = (bytes: number): string => { const formatBytes = (bytes: number): string => {
if (bytes === 0) return '0 B'; if (bytes === 0) return '0 B';
const k = 1024; const k = 1024;
const sizes = ['B', 'KB', 'MB', 'GB', 'TB']; const sizes = ['B', 'KB', 'MB', 'GB', 'TB', 'PB', 'EB'];
const i = Math.floor(Math.log(bytes) / Math.log(k)); const i = Math.min(Math.floor(Math.log(bytes) / Math.log(k)), sizes.length - 1);
return parseFloat((bytes / Math.pow(k, i)).toFixed(2)) + ' ' + sizes[i]; return parseFloat((bytes / Math.pow(k, i)).toFixed(2)) + ' ' + sizes[i];
}; };
@@ -363,9 +363,15 @@ function OverviewTab({ stats, isLoading, onRefresh }: OverviewTabProps) {
); );
} }
// Use (total - available) instead of raw "used" to exclude disk cache/buffers
// This matches what htop/free show as actual application memory usage
const memoryActualUsed =
stats.server_info.memory_available > 0
? stats.server_info.memory_total - stats.server_info.memory_available
: stats.server_info.memory_used;
const memoryUsedPercent = const memoryUsedPercent =
stats.server_info.memory_total > 0 stats.server_info.memory_total > 0
? Math.round((stats.server_info.memory_used / stats.server_info.memory_total) * 100) ? Math.round((memoryActualUsed / stats.server_info.memory_total) * 100)
: 0; : 0;
return ( return (
@@ -446,7 +452,7 @@ function OverviewTab({ stats, isLoading, onRefresh }: OverviewTabProps) {
<StatCard <StatCard
label={t('admin.remnawave.overview.memory', 'Memory')} label={t('admin.remnawave.overview.memory', 'Memory')}
value={`${memoryUsedPercent}%`} value={`${memoryUsedPercent}%`}
subValue={`${formatBytes(stats.server_info.memory_used)} / ${formatBytes(stats.server_info.memory_total)}`} subValue={`${formatBytes(memoryActualUsed)} / ${formatBytes(stats.server_info.memory_total)}`}
icon={<span className="text-lg">💾</span>} icon={<span className="text-lg">💾</span>}
color={memoryUsedPercent > 80 ? 'red' : memoryUsedPercent > 60 ? 'orange' : 'green'} color={memoryUsedPercent > 80 ? 'red' : memoryUsedPercent > 60 ? 'orange' : 'green'}
/> />

View File

@@ -35,8 +35,8 @@ declare module '@tanstack/react-table' {
const formatBytes = (bytes: number): string => { const formatBytes = (bytes: number): string => {
if (!Number.isFinite(bytes) || bytes <= 0) return '0 B'; if (!Number.isFinite(bytes) || bytes <= 0) return '0 B';
const k = 1024; const k = 1024;
const sizes = ['B', 'KB', 'MB', 'GB', 'TB']; const sizes = ['B', 'KB', 'MB', 'GB', 'TB', 'PB', 'EB'];
const i = Math.floor(Math.log(bytes) / Math.log(k)); const i = Math.min(Math.floor(Math.log(bytes) / Math.log(k)), sizes.length - 1);
return parseFloat((bytes / Math.pow(k, i)).toFixed(2)) + ' ' + sizes[i]; return parseFloat((bytes / Math.pow(k, i)).toFixed(2)) + ' ' + sizes[i];
}; };

View File

@@ -766,10 +766,10 @@ export default function AdminUserDetail() {
const formatBytes = (bytes: number) => { const formatBytes = (bytes: number) => {
if (bytes === 0) return '0 B'; if (bytes === 0) return '0 B';
if (bytes < 1024) return `${bytes} B`; const k = 1024;
if (bytes < 1024 * 1024) return `${(bytes / 1024).toFixed(1)} KB`; const sizes = ['B', 'KB', 'MB', 'GB', 'TB', 'PB', 'EB'];
if (bytes < 1024 * 1024 * 1024) return `${(bytes / (1024 * 1024)).toFixed(1)} MB`; const i = Math.min(Math.floor(Math.log(bytes) / Math.log(k)), sizes.length - 1);
return `${(bytes / (1024 * 1024 * 1024)).toFixed(2)} GB`; return `${parseFloat((bytes / Math.pow(k, i)).toFixed(2))} ${sizes[i]}`;
}; };
const copyToClipboard = async (text: string) => { const copyToClipboard = async (text: string) => {