Team Fortress 2 Source Code as on 22/4/2020
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

385 lines
8.7 KiB

  1. #!/usr/bin/perl -w
  2. use Getopt::Long;
  3. use Pod::Usage;
  4. use Sys::Hostname;
  5. use File::Copy;
  6. use File::Path;
  7. use Time::HiRes qw(gettimeofday tv_interval);
  8. use Cwd;
  9. use strict;
  10. use vars qw(%TESTS %STATS $ABORT_RUN $MPI_GRAPHICS);
  11. # To add a new test, just create a new hash entry that has code
  12. # references for the Prep, Run and Clean stages of the test.
  13. # The new test can be selected using the -test option.
  14. %TESTS = (
  15. 'vrad' => {
  16. 'PREP' => \&VRADPrep,
  17. 'RUN' => \&VRADRun,
  18. 'CLEAN' => \&VRADClean,
  19. },
  20. 'vvis' => {
  21. 'PREP' => \&VVISPrep,
  22. 'RUN' => \&VVISRun,
  23. 'CLEAN' => \&VVISClean,
  24. },
  25. 'shadercompile' => {
  26. 'PREP' => \&ShaderPrep,
  27. 'RUN' => \&ShaderRun,
  28. 'CLEAN' => \&ShaderClean,
  29. }
  30. );
  31. %STATS = ();
  32. $ABORT_RUN = 0;
  33. $MPI_GRAPHICS = 0;
  34. local $SIG{INT} = sub {
  35. $ABORT_RUN = 1;
  36. };
  37. my $start = 4;
  38. my $stop = 32;
  39. my $step = 4;
  40. my $test = "vrad";
  41. my $list = undef;
  42. my $help = 0;
  43. my $man = 0;
  44. my @work_list = ();
  45. GetOptions("file=s" => \$list,
  46. "test=s" => \$test,
  47. "workerlist=s" => sub {
  48. shift; local $_ = shift;
  49. @work_list = split(',', $_)
  50. },
  51. "start|s=i" => \$start,
  52. "stop|e=i" => \$stop,
  53. "step=i" => \$step,
  54. "graphics" => \$MPI_GRAPHICS,
  55. "help|?" => \$help,
  56. "man" => \$man) or pod2usage(2);
  57. pod2usage(1) if $help;
  58. pod2usage(-exitstatus => 0, -verbose => 2) if $man;
  59. my @extra_args = @ARGV;
  60. unless (@work_list) {
  61. for (my $workers = $stop; $workers >= $start; $workers -= $step) {
  62. push @work_list, $workers;
  63. }
  64. }
  65. if (defined($list)) {
  66. @work_list = ReadMachineList($list, \@work_list);
  67. }
  68. unless (@work_list) {
  69. die "No workers in list\n";
  70. }
  71. my $logfile = "$test-$$.log";
  72. print "Testing: ", join(", ", @work_list), "\n";
  73. print "Logging to $logfile\n";
  74. # Redirect console to log file and unbuffer the output
  75. open STDOUT, ">$logfile";
  76. open STDERR, ">>$logfile";
  77. my $oldfh = select(STDOUT); $| = 1;
  78. select(STDERR); $| = 1;
  79. select($oldfh);
  80. # Lock the list of machines if given
  81. # Prepare for the test
  82. # Run the test over the work list
  83. # Clean up after the test
  84. # Release lock on list of machines if given
  85. my $pass = defined($list) ? ReserveMachines($list, $test) : '';
  86. TestPrep($test, @extra_args);
  87. for my $workers (@work_list) {
  88. last if $ABORT_RUN;
  89. TestRun($test, $workers, $pass, @extra_args);
  90. }
  91. TestClean($test, @extra_args);
  92. ReleaseMachines($list) if defined($list);
  93. sub ReadMachineList
  94. {
  95. my $list = shift;
  96. my $work_list = shift;
  97. my @machines = ();
  98. if (open(my $listfh, $list)) {
  99. while(my $line = <$listfh>) {
  100. chomp($line);
  101. next unless $line =~ /\S/;
  102. push @machines, $line;
  103. }
  104. }
  105. my @capped_list = grep { $_ <= scalar(@machines) } @{$work_list};
  106. if ($#{$work_list} > $#capped_list) {
  107. print "Not enough machines to run test\n";
  108. print "Reducing max workers\n\n";
  109. }
  110. return @capped_list;
  111. }
  112. sub SetVMPIPass {
  113. my $machines = shift;
  114. my $pass = shift;
  115. system("vmpi_chpass.pl", "-p", $pass, "-f", $machines);
  116. }
  117. sub ReserveMachines
  118. {
  119. my $list = shift;
  120. my $pass = shift;
  121. my $host = lc hostname();
  122. $pass .= "-test-$host-$$";
  123. SetVMPIPass($list, $pass);
  124. return $pass;
  125. }
  126. sub ReleaseMachines
  127. {
  128. my $machines = shift;
  129. SetVMPIPass($machines, '');
  130. }
  131. sub DoTestFunc
  132. {
  133. my $test = shift;
  134. my $func = shift;
  135. my $workers = $_[0];
  136. if (exists($TESTS{$test}{$func})) {
  137. my $start = [gettimeofday];
  138. &{$TESTS{$test}{$func}}(@_);
  139. my $stop = [gettimeofday];
  140. my $time = tv_interval($start, $stop);
  141. $STATS{$func}{$workers} = $time / 60;
  142. }
  143. else {
  144. die "Failed to locate test function for: $test($func)\n";
  145. }
  146. }
  147. sub TestPrep
  148. {
  149. my $test = shift;
  150. DoTestFunc($test, 'PREP', 0, '', @_);
  151. }
  152. sub TestRun
  153. {
  154. my $test = shift;
  155. DoTestFunc($test, 'RUN', @_);
  156. }
  157. sub TestClean
  158. {
  159. my $test = shift;
  160. DoTestFunc($test, 'CLEAN', 0, '', @_);
  161. }
  162. sub GetMPIArgs
  163. {
  164. my $n_workers = shift;
  165. my $pass = shift;
  166. my @args = ("-mpi");
  167. push(@args, "-mpi_workercount", $n_workers) if $n_workers > 0;
  168. push(@args, "-mpi_pw", $pass) if $pass;
  169. push(@args, "-mpi_graphics", "-mpi_trackevents") if $MPI_GRAPHICS;
  170. return @args;
  171. }
  172. sub VRADPrep
  173. {
  174. my $n_workers = shift;
  175. my $pass = shift;
  176. my $basename = shift;
  177. my @extra_args = @_;
  178. my @mpi_args = GetMPIArgs($n_workers, $pass);
  179. system("vbsp", $basename);
  180. system("vvis", @mpi_args, @extra_args, $basename);
  181. copy("$basename.bsp", "$basename-$$.bsp");
  182. }
  183. sub VRADRun
  184. {
  185. my $n_workers = shift;
  186. my $pass = shift;
  187. my $basename = shift;
  188. my @extra_args = @_;
  189. my @mpi_args = GetMPIArgs($n_workers, $pass);
  190. copy("$basename-$$.bsp", "$basename.bsp");
  191. system("vrad", "-final", "-staticproppolys", "-staticproplighting",
  192. @mpi_args, @extra_args, $basename);
  193. }
  194. sub VRADClean
  195. {
  196. my $n_workers = shift;
  197. my $pass = shift;
  198. my $basename = shift;
  199. unlink("$basename.bsp", "$basename-$$.bsp");
  200. }
  201. sub VVISPrep
  202. {
  203. my $n_workers = shift;
  204. my $pass = shift;
  205. my $basename = shift;
  206. my @mpi_args = GetMPIArgs($n_workers, $pass);
  207. system("vbsp", $basename);
  208. copy("$basename.bsp", "$basename-$$.bsp");
  209. }
  210. sub VVISRun
  211. {
  212. my $n_workers = shift;
  213. my $pass = shift;
  214. my $basename = shift;
  215. my @extra_args = @_;
  216. my @mpi_args = GetMPIArgs($n_workers, $pass);
  217. copy("$basename-$$.bsp", "$basename.bsp");
  218. system("vvis", @mpi_args, $pass, @extra_args, $basename);
  219. }
  220. sub VVISClean
  221. {
  222. my $n_workers = shift;
  223. my $pass = shift;
  224. my $basename = shift;
  225. unlink("$basename.bsp", "$basename-$$.bsp");
  226. }
  227. sub ShaderPrep
  228. {
  229. my $n_workers = shift;
  230. my $pass = shift;
  231. my $basename = shift;
  232. $ENV{DIRECTX_SDK_VER}='pc09.00';
  233. $ENV{DIRECTX_SDK_BIN_DIR}='dx9sdk\\utilities';
  234. $ENV{PATH} .= ";..\\..\\devtools\\bin";
  235. my $src_base = "../..";
  236. my $dos_base = $src_base;
  237. $dos_base =~ s|/|\\|g;
  238. unlink("makefile.$basename");
  239. unlink(qw(filelist.txt filestocopy.txt filelistgen.txt inclist.txt vcslist.txt));
  240. rmtree("shaders");
  241. mkpath(["shaders/fxc", "shaders/vsh", "shaders/psh"]);
  242. print "Update Shaders\n";
  243. system("updateshaders.pl", "-source", $dos_base, $basename);
  244. print "Prep Shaders\n";
  245. system("nmake", "/S", "/C", "-f", "makefile.$basename");
  246. if (open(my $fh, ">>filestocopy.txt")) {
  247. print $fh "$dos_base\\$ENV{DIRECTX_SDK_BIN_DIR}\\dx_proxy.dll\n";
  248. print $fh "$dos_base\\..\\game\\bin\\shadercompile.exe\n";
  249. print $fh "$dos_base\\..\\game\\bin\\shadercompile_dll.dll\n";
  250. print $fh "$dos_base\\..\\game\\bin\\vstdlib.dll\n";
  251. print $fh "$dos_base\\..\\game\\bin\\tier0.dll\n";
  252. }
  253. print "Uniqify List\n";
  254. system("uniqifylist.pl < filestocopy.txt > uniquefilestocopy.txt");
  255. copy("filelistgen.txt", "filelist.txt");
  256. print "Done Prep\n";
  257. }
  258. sub ShaderRun
  259. {
  260. my $n_workers = shift;
  261. my $pass = shift;
  262. my $basename = shift;
  263. my @extra_args = @_;
  264. my @mpi_args = GetMPIArgs($n_workers, $pass);
  265. my $old_dir = getcwd();
  266. my $dos_dir = $old_dir;
  267. $dos_dir =~ s|/|\\|g;
  268. system("shadercompile", "-allowdebug", "-shaderpath", $dos_dir, @mpi_args, @extra_args);
  269. }
  270. sub ShaderClean
  271. {
  272. my $n_workers = shift;
  273. my $pass = shift;
  274. my $basename = shift;
  275. unlink("makefile.$basename");
  276. unlink(qw(filelist.txt filestocopy.txt filelistgen.txt inclist.txt vcslist.txt));
  277. mkpath(["shaders/fxc", "shaders/vsh", "shaders/psh"]);
  278. }
  279. END {
  280. if (%STATS) {
  281. print "\n\n", "-"x70, "\n\n";
  282. for my $func (qw(PREP RUN CLEAN)) {
  283. print "$func\n";
  284. print "="x length($func), "\n";
  285. for my $workers (sort {$a <=> $b} keys %{$STATS{$func}}) {
  286. printf("%3d, %6.3f\n", $workers, $STATS{$func}{$workers});
  287. }
  288. print "\n";
  289. }
  290. }
  291. }
  292. __END__
  293. =head1 NAME
  294. vmpi_test.pl - Test utility to automate execution of VMPI tools
  295. =head1 SYNOPSIS
  296. vmpi_test.pl [-test <test name>] [-file <host file>] [-start <num>] [-stop <num>] [-step <num>] [-workerlist <list>] [-graphics] [-help|-?] [-man]
  297. Options:
  298. -test The name of the test to run
  299. -file A file that contains the names of machines to use
  300. -start Lowest worker count to test
  301. -stop Highest worker count to test
  302. -step Interval to increment worker count
  303. -workerlist A comma separated list of worker counts to test
  304. -graphics Enable MPI visual work unit tracker
  305. -help|-? Display command line usage
  306. -man Display full documentation
  307. =head1 DESCRIPTION
  308. B<vmpi_test.pl> executes a specified test for each number of worker
  309. counts given on the command line. The worker counts can be provided as
  310. a start, stop and step relationship, or it can be specified using a
  311. comma separated list. An optional host list file can be provided to
  312. restrict the test to a given set of machines. These machines will have
  313. a VMPI password applied to them so that you will get exclusive access
  314. to them.
  315. =cut