f1196ac3737ce1972542f5a49e22ee1674647aac
[scilab.git] / scilab / modules / development_tools / macros / bench_run.sci
1 // Scilab ( http://www.scilab.org/ ) - This file is part of Scilab
2 // Copyright (C) 2007-2008 - INRIA - Pierre MARECHAL <pierre.marechal@inria.fr>
3 // Copyright (C) 2011-2011 - DIGITEO - Bruno JOFRET
4 //
5 // Copyright (C) 2012 - 2016 - Scilab Enterprises
6 //
7 // This file is hereby licensed under the terms of the GNU GPL v2.0,
8 // pursuant to article 5.3.4 of the CeCILL v.2.1.
9 // This file was originally licensed under the terms of the CeCILL v2.1,
10 // and continues to be available under such terms.
11 // For more information, see the COPYING file which you should have received
12 // along with this program.
13
14 //-----------------------------------------------------------------------------
15 // Launch benchmarks
16 //-----------------------------------------------------------------------------
17
18 function [modutests_names, elapsed_time, nb_iterations] = bench_run(varargin)
19
20     lhs = argn(1);
21     rhs = argn(2);
22
23     global test_list;
24     global test_count;
25
26     test_list          = [];
27     modutests_names    = "";
28     test_count         = 0;
29     boucle_for_time    = 0;
30
31     just_list_tests    = %F;
32     print_help         = %F;
33     nb_run             = "10000";
34     nb_run_override    = %f;
35
36     elapsed_time       = [];
37     nb_iterations      = [];
38
39     xml_str            = "";
40
41     // =======================================================
42     // Gestion des tests à lancer
43     // =======================================================
44
45     if (rhs == 0) ..
46         | ((rhs == 1) & (varargin(1)==[] | varargin(1)=="[]" | varargin(1) == "")) ..
47         | (((rhs >= 2)) & (varargin(1)==[] | varargin(1)=="[]" | varargin(1) == "") & (varargin(2)==[] | varargin(2)=="[]" | varargin(2) == "")) then
48
49         // No input argument
50         // bench_run()
51         // bench_run([])
52         // => Launch each test of each module
53
54         module_list = getmodules();
55         module_list = gsort(module_list,"lr","i");
56         for k=1:size(module_list,"*")
57             bench_add_module(module_list(k));
58         end
59
60     elseif (rhs == 1) ..
61         | ((rhs >= 2) & (varargin(2)==[] | varargin(2)=="[]" | varargin(2) == "")) ..
62
63         // One input argument
64         // bench_run(<module_name>)
65         // bench_run([<module_name_1>,<module_name_2>])
66
67         // varargin(1) = [<module_name_1>,<module_name_2>]
68
69         module_mat = varargin(1);
70
71         [nl,nc] = size(module_mat);
72
73         // bench_run([<module_name_1>,<module_name_2>])
74
75         for i=1:nl
76             for j=1:nc
77                 if( with_module(module_mat(i,j)) ) then
78                     bench_add_module(module_mat(i,j));
79                 else
80                     if isdir(module_mat(i,j)) then
81                         bench_add_dir(module_mat(i,j));
82                     else
83                         error(msprintf(gettext("%s: %s is not an installed module"), "bench_run", module_mat(i,j)));
84                     end
85                 end
86             end
87         end
88
89     elseif (rhs >= 2 & rhs <= 4) then
90
91         // Two input arguments
92         // bench_run(<module_name>,<test_name>)
93         // bench_run(<module_name>,[<test_name_1>,<test_name_2>] )
94
95         module_mat = varargin(1);
96         test_mat   = varargin(2);
97         bench_list_reduced = [];
98
99         // get module and test lists
100         bench_list = bench_list_tests(module_mat);
101         // only keep relevant tests
102         // after this loop bench_test_reduced contains the module and relevant tests
103         for i = 1:size(test_mat, "*")
104             found_tests = find(bench_list(:,2) == test_mat(i));
105             if ~isempty(found_tests)
106                 bench_list_reduced = [bench_list_reduced; bench_list(found_tests, :)];
107             else
108                 // At least one element in the test list is wrong
109                 // this is an error
110                 error(msprintf(_("%s: Wrong value for input argument #%d: test %s not found in the list of modules"), "bench_run", 2, test_mat(i)));
111             end
112         end
113
114         for i=1:size(bench_list_reduced, "r") //loops over each row of bench_list_reduced
115             bench_add_onebench(bench_list_reduced(i, 1), bench_list_reduced(i, 2));
116         end
117     else
118         error(msprintf(gettext("%s: Wrong number of input argument(s): %d to %d expected.\n"), "bench_run", 0, 4));
119     end
120
121     // =======================================================
122     // Gestion des options
123     // =======================================================
124
125     if rhs >= 3 then
126
127         option_mat =  varargin(3);
128
129         if grep(option_mat,"list") <> [] then
130             just_list_tests    = %T;
131         end
132
133         if grep(option_mat,"help") <> [] then
134             print_help         = %T;
135         end
136
137         nb_run_line = grep(option_mat,"/nb_run\s*=\s*/", "r")
138         if ~isempty(nb_run_line) then
139             nb_run_override = %t;
140             stripped_option = option_mat(nb_run_line);
141             idx_nonblank = strindex(stripped_option, "/[^ \t\b]/", "r");
142             stripped_option = part(stripped_option, idx_nonblank);
143             nb_run      = strsubst(stripped_option, "nb_run=","");
144         end
145
146     end
147
148     if print_help then
149
150         // =======================================================
151         // Display help
152         // =======================================================
153
154         example = bench_examples();
155         printf("%s\n",example);
156         return;
157
158     elseif just_list_tests then
159
160         // =======================================================
161         // Just list tests
162         // =======================================================
163
164         printf("\n");
165
166         for i=1:test_count
167             printf("   %03d - ",i);
168             printf("[%s] %s\n",test_list(i,1),test_list(i,2));
169         end
170
171     else
172
173         // =======================================================
174         // Test launch
175         // =======================================================
176
177         // Protect user modes during tests
178         saved_modes = mode();
179         saved_ieee = ieee();
180         saved_format = format();
181         saved_warning = warning("query");
182         saved_funcprot = funcprot();
183
184         printf("\n");
185
186         xml_str = [ xml_str ; "<benchmarks>" ];
187
188         // Calcul de la durée de la boucle for en µs
189
190         tic();
191         for i = 1:1000000
192         end
193         timing = toc();
194         boucle_for_time = timing * 1000;
195
196         printf("            For Loop (as reference) ...........................      %4.2f ms [ 1000000 x]\n\n",boucle_for_time);
197
198         // Creation of return values the size of test_count
199
200         for i=1:test_count
201
202             // Display
203             printf("   %03d/%03d - ",i,test_count);
204             printf("[%s] %s ",test_list(i,1),test_list(i,2));
205             for j = length(test_list(i,2) + test_list(i,1)):45
206                 printf(".");
207             end
208             printf(" ");
209
210             // Bench process
211             [returned_time, nb_run_done] = bench_run_onebench(test_list(i,1), test_list(i,2), nb_run);
212
213             // restore user modes inside the loop
214             // Protects from tests that modify those settings
215             mode(saved_modes);
216             ieee(saved_ieee);
217             format(saved_format([2 1]));
218             warning(saved_warning);
219             funcprot(saved_funcprot);
220
221             elapsed_time = [elapsed_time; returned_time];
222             nb_iterations = [nb_iterations; nb_run_done];
223
224             // Display
225             returned_time_str           = sprintf("%4.2f ms",returned_time);
226             for j = length(returned_time_str):13
227                 printf(" ");
228             end
229             printf("%s [",returned_time_str);
230             for j = length(nb_run_done):7
231                 printf(" ");
232             end
233             printf("%s x]\n",nb_run_done);
234
235             // XML print
236             xml_str = [ xml_str ; ..
237             "    <bench>"; ..
238             "        <module>"+test_list(i,1)+"</module>"; ..
239             "        <id>"+test_list(i,2)+"</id>"; ..
240             "        <duration>"+strsubst(returned_time_str," ms","")+"</duration>"; ..
241             "        <nb_run>"+nb_run_done+"</nb_run>"; ..
242             "    </bench>" ];
243
244         end
245     end
246
247     modutests_names = test_list;
248     nb_iterations = eval(nb_iterations);
249
250     // XML management
251     // ==============
252     //      exportToFile can be
253     //      * "", "[]" or []: default behaviour, write the output file in the TMPDIR/benchmarks
254     //      path/to/directory/: export a timestamped xml file to the output directory
255     //      path/to/directory/filename.xml: exports filename.xml to the directory
256     //      get the current date to create a timestamp
257
258     // Close the final tag for export
259     xml_str = [ xml_str ; "</benchmarks>" ];
260     if size(unique(modutests_names(:,1)), "r") == 1
261         module_name = tokens(pathconvert(modutests_names(1, 1), %f, %f, "u"), "/"); // name of the only module tested
262         module_name = module_name($);
263     else
264         module_name = "";
265     end
266
267     if (rhs == 4)
268         exportToFile = varargin(4);
269         if (isempty(exportToFile) | exportToFile == "[]")
270             exportToFile = "";
271         end
272     else
273         exportToFile = "";
274     end
275     [xml_file_name, ierr, fd_xml] = bench_file_output_path(exportToFile);
276
277     if ierr == 0 then
278         mputl(xml_str, fd_xml);
279         mclose(fd_xml);
280     end
281
282     clearglobal test_list;
283     clearglobal test_count;
284     clearglobal boucle_for_time;
285
286
287 endfunction
288
289 //-----------------------------------------------------------------------------
290 // Pierre MARECHAL
291 // Scilab team
292 // Date : 28 oct. 2007
293 //
294 // => List all test files in the module <module_mat>
295 // => Add them to the test_mat matrix
296 //-----------------------------------------------------------------------------
297
298 function bench_add_module(module_mat,test_type)
299
300     module_test_dir = SCI+"/modules/"+module_mat+"/tests/benchmarks";
301     test_mat        = gsort(basename(listfiles(module_test_dir+"/*.tst")),"lr","i");
302
303     nl = size(test_mat,"*");
304     for i=1:nl
305         bench_add_onebench(module_mat,test_mat(i));
306     end
307
308 endfunction
309
310 function [bench_list] = bench_list_tests(module_mat)
311
312     module_test_dir = [];
313     bench_list= [];
314     for i = 1:size(module_mat, "*")
315         if with_module(module_mat(i))
316             // module_mat(i) is a scilab module
317             module_test_dir = [module_test_dir; SCI+"/modules/"+module_mat(i)+"/tests/benchmarks"];
318         else
319             // module_mat(i) is a directory
320             module_test_dir = [module_test_dir; module_mat(i) + "/tests/benchmarks"];
321         end
322         test_mat        = gsort(basename(listfiles(module_test_dir(i) + "/*.tst")),"lr","i");
323         bench_list = [bench_list; [repmat(module_mat(i), size(test_mat, "*"), 1), test_mat]];
324     end
325 endfunction
326
327 //-----------------------------------------------------------------------------
328 // Pierre MARECHAL
329 // Scilab team
330 // Date : 28 oct. 2007
331 //
332 // => Add the test <test> to the test_mat matrix
333 //-----------------------------------------------------------------------------
334
335 function bench_add_onebench(module,test)
336
337     global test_list;
338     global test_count;
339
340     test_count = test_count + 1;
341
342     test_list( test_count , 1 ) = module;
343     test_list( test_count , 2 ) = test;
344
345 endfunction
346
347 //-----------------------------------------------------------------------------
348 // Pierre MARECHAL
349 // Scilab team
350 // Date : 28 oct. 2007
351 //
352 // => Run one test
353 //-----------------------------------------------------------------------------
354
355 function [returned_time,nb_run_done] = bench_run_onebench(module, test, nb_run)
356     // runs the benchmark for module
357     returned_time = 0;
358
359     if with_module(module)
360         fullPath      = SCI+"/modules/"+module+"/tests/benchmarks/"+test;
361     else
362         fullPath = module + "/tests/benchmarks/" + test;
363     end
364
365     tstfile       = pathconvert(fullPath+".tst",%f,%f);
366     scefile       = pathconvert(TMPDIR+"/"+test+".sce",%f,%f);
367
368     // Get the tst file
369     txt = mgetl(tstfile);
370
371     // Check if the nb run is defined in the test
372
373     check_nb_run_line = grep(txt,"<-- BENCH NB RUN :");
374
375     nb_run_done   = nb_run;
376
377     if (check_nb_run_line <> [] & ~nb_run_override) then
378         nb_run_line   = txt(check_nb_run_line);
379         nb_run_start  = strindex(nb_run_line,"<-- BENCH NB RUN :") + length("<-- BENCH NB RUN :");
380         nb_run_end    = strindex(nb_run_line,"-->") - 1;
381         nb_run        = stripblanks(part(nb_run_line,[nb_run_start:nb_run_end]));
382         nb_run_done   = nb_run;
383     end
384
385     // get the <-- BENCH START --> and <-- BENCH END --> tags
386     line_start = grep(txt,"<-- BENCH START -->");
387     line_end   = grep(txt,"<-- BENCH END -->");
388
389     // Get the context and the bench
390     // Take the whole file as bench if the tags are not found
391     if isempty(line_start) | isempty(line_end)
392         context = "";
393         bench = txt;
394         after = ""
395     else
396         context    = txt([1:line_start-1]);
397         bench      = txt([line_start+1:line_end-1]);
398         after      = txt([line_end:$]);
399     end
400
401     // Remove blank lines
402     context(find(context == "" )) = [];
403     bench  (find(bench   == "" )) = [];
404
405     tst_str = [ context ;
406     "nb_run = "+nb_run+";";
407     "tic();";
408     "for __loop_iterator__ = 1:nb_run";
409     bench;
410     "end";
411     "timing = toc();";
412     after;
413     "returned_time = timing * 1000;"]
414
415     mputl(tst_str,scefile);
416     exec(scefile);
417     returned_time = returned_time - (boucle_for_time * nb_run / 1d6)
418     return;
419
420 endfunction
421
422 //-----------------------------------------------------------------------------
423 // Pierre MARECHAL
424 // Scilab team
425 // Date : 28 oct. 2007
426 //
427 // => Check ref or generate ref
428 //-----------------------------------------------------------------------------
429
430 function example = bench_examples()
431
432     example = [ sprintf("Examples :\n\n") ];
433
434     example = [ example ; sprintf("// Launch all tests\n") ];
435     example = [ example ; sprintf("// This may take some time...\n") ];
436     example = [ example ; sprintf("// bench_run();\n") ];
437     example = [ example ; sprintf("// bench_run([]);\n") ];
438     example = [ example ; sprintf("// bench_run([],[]);\n") ];
439     example = [ example ; "" ];
440     example = [ example ; sprintf("// Test one or several module\n") ];
441     example = [ example ; sprintf("bench_run(''core'');\n") ];
442     example = [ example ; sprintf("bench_run(''core'',[]);\n") ];
443     example = [ example ; sprintf("bench_run([''core'',''string'']);\n") ];
444     example = [ example ; "" ];
445     example = [ example ; sprintf("// Launch one or several test in a specified module\n") ];
446     example = [ example ; sprintf("bench_run(''core'',[''trycatch'',''opcode'']);\n") ];
447     example = [ example ; "" ];
448     example = [ example ; sprintf("// With options\n") ];
449     example = [ example ; sprintf("bench_run([],[],''list'');\n") ];
450     example = [ example ; sprintf("bench_run([],[],''help'');\n") ];
451     example = [ example ; sprintf("bench_run(""string"",[],''nb_run=100'');\n") ];
452     example = [ example ; sprintf("// results in an output file in the local directory\n") ];
453     example = [ example ; sprintf("bench_run(""string"",[],''nb_run=100'', ""my_output_file.xml"");\n") ];
454     example = [ example ; sprintf("// results in an output directory TMPDIR/benchmarks/ is the default \n") ];
455     example = [ example ; sprintf("bench_run(""string"",[],''nb_run=100'', TMPDIR);\n") ];
456     example = [ example ; "" ];
457
458 endfunction
459
460 function bench_add_dir(directory)
461     // Scans directory for tests/benchmarks and add the benchmarks
462     module_test_dir = directory + "/tests/benchmarks";
463     test_mat        = gsort(basename(listfiles(module_test_dir+"/*.tst")),"lr","i");
464
465     nl = size(test_mat,"*");
466     for i=1:nl
467         bench_add_onebench(directory, test_mat(i));
468     end
469 endfunction
470
471 function [xml_file_name, ierr, fd_xml] = bench_file_output_path(exportPath, module_name)
472     if exportPath == ""
473         // Default for export is TMPDIR/benchmarks/
474         exportPath = TMPDIR + "/benchmarks";
475         if ~isdir(exportPath)
476             createdir(exportPath);
477         end
478     end
479
480     // Create timestamp and scilab short version
481     current_date = getdate();
482     current_date = msprintf("%d-%02d-%02d_%02d%02d%02d", current_date(1), current_date(2), current_date(6), current_date(7), current_date(8), current_date(9));
483     sciversion = getversion("scilab");
484     sciversion = string(sciversion);
485     sciversion = sciversion(1) + "." + sciversion(2) + "." + sciversion(3);
486
487     // Manage a single module name separation
488     if (module_name <> "")
489         module_name_sep = module_name + "_";
490     else
491         module_name_sep = "";
492     end
493
494     if isdir(exportPath)
495         // The exportPath is a directory
496         // build the inside this directory
497         xml_file_name = exportPath + "/bench_" + module_name_sep + sciversion + "_" + current_date +".xml";
498         ierr = execstr("fd_xml = mopen(xml_file_name,''wt'');","errcatch");
499     else
500         // The exportPath is not a directory
501         xml_file_name = exportPath;
502         ierr = execstr("fd_xml = mopen(xml_file_name,''wt'');","errcatch");
503     end
504     if ierr <> 0 then
505         [xml_file_alt, ierr, fd_xml] = bench_file_output_path("", module_name);
506         msg = msprintf(_("%s: Cannot create file %s, created file %s instead.\n"), "bench_run", fullpath(xml_file_name), strsubst(fullpath(xml_file_alt), TMPDIR, "TMPDIR"));
507         warning(msg);
508     end
509 endfunction