#!/usr/bin/perl # # scan job execution log files from the Cornell SP2 system, and use convert2swf.pm # to convert the data into the standard workload format. # use warnings; use strict; use Time::Local; use POSIX; use convert2swf_v4; # NOTE: there are actually 2 versions, with slight differences, # e.g. early doesn't have the 20th field #my $version = "early"; my $version = "prod"; ############################ # # DO THE CONVERSION: # my $tz_str = "US/Eastern"; my $max_procs = 336; my @queues = ("DSI", "astro", "piofs", "informix", ); SWF::init( $tz_str, $max_procs, \@queues ); my $format_bugs; my $jobs_data = get_jobs(); my ($zero, $maxtime) = SWF::convert( $jobs_data, $format_bugs ); my $header = generate_header( $zero, $maxtime, $max_procs ); SWF::print( $header ); ############################ # SPECIFICS for CTC workload # the format of each entry includes the following space-separated fields: # 0 job name # 1 LoadLeveler class (actually time limit) # 2 nodes # 3 submit time (secs since epoch) # 4 start time (secs since epoch) # 5 end time (secs since epoch) # 6 memory requested # 7 node type requested (wide/thin) # 8 mass storage requested (y/n) # 9 adapter requested (ether/ip/us) # 10 submit time (calendar) # 11 start time (calendar) # 12 end time (calendar) # 13 resource use (sum of node CPU times) # 14 job type (serial/parallel/PVM) # 15 completion status (completed/removed/other) # 16 user ID # 17 cumulative user CPU time # 18 cumulative system CPU time # 19 name of script used to submit job # 20 runtim limit for EASY (min) my $job_cnt; sub get_jobs { ############## # parse input format and create a hash for each job my @list_of_jobs; # # scan trace and collect job info # while (<>) { # # parse line and extract info # if (/^\s*$/) { # empty line next; } $_ =~ /\s*(.*)\s*/; # get rid of white space at ends $_ = $1; my @line = split('\s+'); # split into fields if (($version eq "prod") && ($#line != 20)) { $format_bugs .= "format_problem $_\n"; warn(">>>Format problem on $_\ngot $#line fields (should be 20)"); next; } if (($version eq "early") && ($#line != 19)) { # last two fields often not separated if (($#line == 18) && ($line[18] =~ /^(\d+)(.+)$/)) { $line[18] = $1; $line[19] = $2; } else { $format_bugs .= "format_problem $_\n"; warn(">>>Format problem on $_\ngot $#line fields (should be 19)"); next; } } my %nj; # # set the desired fields as specified in convert2swf.pl # $nj{trace} = $_; # used for error messages $nj{submit} = $line[3]; $nj{start} = $line[4]; $nj{end} = $line[5]; $nj{procs} = $line[2]; # CPU time is given for all nodes, separated into user and system. # we need total per node. my $cpu; if ($line[2] > 0) { $cpu = int( ($line[17] + $line[18]) / $line[2] ); $nj{cpu} = $cpu; } if ($version eq "prod") { # requested runtime is given in minutes $nj{req_time} = $line[20] * 60; } # no data on requested runtime in early version if ($version eq "early") { $nj{req_mem} = $line[6] * 1024; } # all request 128M in prod version $nj{status} = ($line[15] eq "Co") ? 1 : 0; $nj{user} = $line[16]; $nj{app} = $line[19]; $nj{queue} = $line[1]; $list_of_jobs[$job_cnt++] = \%nj; } return \@list_of_jobs; } sub generate_header { my ($zero, $maxtime, $max_procs) = @_; my ($sec, $min, $hr, $mday, $mon, $year, $wday, $yday, $isdst); $header = "; Version: 2.2\n"; $header .= "; Computer: IBM SP2\n"; $header .= "; Installation: Cornell Theory Center (CTC)\n"; if ($version eq "early") { $header .= "; Acknowledge: Steve Hotovy\n"; } else { $header .= "; Acknowledge: Dan Dwyer and Steve Hotovy\n"; } $header .= "; Information: http://www.tc.cornell.edu/\n"; $header .= "; http://www.cs.huji.ac.il/labs/parallel/workload/\n"; $header .= sprintf("; Conversion: Dror Feitelson (feit\@cs.huji.ac.il) %s\n", strftime("%d %b %Y", localtime())); $header .= sprintf("; MaxJobs: %d\n", $job_cnt); $header .= sprintf("; MaxRecords: %d\n", $job_cnt); $header .= "; Preemption: No\n"; $header .= sprintf("; UnixStartTime: %d\n", $zero); $header .= "; TimeZone: -18000\n"; $header .= sprintf("; TimeZoneString: %s\n", $tz_str); $header .= sprintf("; StartTime: %s\n", strftime("%a %b %2d %H:%M:%S %Z %Y", localtime($zero))); $header .= sprintf("; EndTime: %s\n", strftime("%a %b %2d %H:%M:%S %Z %Y", localtime($maxtime))); $header .= "; MaxNodes: $max_procs (batch partition; 512 total)\n"; $header .= "; MaxProcs: $max_procs\n"; $header .= "; Note: uses the EASY scheduler\n"; $header .= "; Queues: these are actually LoadLeveler classes\n"; # NOTE: do not include list of queues return $header; }