Skip to content

Commit e208736

Browse files
authored
Display the process memory usage instead of GC (Configurable) (#1062)
* Memory * 更新 MemoryCounter.hx * legacyMemoryCounter * fix
1 parent 13eb003 commit e208736

12 files changed

Lines changed: 143 additions & 5 deletions

File tree

assets/languages/en/Options.xml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -206,6 +206,9 @@
206206

207207
<str id="songOffsetAffectEditors-name">Offset in Charter</str>
208208
<str id="songOffsetAffectEditors-desc">If checked, this will enable the Song Offset option in the Chart Editor too.</str>
209+
210+
<str id="legacyMemoryCounter-name">Legacy Memory Counter</str>
211+
<str id="legacyMemoryCounter-desc">If checked, the memory counter will show the Haxe GC memory usage and its peak (the original behavior) instead of the working set memory seen in Task Manager.</str>
209212
</group>
210213

211214
</language>

assets/languages/es/Options.xml

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -180,6 +180,9 @@
180180
<str id="charterAutoSaveWarningTime-desc">Esto controla por cuánto tiempo te advertirá el editor antes de autoguardar (en segundos..., 0 para desactivar)</str>
181181

182182
<str id="charterAutoSavesSeparateFolder-name">Carpeta de Autoguardados</str>
183-
<str id="charterAutoSavesSeparateFolder-desc">Si está activado, el autoguardado se guardará en otra carpeta con su fecha en vez de sobreescribir el archivo actual. (song/autosaves/)</str> </group>
183+
<str id="charterAutoSavesSeparateFolder-desc">Si está activado, el autoguardado se guardará en otra carpeta con su fecha en vez de sobreescribir el archivo actual. (song/autosaves/)</str>
184+
185+
<str id="legacyMemoryCounter-name">Contador de Memoria Clásico</str>
186+
<str id="legacyMemoryCounter-desc">Si está activado, el contador de memoria mostrará el uso de memoria del GC de Haxe y su máximo (el comportamiento original) en vez de la memoria de trabajo vista en el Administrador de Tareas.</str> </group>
184187

185188
</language>

assets/languages/it/Options.xml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -199,5 +199,8 @@
199199

200200
<str id="songOffsetAffectEditors-name">Offset Editor Chart</str>
201201
<str id="songOffsetAffectEditors-desc">Se abilitato, questo attiverà l'opzione Offset Canzone anche nel Editor Chart.</str>
202+
203+
<str id="legacyMemoryCounter-name">Contatore Memoria Classico</str>
204+
<str id="legacyMemoryCounter-desc">Se attivato, il contatore di memoria mostrerà l'uso di memoria del GC di Haxe e il suo picco (il comportamento originale) invece della memoria di lavoro vista nel Task Manager.</str>
202205
</group>
203206
</language>

assets/languages/pl/Options.xml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -175,6 +175,9 @@
175175

176176
<str id="charterAutoSavesSeparateFolder-name">Folder Autozapisów</str>
177177
<str id="charterAutoSavesSeparateFolder-desc">Jeśli włączone, Edytor będzie zapisywać pliki w osobnym folderze, zamiast nadpisywania aktualnego pliku. (song/autosaves/)</str>
178+
179+
<str id="legacyMemoryCounter-name">Klasyczny Licznik Pamięci</str>
180+
<str id="legacyMemoryCounter-desc">Jeśli włączone, licznik pamięci pokaże użycie pamięci GC Haxe i jego szczyt (oryginalne zachowanie) zamiast pamięci roboczej widocznej w Menedżerze Zadań.</str>
178181
</group>
179182

180183
</language>

assets/languages/pt/Options.xml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -206,6 +206,9 @@
206206

207207
<str id="songOffsetAffectEditors-name">Atraso no Mapeador</str>
208208
<str id="songOffsetAffectEditors-desc">Se marcado, irá ativar o Atraso da Música no Editor de Mapas, também.</str>
209+
210+
<str id="legacyMemoryCounter-name">Contador de Memória Clássico</str>
211+
<str id="legacyMemoryCounter-desc">Se marcado, o contador de memória mostrará o uso de memória do GC de Haxe e o seu máximo (o comportamento original) em vez da memória de trabalho vista no Gerenciador de Tarefas.</str>
209212
</group>
210213

211214
</language>

source/funkin/backend/system/framerate/MemoryCounter.hx

Lines changed: 45 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -28,14 +28,57 @@ class MemoryCounter extends Sprite {
2828
addChild(label);
2929
}
3030
memoryPeakText.alpha = 0.5;
31+
#if !(cpp && (windows || mac || linux))
32+
memoryPeakText.visible = false;
33+
#end
3134
}
3235

