Results 1 to 14 of 14

Thread: priority of processes on Win2k vs Linux

  1. #1
    Member rbutcher's Avatar
    Join Date
    Mar 2005
    Location
    Sydney Australia
    Posts
    48

    priority of processes on Win2k vs Linux

    I run a few Win2k and Linux machines. I find that Linux pretty accurately manages to run various dc projects at the specified priority i.e. if I set nice to -1 it gets 95% cpu, at 19 it gets 2% (with the exception of Einstein, which always runs at lowest).
    On Win2k I find that almost all dc projects ignore the specified priority, just either taking a pro-rata cpu % whether priority is high or low, or in some cases always taking 100% (e.g. Chronos, Predictor, Folding). World Community Grid always takes lowest priority.
    Is this a result of bad programming, or is there something about running jobs I need to know ?
    thanks
    Rod

  2. #2
    Windows is much more confusing when it comes to priority. In Linux its very simple, its a scale from -19 to 19. Anything with the same number has equal priority. So two DC apps running nice 19 should share the CPU 50/50.

    In Windows, there is process priority *and* thread priority. Even if the process priority is Lowest (what you see in Task Manager), the thread priority might be something else causing it to get more processing time than another process.

    You can find out what the process and thread priorities of your DC prorgams in Windows by using my SetPriority program here:
    http://gilchrist.ca/jeff/SetPriority/index.html

    As long as the process isn't a service, you can change the priority with that program to whatever you want. Once you take a look at the priority settings fro each DC app, I bet you will see that the ones that don't share nicely have different values.

    Hope that helps.

  3. #3
    Originally posted by Digital Parasite

    Hope that helps.
    Helps me a great deal. Thanks so much for that information as well as the program.

  4. #4
    Member rbutcher's Avatar
    Join Date
    Mar 2005
    Location
    Sydney Australia
    Posts
    48
    I'll add my thanks too Jeff !

  5. #5
    Member rbutcher's Avatar
    Join Date
    Mar 2005
    Location
    Sydney Australia
    Posts
    48
    I'v discovered that some DC programs like D2OL, BOINC, Chronos (BOINC based), UD have a habit of starting a new process for a new work unit, hence wrecking the good work done by SetPriority. On linux I've got round this for TSC and D2OL with a cron job that runs every 5 minutes and uses a shell script to find the pid for any current process containing the name Win and reset nice to 19. Looks like D2OLDaddy does something similar on Windows, am I correct ? Is the only way around this for me to write a script (e.g. Perl) which runs say every five minutes, gets the current PID and invoke SetPriority ? Is there a scheduling equivalent of cron on Windows ?
    Thanks
    Rod

  6. #6
    Right, D2OLDaddy does exactly that, designed for D2OL and TSC. It will reset your priority automatically every X seconds that you configure it to do.

    Windows 2000 and XP have something called "Scheduled Tasks" that you can setup to run programs/scripts. Its usually found under Accessories -> System Tools from the start menu. If this is just for D2OL/TSC you need it for, I would suggest using D2OL Daddy in windows since it does all that for you automatically.

  7. #7
    Member rbutcher's Avatar
    Join Date
    Mar 2005
    Location
    Sydney Australia
    Posts
    48
    Below is a Perl script (setpriority.pl) I hacked up which can be scheduled as you describe above, and will translate a (part of) process name to its PID and run SetPriority. It's not a very good Perl program but it works. Requires Perl (e.g. from activestate.com) and Win32::Process::Info to be installed.
    Run it as :-
    setpriority.pl partofprocessname priority threadpriority

    e.g. for LHC :-
    setpriority.pl sixtrack 16384 -1
    ========================================
    #setpriority.pl

    $procname = @ARGV[0];
    $priority = @ARGV[1];
    $threadpriority = @ARGV[2];

    ##print "Setting process $procname priority $priority thread priority $threadpriority\n";

    use Win32::Process::Info;

    my $pi = Win32::Process::Info->new ();
    foreach $proc ($pi->GetProcInfo ()) {

    foreach (sort keys %$proc) {

    if ($_ =~ /\bHandle\b/) {
    $thispid = $proc->{$_}
    } # end if handle

    if ($_ =~ /\bName\b/) {
    $thisname = $proc->{$_};
    if ($thisname =~ /$procname/){;
    system("c\:\\SetPriority\\SetPriority.exe -p$priority -t$threadpriority $thispid");
    exit;
    } # end if thisname =

    } # end if eq Name

    } # end for each sort keys

    } # end for each proc
    ========================================
    Last edited by rbutcher; 11-29-2005 at 04:51 AM.

  8. #8
    Member rbutcher's Avatar
    Join Date
    Mar 2005
    Location
    Sydney Australia
    Posts
    48
    Latest state of play in the saga.. I added the following command line to the Win2k Scheduled Tasks - when it runs nothing happens, process priorities (e.g. for LHC sixtrack) stay at the low default value and don't get changed.. yet when I run it from the command line it works. Scheduler History shows the task was run at the correct time, with blank status which is supposed to mean success. The command :-
    c:\Perl\site\lib\setpriority.pl sixtrack 16384 -1
    This Perl script (see previous post) runs Jeff's SetPriority program. Works when runs from command line, not from the scheduler. Any ideas ?
    Ahem.. I just discovered that the perl interpreter is not invoked by the Scheduler. If I prefix the Perl interpreter to the execution string it works :
    c:\Perl\bin\perl c:\Perl\site\lib\setpriority.pl sixtrack 16384 -1

  9. #9
    Administrator Bok's Avatar
    Join Date
    Oct 2003
    Location
    Wake Forest, North Carolina, United States
    Posts
    24,467
    Blog Entries
    13
    Perl not in the environment ?

    Same thing happens in unix often..

  10. #10
    Member rbutcher's Avatar
    Join Date
    Mar 2005
    Location
    Sydney Australia
    Posts
    48
    Originally posted by Digital Parasite
    Right, D2OLDaddy does exactly that, designed for D2OL and TSC. It will reset your priority automatically every X seconds that you configure it to do.

    Windows 2000 and XP have something called "Scheduled Tasks" that you can setup to run programs/scripts. Its usually found under Accessories -> System Tools from the start menu. If this is just for D2OL/TSC you need it for, I would suggest using D2OL Daddy in windows since it does all that for you automatically.
    Jeff, I'm trying to get my Perl script to change thread priorities, by using Win32::API, but I've been told that only the process that creates the thread can get a handle on it to modify it, or to create a "duplicate handle" that another process can use (this other process being the Perl interpreter). - which clearly is not the case with your setpriority C program. Care to share the source so I can see how it's done ?
    thanks
    Rod

  11. #11
    Originally posted by rbutcher
    JCare to share the source so I can see how it's done ?
    Here is the relevant piece of code:

    Code:
    HANDLE         hProcessSnap = NULL; 
    BOOL           bRet      = FALSE; 
    THREADENTRY32  te32      = {0}; 
     
    //  Take a snapshot of all processes in the system. 
    
    hProcessSnap = CreateToolhelp32Snapshot(TH32CS_SNAPTHREAD, 0); 
    
    if (hProcessSnap == INVALID_HANDLE_VALUE) 
        return (FALSE); 
     
    //  Fill in the size of the structure before using it. 
    te32.dwSize = sizeof(THREADENTRY32); 
    
    // Get first process information
    Thread32First(hProcessSnap, &te32)
    
    // get the thread priority
    HANDLE hThread;
    hThread = OpenThread(THREAD_SET_INFORMATION|THREAD_QUERY_INFORMATION, FALSE, te32.th32ThreadID); 
    
    // set new priority class
    if (SetThreadPriority(hThread, threadPriority) != TRUE)
    {
    	cerr << "SetThreadPriority() ";
    	printError();
    }
    CloseHandle(hThread);

  12. #12
    Member rbutcher's Avatar
    Join Date
    Mar 2005
    Location
    Sydney Australia
    Posts
    48
    Thanks for that Jeff. That pointed me to the MSDN website documentation - from that I understand I need to walk thru the Processes using Process32First and then Process32Next untill I find the Process I want, and then use Thread32First like your code shows, to position on the first (only) thread for the process - at least that's the impression I get from the MSDN articles on the subject. Correct ?
    thanks
    Rod

  13. #13
    Almost. Changing the priority of the first thread will do just that, change the priority of the first thread. If a process has multiple threads you will have to use the Next() function after you do the first to modify the rest.

    If you look at Firefox for example you will see it has multiple threads, running at different priorities:

    Code:
    Process ID (PID): 3224
    Current Priority Class : 32
    Current Thread Priority: 0
    Current Thread Priority: 0
    Current Thread Priority: 0
    Current Thread Priority: 0
    Current Thread Priority: 0
    Current Thread Priority: 1
    Current Thread Priority: 0
    Current Thread Priority: 0
    Current Thread Priority: 0
    Current Thread Priority: 15
    Current Thread Priority: 15
    Current Thread Priority: 0
    
    
                  Process      Thread
                  -------      ------
    RealTime   :  256          15
    High       :  128          2
    AboveNormal:  32768        1
    Normal     :  32           0
    BelowNormal:  16384        -1
    Idle       :  64           -2
    Lowest     :  N/A          -15
    If you just set the priority of the first thread, it would miss the others. My code will actually walk through the list of all threads and set each one.

  14. #14
    Member rbutcher's Avatar
    Join Date
    Mar 2005
    Location
    Sydney Australia
    Posts
    48
    Thanks a million Jeff. In case anybody is still interested, here's the Perl code to modify the first thread's priority given a PID. To modify all threads for the PID, we jwould just continue in the Thread32Next loop .

    # set first thread for $pid to $hThreadPriority
    my $pid = 952;
    my $hThreadPriority = 0;
    my $retcode;
    my $hThreadSnap;
    my $hThread;
    my $Point;

    use strict;
    use Win32::API;

    Win32::API->Import( 'Kernel32', q[ DWORD GetLastError( ) ] );

    $retcode = Win32::API->Import( 'Kernel32',
    q[ HANDLE CreateToolhelp32Snapshot
    ( DWORD dwFlags, DWORD th32ProcessID ) ] );
    print "import CreateToolhelp32Snapshot code $retcode \n";

    use constant TH32CS_SNAPTHREAD => 0x4;

    $hThreadSnap=CreateToolhelp32Snapshot(TH32CS_SNAPTHREAD, 0);
    $retcode = GetLastError();
    print "CreateToolhelp32Snapshot error code $retcode \n";
    print "hThreadSnap = $hThreadSnap \n";

    # typedef for THREADENTRY32
    typedef Win32::API::Struct TE32 => qw{
    DWORD dwSize;
    DWORD cntUsage;
    DWORD th32ThreadID;
    DWORD th32OwnerProcessID;
    LONG tpBasePri;
    LONG tpDeltaPri;
    DWORD dwFlags;
    };

    $retcode = Win32::API->Import( 'Kernel32',
    q[ BOOL Thread32First
    ( HANDLE hSnapshot, LPTE32 lpte)]);
    print "import thread32first code $retcode \n";

    $Point = Win32::API::Struct->new( 'TE32' );
    $Point->{dwSize}=28;

    Thread32First($hThreadSnap, $Point);
    $retcode = GetLastError();
    print "thread32first error $retcode \n";
    print "pid = $Point->{th32OwnerProcessID} \n";

    $retcode = Win32::API->Import( 'Kernel32',
    q[ BOOL Thread32Next
    ( HANDLE hSnapshot, LPTE32 lpte)]);
    print "import threadnext code $retcode \n";


    until ( $Point->{th32OwnerProcessID} == $pid ) {
    Thread32Next($hThreadSnap, $Point);
    $retcode = GetLastError();
    print "thread32next error $retcode \n";
    print "pid = $Point->{th32OwnerProcessID} \n";
    }


    $retcode = Win32::API->Import( 'Kernel32', q[HANDLE OpenThread(
    DWORD dwDesiredAccess,
    BOOL bInheritHandle,
    DWORD dwThreadId
    ) ] );
    print "import openthread code $retcode \n";

    use constant THREAD_SET_INFORMATION => 0x0020;
    use constant THREAD_QUERY_INFORMATION => 0x0040;

    $hThread = OpenThread(
    THREAD_SET_INFORMATION|THREAD_QUERY_INFORMATION,
    0,
    $Point->{th32ThreadID}
    );
    $retcode = GetLastError();
    print "openthread error code $retcode \n";

    $retcode = Win32::API->Import( 'Kernel32', q[BOOL SetThreadPriority(
    HANDLE hThread,
    int nPriority
    ) ] );
    print "import openthread code $retcode \n";

    SetThreadPriority( $hThread, $hThreadPriority );
    $retcode = GetLastError();
    print "setthreadpriority error code $retcode \n";
    Last edited by rbutcher; 12-15-2005 at 08:59 PM.

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •