 |
|
 |
The working set stuff is good (Job Objects also control working sets), but that's not total memory usage, only real memory usage (paged in) at any one time. Summary you cannot control the total allocated memory.
Look at the definition in the msdn link you have provided for the method call:
"The working set of a process is the set of memory pages currently visible to the process in physical RAM memory. These pages are resident and available for an application to use without triggering a page fault.
"
rv
|
|
|
|
 |
|
|
 |
|
|
 |
|
 |
Hello,
Great article and easy to implement.
I'd appreciate if you'll explain and show how to use and dispose a running job.
BTW, I'm using VS2008Express.
Thanks.
Oren
|
|
|
|
 |
|
 |
Hi, it should work as above. Do you get an error?
|
|
|
|
 |
|
 |
Hi,
First I really appreciate your fast response.
I have no problem set limits to a running process, but I don't know how to stop/dispose or make changes to the limits while the process still running.
Currently, I have to stop or kill the limited process, make change to the limits settings and run the process again.
Thanks,
Oren
|
|
|
|
 |
|
 |
Hi, I haven't tried it, but I believe that once the Job object is disposed the limits on the process should go "back to normal." In the Dispose() method of Win32.Job it calls kernel32.dll::CloseHandle on the WIN32 Job object handle. Supposedly this should remove the connection of the job to the process.
Therefore, in the above example, I put "HERE" where there should no longer be any job limits -- i.e. after the Job is disposed but before the Process is disposed:
using (Process p = new Process())
{
p.StartInfo = new ProcessStartInfo("myexe.exe");
p.Start();
using (PublicDomain.Win32.Job j = PublicDomain.Win32.Job.CreateJobWithMemoryLimits(
(uint)GlobalConstants.BytesInAMegabyte * 12,
(uint)GlobalConstants.BytesInAMegabyte * 30,
p))
{
}
}
|
|
|
|
 |
|
 |
Hi,
What I'm trying to do is, I have an application running. this application does not have this procedure in it and it impossible to add or start this app using this code. So what
I've done is building a small app that monitors the running processes. if the app is running, i perform the limits on the running process.
This is the code i wrote and it is working:
public void SetHardLimit(string ProcessName,uint ProcessMinSize, uint ProcessMaxSize)
{
Process[] processlist = Process.GetProcessesByName(ProcessName);
Win32.Job job = new Win32.Job(StringUtilities.RandomString(10, true));
job.SetLimitWorkingSetSize(ProcessMinSize, ProcessMaxSize);
foreach (Process p in processlist)
{
try
{
job.AssignProcess(p);
}
catch
{
}
}
}
Can you tell me how to dispose the handle of the limited process?
Thanks,
Oren
|
|
|
|
 |
|
 |
Ahh, I see. You call a method called SetHardLimit, and I'm assuming that you will want to remove these limits at a later time? If that's the case, then you should return the Win32.Job object from the SetHardLimit and later, call its Dispose method, e.g.:
public Win32.Job SetHardLimit(string ProcessName,uint ProcessMinSize, uint ProcessMaxSize)
{
...
return job;
}
private Win32.Job m_job;
public void SetLimits()
{
RemoveLimits();
m_job = SetHardLimit("...", 11111, 1111);
}
public void RemoveLimits()
{
if (m_job != null)
{
m_job.Dispose();
m_job = null;
}
}
Also, you should never have a blank catch {} block. You should at least log the exception somewhere or have the ability to log the exception somewhere by enabling exception tracing (e.g. Log4Net, PublicDomain.Logger, etc.).
|
|
|
|
 |
|
 |
BTW, the documentation for AssignProcessToJobObject says:
"A process can be associated only with a single job."
I'm not sure about how many processes a single Job can be assigned to. You should definitely test your code thoroughly. Also, read the MSDN documentation for the various calls.
|
|
|
|
 |
|
 |
hi. This is exactly what i want to do. thanks for the code and just to make sure i am not mistaking in my writing i attached my code sample based on your reply.
also, i have added an exception to the catch.
the problem now is that when running SetLimits() on the process for the second time, i get and 'access denied' exception.
i am building and running the code using Administrator user.
also, RemoveLimits() wont work.
Appreciate your help and time
Thanks,
Oren
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using PublicDomain;
using System.Diagnostics;
namespace WindowsFormsApplication1
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private Win32.Job m_job;
public static Win32.Job CreateJobWithMemoryLimits(
uint minWorkingSetSize,
uint maxWorkingSetSize,
params Process[] processesToLimit)
{
Win32.Job job = new Win32.Job(StringUtilities.RandomString(10, true));
job.SetLimitWorkingSetSize(minWorkingSetSize, maxWorkingSetSize);
foreach (Process p in processesToLimit)
{
try
{
job.AssignProcess(p);
}
catch (Exception e)
{
MessageBox.Show(e.ToString());
}
}
return job;
}
public void RemoveLimits()
{
if (m_job != null)
{
m_job.Dispose();
m_job = null;
}
}
public void ChangeLimits()
{
RemoveLimits();
Process[] ProcessList = Process.GetProcessesByName("MYPROCESSES");
m_job = CreateJobWithMemoryLimits(
uint.Parse(textBox1.Text) * 1048576,
uint.Parse(textBox2.Text) * 1048576,
ProcessList);
}
private void BT1Set_Click(object sender, EventArgs e)
{
ChangeLimits();
}
private void BT3Release_Click(object sender, EventArgs e)
{
RemoveLimits();
}
}
}
|
|
|
|
 |
