Skip to content

Commit 7f85f33

Browse files
committed
seperated roblox memory trimming to its own thing
1 parent c0f1a78 commit 7f85f33

10 files changed

Lines changed: 431 additions & 184 deletions

File tree

Bloxstrap/App.xaml.cs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,8 @@ public partial class App : Application
5252

5353
public FroststrapRichPresence RichPresence { get; private set; } = null!;
5454

55+
public static MemoryCleaner MemoryCleaner { get; private set; } = null!;
56+
5557
public static bool IsActionBuild => !String.IsNullOrEmpty(BuildMetadata.CommitRef);
5658

5759
public static bool IsProductionBuild => IsActionBuild && BuildMetadata.CommitRef.StartsWith("tag", StringComparison.Ordinal);

Bloxstrap/Integrations/MemoryCleaner.cs

Lines changed: 224 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
using System.Runtime.InteropServices;
22
using System.Timers;
33
using System.Diagnostics;
4+
using System.ComponentModel;
45

56
namespace Bloxstrap.Integrations
67
{
@@ -9,6 +10,7 @@ public class MemoryCleaner : IDisposable
910
private const string LOG_IDENT = "MemoryCleaner";
1011

1112
private System.Timers.Timer? _cleanupTimer;
13+
private System.Timers.Timer? _robloxTrimTimer;
1214
private bool _isCleaning = false;
1315
private readonly object _cleanupLock = new object();
1416

@@ -18,7 +20,6 @@ public class MemoryCleaner : IDisposable
1820
[DllImport("psapi.dll", SetLastError = true)]
1921
private static extern int EmptyWorkingSet(IntPtr hProcess);
2022

21-
2223
[DllImport("kernel32.dll", SetLastError = true)]
2324
private static extern IntPtr GetCurrentProcess();
2425

@@ -28,6 +29,8 @@ public class MemoryCleaner : IDisposable
2829
"smss", "svchost", "explorer", "taskhostw", "dwm", "ctfmon"
2930
};
3031

32+
private readonly HashSet<string> _robloxProcessNames = new HashSet<string>(StringComparer.OrdinalIgnoreCase) { "robloxplayerbeta", "robloxstudiobeta" };
33+
3134
public MemoryCleaner()
3235
{
3336
InitializeTimer();
@@ -40,6 +43,7 @@ private void InitializeTimer()
4043
try
4144
{
4245
UpdateTimer();
46+
UpdateRobloxTrimTimer();
4347
App.Logger.WriteLine(LOG_IDENT_INIT, "Memory cleaner initialized");
4448
}
4549
catch (Exception ex)
@@ -71,6 +75,66 @@ private void UpdateTimer()
7175
App.Logger.WriteLine($"{LOG_IDENT}::UpdateTimer", $"Timer started with {interval} interval");
7276
}
7377

78+
private void UpdateRobloxTrimTimer()
79+
{
80+
_robloxTrimTimer?.Stop();
81+
_robloxTrimTimer?.Dispose();
82+
_robloxTrimTimer = null;
83+
84+
if (!App.Settings.Prop.EnableRobloxTrim || App.Settings.Prop.RobloxTrimIntervalSeconds <= 0)
85+
{
86+
App.Logger.WriteLine($"{LOG_IDENT}::UpdateRobloxTrimTimer", "Roblox-specific trimming disabled");
87+
return;
88+
}
89+
90+
int intervalSeconds = App.Settings.Prop.RobloxTrimIntervalSeconds;
91+
92+
_robloxTrimTimer = new System.Timers.Timer();
93+
_robloxTrimTimer.Interval = intervalSeconds * 1000;
94+
_robloxTrimTimer.Elapsed += OnRobloxTrimTimerElapsed;
95+
_robloxTrimTimer.AutoReset = true;
96+
_robloxTrimTimer.Start();
97+
98+
App.Logger.WriteLine($"{LOG_IDENT}::UpdateRobloxTrimTimer", $"Roblox trim timer started with {intervalSeconds} second interval");
99+
}
100+
101+
private void OnRobloxTrimTimerElapsed(object? sender, ElapsedEventArgs e)
102+
{
103+
const string LOG_IDENT_TIMER = $"{LOG_IDENT}::OnRobloxTrimTimerElapsed";
104+
105+
try
106+
{
107+
if (_isCleaning)
108+
{
109+
App.Logger.WriteLine(LOG_IDENT_TIMER, "Cleanup already in progress, skipping Roblox trim...");
110+
return;
111+
}
112+
113+
App.Logger.WriteLine(LOG_IDENT_TIMER, "Roblox trim timer elapsed, trimming Roblox processes");
114+
115+
lock (_cleanupLock)
116+
{
117+
_isCleaning = true;
118+
}
119+
120+
try
121+
{
122+
TrimRobloxProcesses();
123+
}
124+
finally
125+
{
126+
lock (_cleanupLock)
127+
{
128+
_isCleaning = false;
129+
}
130+
}
131+
}
132+
catch (Exception ex)
133+
{
134+
App.Logger.WriteLine(LOG_IDENT_TIMER, $"Exception: {ex.Message}");
135+
}
136+
}
137+
74138
private void OnCleanupTimerElapsed(object? sender, ElapsedEventArgs e)
75139
{
76140
const string LOG_IDENT_TIMER = $"{LOG_IDENT}::OnCleanupTimerElapsed";
@@ -110,7 +174,6 @@ public void CleanMemory()
110174
App.Logger.WriteLine(LOG_IDENT_CLEAN, $"Total memory before cleanup: {FormatBytes(beforeMemory)}");
111175

112176
CleanStandbyList();
113-
114177
CleanProcessWorkingSets();
115178

116179
long afterMemory = GetTotalMemoryUsage();
@@ -135,6 +198,159 @@ public void CleanMemory()
135198
}
136199
}
137200