3336
public function reload() {}
3437

38+
private var usingLegacy:Bool = false;
39+
3540
public override function __enterFrame(t:Int) {
3641
if (alpha <= 0.05) return;
3742
super.__enterFrame(t);
3843

44+
#if (cpp && (windows || mac || linux))
45+
var legacy = funkin.options.Options.legacyMemoryCounter;
46+
47+
if (legacy) {
48+
if (legacy != usingLegacy) {
49+
usingLegacy = legacy;
50+
memoryPeak = 0;
51+
}
52+
53+
final mem = MemoryUtil.currentMemUsage();
54+
if (memoryPeak < mem) memoryPeak = mem;
55+
if (mem == memory) {
56+
updateLabelPosition();
57+
return;
58+
}
59+
60+
memory = mem;
61+
memoryPeakText.visible = true;
62+
memoryText.text = CoolUtil.getSizeString(memory);
63+
memoryPeakText.text = ' / ${CoolUtil.getSizeString(memoryPeak)}';
64+
} else {
65+
if (legacy != usingLegacy) usingLegacy = legacy;
66+
67+
final gcMem = MemoryUtil.currentMemUsage();
68+
final osMem = MemoryUtil.currentProcessMemUsage();
69+
70+
if (gcMem == memory && osMem == memoryPeak) {
71+
updateLabelPosition();
72+
return;
73+
}
74+
75+
memory = gcMem;
76+
memoryPeak = osMem;
77+
memoryPeakText.visible = true;
78+
memoryText.text = CoolUtil.getSizeString(gcMem);
79+
memoryPeakText.text = ' / ${CoolUtil.getSizeString(osMem)}';
80+
}
81+
#else
3982
final mem = MemoryUtil.currentMemUsage();
4083

4184
if (mem == memory) {
@@ -44,9 +87,8 @@ class MemoryCounter extends Sprite {
4487
}
4588

4689
memory = mem;
47-
if (memoryPeak < memory) memoryPeak = memory;
48-
memoryText.text = CoolUtil.getSizeString(memory);
49-
memoryPeakText.text = ' / ${CoolUtil.getSizeString(memoryPeak)}';
90+
memoryText.text = CoolUtil.getSizeString(mem);
91+
#end
5092

5193
updateLabelPosition();
5294
}

source/funkin/backend/utils/MemoryUtil.hx

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -119,6 +119,23 @@ final class MemoryUtil {
119119
#end
120120
}
121121

122+
/**
123+
* Gets the current process memory usage (Working Set / RSS) from the OS.
124+
* This is much more granular than Haxe GC memory and updates more frequently.
125+
* Returns the value in bytes, matching what you see in Task Manager / Activity Monitor.
126+
*/
127+
public static inline function currentProcessMemUsage():Float {
128+
#if (cpp && windows)
129+
return funkin.backend.utils.native.Windows.getCurrentProcessMemory();
130+
#elseif (cpp && mac)
131+
return funkin.backend.utils.native.Mac.getCurrentProcessMemory();
132+
#elseif (cpp && linux)
133+
return funkin.backend.utils.native.Linux.getCurrentProcessMemory();
134+
#else
135+
return currentMemUsage();
136+
#end
137+
}
138+
122139

123140
/**
124141
* Gets the memory type of the system.

source/funkin/backend/utils/native/Linux.hx

Lines changed: 34 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
package funkin.backend.utils.native;
22

33
#if linux
4-
@:cppFileCode("#include <stdio.h>")
4+
@:cppFileCode("#include <stdio.h>\n#include <time.h>")
55
@:dox(hide)
66
final class Linux {
77
@:functionCode('
@@ -28,5 +28,38 @@ final class Linux {
2828
{
2929
return 0;
3030
}
31+
32+
@:functionCode('
33+
struct timespec now;
34+
clock_gettime(CLOCK_MONOTONIC, &now);
35+
long long nowMs = now.tv_sec * 1000LL + now.tv_nsec / 1000000LL;
36+
37+
// cache the value and only re-read /proc every 500ms, to avoid polling the kernel file every frame
38+
static long long lastReadMs = 0;
39+
static double cached = 0.0;
40+
41+
if (cached != 0.0 && (nowMs - lastReadMs) < 500)
42+
return cached;
43+
44+
lastReadMs = nowMs;
45+
46+
FILE *status = fopen("/proc/self/status", "r");
47+
if (status == NULL) return cached;
48+
49+
char line[256];
50+
while (fgets(line, sizeof(line), status)) {
51+
unsigned long long rss; // use 64-bit so the kB -> bytes conversion never overflows on 32-bit builds
52+
if (sscanf(line, "VmRSS: %llu kB", &rss) == 1) {
53+
fclose(status);
54+
return cached = (double)rss * 1024.0; // kB -> bytes
55+
}
56+
}
57+
fclose(status);
58+
return cached;
59+
')
60+
public static function getCurrentProcessMemory():Float
61+
{
62+
return 0;
63+
}
3164
}
3265
#end

source/funkin/backend/utils/native/Mac.hx

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ import funkin.backend.utils.NativeAPI.CodeCursor;
55
import openfl.ui.Mouse;
66

77
@:headerInclude('sys/sysctl.h')
8+
@:headerInclude('mach/mach.h')
89
@:dox(hide)
910
final class Mac
1011
{
@@ -23,6 +24,19 @@ final class Mac
2324
return 0;
2425
}
2526

27+
@:functionCode('
28+
task_basic_info_data_t info;
29+
mach_msg_type_number_t count = TASK_BASIC_INFO_COUNT;
30+
if (task_info(mach_task_self(), TASK_BASIC_INFO, (task_info_t)&info, &count) == KERN_SUCCESS) {
31+
return (double)info.resident_size;
32+
}
33+
return 0.0;
34+
')
35+
public static function getCurrentProcessMemory():Float
36+
{
37+
return 0;
38+
}
39+
2640
public static function setMouseCursorIcon(icon:CodeCursor):Void
2741
{
2842
final valid:Bool = external.ExternalMac.setCursorIcon(icon.toInt(), null, 0, 0);

source/funkin/backend/utils/native/Windows.hx

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@ import funkin.backend.utils.NativeAPI.MessageBoxIcon;
2727
#include <wingdi.h>
2828
#include <shellapi.h>
2929
#include <uxtheme.h>
30+
#include <psapi.h>
3031

3132
#define SAFE_RELEASE(punk) \\
3233
if ((punk) != NULL) \\
@@ -267,5 +268,17 @@ final class Windows {
267268
{
268269
return 0;
269270
}
271+
272+
@:functionCode("
273+
PROCESS_MEMORY_COUNTERS_EX pmc;
274+
if (GetProcessMemoryInfo(GetCurrentProcess(), (PROCESS_MEMORY_COUNTERS*)&pmc, sizeof(pmc))) {
275+
return (double)pmc.WorkingSetSize;
276+
}
277+
return 0.0;
278+
")
279+
public static function getCurrentProcessMemory():Float
280+
{
281+
return 0;
282+
}
270283
}
271284
#end

0 commit comments

Comments
 (0)