|
 |
How did you test that RemoveLimits doesn't work? Are you sure there were allocation attempts after the limits were removed on the other process? If this doesn't work, then disposing the Job object may not be enough.
|
|
|
|
 |
|
 |
1.
-i opened TM (task manager). started the code and monitored app.
-in TM the app working set was more the 60mb.
-after running ChangeLimits() with max set to 30mb, in TM the app working set limited to 30mb.
-when running RemoveLimits() there was no change to the app working set.
-when running Change limits() with new max set to 40mb there was no change to the app working set and an access denied exception was thrown.
-when running a second app and running ChangeLimits() again, i get access denied exception for the first app (then one with the 30mb limit) and the second app working set was limited to 30mb.
2.
when running the code in debug mode, you can see the m_handle value saved by m_job when creating the job is disposed when running RemoveLimits().
if that does not work, how will i be able to remove the limits?
Thanks,
Oren
|
|
|
|
 |
|
 |
m_job name after running ChangeLimits() is bctgfkuhnd(1725)
m_name = bctgfkuhnd
m_handle = 1725
when performing m_job.dispose() i noted that only m_handle is turned to null and m_name stays bctgfkuhnd.
is it possible that i need to perform some kind of dispose to the m_name before setting m_job to null?
am i making any sense?
Thanks,
Oren
|
|
|
|
 |
|
 |
Have you had any problems with the following errors w/ using public domain? see below
System.ComponentModel.Win32Exception was unhandled
Message="Access is denied"
Source="PublicDomain"
ErrorCode=-2147467259
NativeErrorCode=5
StackTrace:
at PublicDomain.Win32.GetLastErrorThrow()
at PublicDomain.Win32.Job.CreateJobWithMemoryLimits(UInt32 minWorkingSetSize, UInt32 maxWorkingSetSize, Process[] processesToLimit)
at ConsoleApplication1.Program.Main(String[] args) in G:\TestProcessMemMax\ConsoleApplication1\Program.cs:line 19
at System.AppDomain._nExecuteAssembly(Assembly assembly, String[] args)
at System.AppDomain.ExecuteAssembly(String assemblyFile, Evidence assemblySecurity, String[] args)
at Microsoft.VisualStudio.HostingProcess.HostProc.RunUsersAssembly()
at System.Threading.ThreadHelper.ThreadStart_Context(Object state)
at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state)
at System.Threading.ThreadHelper.ThreadStart()
InnerException:
|
|
|
|
 |
|
 |
Hi, JOB objects require very high permissions. You can either run as an administrator or apply the specific permission the user needs. If you want to do the latter, you need to figure out which permission is failing. Go to Start -> Control Panel -> Administrative Tools -> Local Security Policy -> Local Policies -> Audit Policy -> Double click Audit Privilege Use -> Check "Failure" -> Click OK
Then re-run and get the error then go to My Computer -> Right Click -> Manage -> and check for the failure in the Event Viewer. It should tell you what permission is needed and then you can just give the user that perm...
|
|
|
|
 |
|
 |
What is the maxium amount of memory a .NET app can allocate? I ran a simple test and hit a limit around 1.5-1.6 GB. Can that be increased?
Todd Smith
|
|
|
|
 |
|
 |
Not in a 32Bit Windows. On 64Bit Windows versions the limit should be by far higher.
Robert
|
|
|
|
 |
|
 |
By default 32bit apps are limited to 2gb of memory. The kernel gets the other 2gb in the full 4gb range 32 bits can provide... this can be changed on an OS level (for all processes) to give the kernal 1gb and any app 3gb total memory to use with the /3gb switch in boot.ini.
Here is a link to an article describing the option and what OSs it applies to: http://www.microsoft.com/technet/sysinternals/information/bootini.mspx
Vista uses BCD and no longer uses boot.ini so this option doesn't apply. I am not aware of a similar BCD option.
You can use the msconfig.exe tool and look under the BOOT.INI tab to see where switches go (it doesn't show the 3gb switch as an option though).
|
|
|
|
 |