Get Computer Name in mql4 - page 2

 

because it's a string & not an int look @ http://msdn.microsoft.com/en-us/library/aa364934(v=vs.85).aspx

but what i can't understand is y massing around for such a long time when u have a build in function in mql TerminalPath()

 
1005phillip:

Is there some way to use kernel32.dll to enable my EA to algorithmically determine the current CPU load?

There are some things I'd rather my EA not do if the CPU utilization is currently above a threshold value.

I would think that trading is more important than game playing.

The only thing I could think of would be self-optimizing and for that I would have a batch file delay starting an optimization run while the count of terminals > count of cores.

set termCnt = 0;
for /f "usebackq" %%T in (`tasklist^|find "Terminal.exe"`) do set /a termCnt += 1
if (termCnt LEQ %NUMBER_OF_PROCESSORS%) (
   ping -n 60 localhost >nul&  rem Sleep a minute
   goto loop
)
start new opt
 

It is for self-optimizing and I can't rely on simple count of terminal instances in the tasklist queue as not all instances are performing backtesting. My practical limitations are available CPU cycles, not idle threads.

That said, it would be nice to programmatically know the number of available processors as that would help define the threshold value of CPU utilization.

Is there any way to access "%NUMBER_OF_PROCESSORS%" from within an EA?

 

What I got so far is this:

#import "kernel32.dll"
int GetEnvironmentVariableA(string lpName, string lpBuffer, string nSize);
#import

string buf="";
int result;
result = GetEnvironmentVariableA("NUMBER_OF_PROCESSORS",buf, StringLen(buf));
Print ("NUMBER_OF_PROCESSORS = ",result);
but it returns the value of "1" instead of the correct value of "4". (as verified by requesting %NUMBER_OF_PROCESSORS% in a command prompt)
 

Ah, got it...ignore what I put above, if anyone wants to programmatically extract the number of processors available in their system use the following:

#import "kernel32.dll"
bool ExpandEnvironmentStringsA(string lpSrc, string & lpDst[], string nSize);
#import

string   g[1];

int init()
   {
   g[0]="";
   ExpandEnvironmentStringsA("%NUMBER_OF_PROCESSORS%",g, StringLen(g[0]));
   Print ("%NUMBER_OF_PROCESSORS% = ",StrToInteger(g[0]));
   return(0);
   }
 
hrmmm...this is puzzling me now, the above calls do not work unless I make the prior call to GetEnvironmentVariableA.

Here is what I have to do in order to get the correct processor count reported, no idea why I have to make a call to GetEnvironmentVariableA in order to get ExpandEnvironmentStringsA to function.

#import "kernel32.dll"
int GetEnvironmentVariableA(string lpName, string lpBuffer, string nSize);
bool ExpandEnvironmentStringsA(string lpSrc, string & lpDst[], string nSize);
#import

int      result;
string   g[1];

int init()
   {
   string buf="";
   result = GetEnvironmentVariableA("NUMBER_OF_PROCESSORS",buf, StringLen(buf));
   
   g[0]="";
   result = ExpandEnvironmentStringsA("%NUMBER_OF_PROCESSORS%",g, StringLen(g[0]));
   Print ("%NUMBER_OF_PROCESSORS% = ",StrToInteger(g[0]));
   
   return(0);
   }
This correctly outputs:
2011.02.11 02:37:53     CPU Utilization Monitor USDJPY,M1: %NUMBER_OF_PROCESSORS% = 4
 
1005phillip:
hrmmm...this is puzzling me now, the above calls do not work unless I make the prior call to GetEnvironmentVariableA.

Going back to your original...

result = GetEnvironmentVariableA("NUMBER_OF_PROCESSORS",buf, StringLen(buf)); 
Print ("NUMBER_OF_PROCESSORS = ",result); 

The GetEnvironmentVariable() function puts the value of the variable into the buffer parameter, i.e. "buf". The function's return value is the length of the string. That's why result == 1, because the buf is the single-character string "4".

In other words, there's nothing wrong with your original simpler code except that GetEnvironmentVariable() has two outputs and you're looking at the wrong one.

However, you ought to make two further changes: (a) initialise buf with some dummy data such as "01234567890123456789", and (b) declare the third, "nSize" parameter for GetEnvironmentVariableA() as int rather than string. Otherwise, you are in effect allocating a one-byte memory buffer (the buf variable, consisting of a single null character), and reading a potentially variable amount of data into it with the possibility of overflow.