201+
public void TrimRobloxProcesses()
202+
{
203+
const string LOG_IDENT_ROBLOX = $"{LOG_IDENT}::TrimRobloxProcesses";
204+
205+
try
206+
{
207+
int robloxProcessesFound = 0;
208+
int robloxProcessesTrimmed = 0;
209+
long totalRobloxMemoryFreed = 0;
210+
211+
foreach (var process in Process.GetProcesses())
212+
{
213+
try
214+
{
215+
string processName = process.ProcessName.ToLower();
216+
217+
if (_robloxProcessNames.Contains(processName) && !process.HasExited)
218+
{
219+
robloxProcessesFound++;
220+
221+
long beforeMemory = process.WorkingSet64;
222+
App.Logger.WriteLine(LOG_IDENT_ROBLOX,
223+
$"Found Roblox process: {process.ProcessName} (PID: {process.Id}) using {FormatBytes(beforeMemory)}");
224+
225+
if (TrimRobloxProcessMemory(process))
226+
{
227+
process.Refresh();
228+
long afterMemory = process.WorkingSet64;
229+
long memoryFreed = beforeMemory - afterMemory;
230+
231+
if (memoryFreed > 0)
232+
{
233+
robloxProcessesTrimmed++;
234+
totalRobloxMemoryFreed += memoryFreed;
235+
236+
App.Logger.WriteLine(LOG_IDENT_ROBLOX,
237+
$"Trimmed Roblox process {process.ProcessName}: {FormatBytes(memoryFreed)} freed");
238+
}
239+
}
240+
}
241+
}
242+
catch (Exception ex)
243+
{
244+
App.Logger.WriteLine(LOG_IDENT_ROBLOX, $"Error processing Roblox process: {ex.Message}");
245+
}
246+
finally
247+
{
248+
process.Dispose();
249+
}
250+
}
251+
252+
App.Logger.WriteLine(LOG_IDENT_ROBLOX,
253+
$"Roblox trimming complete: {robloxProcessesTrimmed}/{robloxProcessesFound} processes trimmed, " +
254+
$"total freed: {FormatBytes(totalRobloxMemoryFreed)}");
255+
}
256+
catch (Exception ex)
257+
{
258+
App.Logger.WriteLine(LOG_IDENT_ROBLOX, $"Exception trimming Roblox processes: {ex.Message}");
259+
}
260+
}
261+
262+
private bool TrimRobloxProcessMemory(Process process)
263+
{
264+
const string LOG_IDENT_ROBLOX_TRIM = $"{LOG_IDENT}::TrimRobloxProcessMemory";
265+
266+
try
267+
{
268+
if (process.HasExited)
269+
return false;
270+
271+
if (!process.Responding)
272+
{
273+
App.Logger.WriteLine(LOG_IDENT_ROBLOX_TRIM,
274+
$"Roblox process {process.ProcessName} (PID: {process.Id}) is not responding");
275+
return false;
276+
}
277+
278+
bool success = true;
279+
280+
try
281+
{
282+
SetProcessWorkingSetSize(process.Handle, (IntPtr)(-1), (IntPtr)(-1));
283+
}
284+
catch (Exception ex)
285+
{
286+
App.Logger.WriteLine(LOG_IDENT_ROBLOX_TRIM,
287+
$"SetProcessWorkingSetSize failed for {process.ProcessName}: {ex.Message}");
288+
success = false;
289+
}
290+
291+
try
292+
{
293+
EmptyWorkingSet(process.Handle);
294+
}
295+
catch (Exception ex)
296+
{
297+
App.Logger.WriteLine(LOG_IDENT_ROBLOX_TRIM,
298+
$"EmptyWorkingSet failed for {process.ProcessName}: {ex.Message}");
299+
success = false;
300+
}
301+
302+
Thread.Sleep(50);
303+
304+
return success;
305+
}
306+
catch (Exception ex)
307+
{
308+
App.Logger.WriteLine(LOG_IDENT_ROBLOX_TRIM,
309+
$"Failed to trim Roblox process {process.ProcessName} (PID: {process.Id}): {ex.Message}");
310+
return false;
311+
}
312+
}
313+
314+
public void TrimRobloxNow()
315+
{
316+
const string LOG_IDENT_MANUAL = $"{LOG_IDENT}::TrimRobloxNow";
317+
318+
lock (_cleanupLock)
319+
{
320+
if (_isCleaning)
321+
{
322+
App.Logger.WriteLine(LOG_IDENT_MANUAL, "Cleanup already in progress, skipping manual Roblox trim");
323+
return;
324+
}
325+
326+
_isCleaning = true;
327+
}
328+
329+
try
330+
{
331+
App.Logger.WriteLine(LOG_IDENT_MANUAL, "Manual Roblox memory trim requested");
332+
TrimRobloxProcesses();
333+
OnRobloxTrimmed?.Invoke(this, EventArgs.Empty);
334+
}
335+
catch (Exception ex)
336+
{
337+
App.Logger.WriteLine(LOG_IDENT_MANUAL, $"Exception during manual Roblox trim: {ex.Message}");
338+
OnCleanupError?.Invoke(this, ex.Message);
339+
}
340+
finally
341+
{
342+
lock (_cleanupLock)
343+
{
344+
_isCleaning = false;
345+
}
346+
}
347+
}
348+
349+
public void RefreshRobloxTimer()
350+
{
351+
UpdateRobloxTrimTimer();
352+
}
353+
138354
private void CleanStandbyList()
139355
{
140356
const string LOG_IDENT_STANDBY = $"{LOG_IDENT}::CleanStandbyList";
@@ -219,6 +435,9 @@ private bool IsProcessSafeToClean(Process process)
219435

220436
string processName = process.ProcessName.ToLower();
221437

438+
if (_robloxProcessNames.Contains(processName))
439+
return false;
440+
222441
if (_criticalProcesses.Contains(processName))
223442
return false;
224443

@@ -329,6 +548,8 @@ public void Dispose()
329548
{
330549
_cleanupTimer?.Stop();
331550
_cleanupTimer?.Dispose();
551+
_robloxTrimTimer?.Stop();
552+
_robloxTrimTimer?.Dispose();
332553
App.Logger.WriteLine(LOG_IDENT_DISPOSE, "Memory cleaner disposed");
333554
}
334555
catch (Exception ex)
@@ -339,5 +560,6 @@ public void Dispose()
339560

340561
public event EventHandler<long>? OnMemoryCleaned;
341562
public event EventHandler<string>? OnCleanupError;
563+
public event EventHandler? OnRobloxTrimmed;
342564
}
343565
}

Bloxstrap/Models/Persistable/Settings.cs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,9 @@ public class Settings
3030
public bool ConfirmLaunches { get; set; } = true;
3131
public bool AutoCloseCrashHandler { get; set; } = false;
3232
public MemoryCleanerInterval MemoryCleanerInterval { get; set; } = MemoryCleanerInterval.Never;
33-
public ObservableCollection<string> UserExcludedProcesses { get; set; } = new ObservableCollection<string> { "robloxplayerbeta" };
33+
public ObservableCollection<string> UserExcludedProcesses { get; set; } = new();
34+
public int RobloxTrimIntervalSeconds { get; set; } = 60;
35+
public bool EnableRobloxTrim { get; set; } = true;
3436
public string Locale { get; set; } = "nil";
3537
public CleanerOptions CleanerOptions { get; set; } = CleanerOptions.Never;
3638
public List<string> CleanerDirectories { get; set; } = new List<string>();

Bloxstrap/UI/Elements/AccountManager/Pages/FriendsPage.xaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -126,7 +126,7 @@
126126
Height="30"
127127
IsEnabled="{Binding IsOnline}"
128128
Visibility="{Binding DataContext.IsBulkMode, RelativeSource={RelativeSource AncestorType=ItemsControl}, Converter={StaticResource InverseBooleanToVisibilityConverter}}">
129-
<ui:SymbolIcon Filled="True" Symbol="Play24" FontSize="16" />
129+
<ui:SymbolIcon Filled="True" Symbol="Play24" FontSize="16" Foreground="White" />
130130
</ui:Button>
131131

132132
<ToggleButton

0 commit comments

Comments
 (0)