Failing to initialise buf is only working because you've declared nSize as string rather than int. Therefore, what's happening is that MQL is doing a silent cast of the StringLen integer result to a string, passing the address in memory of that string to GetEnvironmentVariable(), and GetEnvironmentVariable() is then interpreting that value as the size of the buffer - e.g. the string is at memory address 0x43128850 and GetEnvironmentVariable() then believes that the available buffer pointed to by buf is 0x43128850 bytes long.

 
Exactly
1005phillip:

It is for self-optimizing and I can't rely on simple count of terminal instances in the tasklist queue as not all instances are performing backtesting.

You know the number of terminals you have open. Don't exceed terminals+processors.
 
WHRoeder:
You know the number of terminals you have open. Don't exceed terminals+processors.

Actually I don't know the number of terminals, it is variable over time as it depends on the day to day number of clients/brokers/accounts/etc.

I am also deploying the code on a heterogeneous cluster which does not have a processor count that can be hard-coded into the code (nor would I want to anyway), the number of processors available on any given computer will vary, today as well as in the future.

I need the generalized solution, hence my efforts here are focused on developing such.

jjc:

Going back to your original...

The GetEnvironmentVariable() function puts the value of the variable into the buffer parameter, i.e. "buf". The function's return value is the length of the string. That's why result == 1, because the buf is the single-character string "4".

In other words, there's nothing wrong with your original simpler code except that GetEnvironmentVariable() has two outputs and you're looking at the wrong one.

However, you ought to make two further changes: (a) initialise buf with some dummy data such as "01234567890123456789", and (b) declare the third, "nSize" parameter for GetEnvironmentVariableA() as int rather than string. Otherwise, you are in effect allocating a one-byte memory buffer (the buf variable, consisting of a single null character), and reading a potentially variable amount of data into it with the possibility of overflow.

Failing to initialise buf is only working because you've declared nSize as string rather than int. Therefore, what's happening is that MQL is doing a silent cast of the StringLen integer result to a string, passing the address in memory of that string to GetEnvironmentVariable(), and GetEnvironmentVariable() is then interpreting that value as the size of the buffer - e.g. the string is at memory address 0x43128850 and GetEnvironmentVariable() then believes that the available buffer pointed to by buf is 0x43128850 bytes long.


Ah yes, I see it now, thank you very much for investigating the code and pointing out the errors.
#import "kernel32.dll"
bool GetSystemTimes(int & lpIdleTime[], int & lpKernelTime[], int & lpUserTime[]);
int GetEnvironmentVariableA(string lpName, string lpBuffer, int nSize);
#import

int      CurrentBarOpenTime, idle_Initial[1], idle_Final[1], kernel_Initial[1], kernel_Final[1], user_Initial[1], user_Final[1], result, Available_Processors;
string   Processor_Count="01234567890123456789";
double   CPU_Utilization;

//+------------------------------------------------------------------+
//| expert initialization function                                   |
//+------------------------------------------------------------------+
int init()
   {
   
   GetSystemTimes(idle_Initial, kernel_Initial, user_Initial);  // get the initial system times
   
   Sleep(1000);  // sleep 1 second
   
   //http://msdn.microsoft.com/en-us/library/ms724400(v=vs.85).aspx
   GetSystemTimes(idle_Final, kernel_Final, user_Final);  // get the final system times after 1 second wait
   
   //kernel time includes the amount of time the system has been idle, per definition in GetSystemTimes Function
   CPU_Utilization=(kernel_Final[0]-kernel_Initial[0] + user_Final[0]-user_Initial[0]-(idle_Final[0]-idle_Initial[0]))*100./(1.*(kernel_Final[0]-kernel_Initial[0] + user_Final[0]-user_Initial[0]));
   
   Print ("CPU Utilization =  " + DoubleToStr(CPU_Utilization,1) + " %");
   
   result = GetEnvironmentVariableA("NUMBER_OF_PROCESSORS",Processor_Count, StringLen(Processor_Count)); // get the processor count for this computer
   
   Print ("Number of processors = ",StrToInteger(Processor_Count));
   
   Available_Processors = MathFloor(StrToInteger(Processor_Count)*(100.-CPU_Utilization)/100.);
   
   Print ("There are ",Available_Processors," processors available for additional processing");
   
//----
   return(0);
   }
Now it is a simple matter of choosing my minimum threshold for available resources before spawning new auto-optimizer sessions by way of:
if(Available_Processors >= 1) Auto_optimize_allowed=true;
 

For sake of completion, and to help others who might find themselves walking in my footsteps at a future date, I am attaching the include file as well as a rudimentary EA that details the implementation of the call functions in the include file.

Naturally the mqh include file is to be placed in your include folder, the EA mq4 file goes in your experts folder.

Reason: