tizen 2.3.1 release
[framework/web/mobile/wrt.git] / src / profiling / script / profiling-target-part.pl
1 #!/usr/bin/env perl
2 # Copyright (c) 2011 Samsung Electronics Co., Ltd All Rights Reserved
3 #
4 #    Licensed under the Apache License, Version 2.0 (the "License");
5 #    you may not use this file except in compliance with the License.
6 #    You may obtain a copy of the License at
7 #
8 #        http://www.apache.org/licenses/LICENSE-2.0
9 #
10 #    Unless required by applicable law or agreed to in writing, software
11 #    distributed under the License is distributed on an "AS IS" BASIS,
12 #    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 #    See the License for the specific language governing permissions and
14 #    limitations under the License.
15 #
16
17 ##### CONFIGURATION begin #####
18
19 my $WIDGET_PACKAGE_DIR = './test-widgets';
20 my @WIDGETS = (
21   ['minimal.wgt', 'minimal' ],
22   ['0Jet_Pack_Agent.wgt', 'Jet Pack Agent'],
23   ['UnitTestAuto.wgt', 'UnitTest' ],
24 );
25 my $WRT_INSTALL_ENV = 'WRT_TEST_MODE=1';
26
27 my $WRT_CLIENT_LAUNCH = 'wrt-client -l {}';
28 my $WRT_CLIENT_QUERY = 'wrt-launcher -l 2>/dev/null';
29 my $WRT_CLIENT_INSTALL = "$WRT_INSTALL_ENV wrt-installer -i {}";
30 my $WRT_CLIENT_UNINSTALL = "$WRT_INSTALL_ENV wrt-installer -un {}";
31 my $COLD_START_PREPARE_COMMAND = '/sbin/sysctl vm.drop_caches=3';
32 my $OUTPUT_DIR = './OUTPUT';
33 my $PRELOAD_LIBRARIES = './utils/wrt-preloader';
34
35 ##### CONFIGURATION end #####
36
37
38 use strict;
39 use Time::HiRes;
40 use Time::Local;
41 use List::Util;
42
43
44 ##### Single test runners
45
46 # $stream may be undef - then no output
47 sub runWidget {
48   my $widgetTizenId = shift;
49   my $stream = shift;
50   my $streamout = shift;
51   my $fnameerr = shift;
52
53   unless (defined $fnameerr) {
54     $fnameerr = '/dev/null';
55   }
56
57   `mkdir -p $OUTPUT_DIR/tmp`;
58
59   my $fnameerr = "$OUTPUT_DIR/tmp/additional.tmp";
60
61   my $command = $WRT_CLIENT_LAUNCH;
62   $command =~ s/\{\}/$widgetTizenId/;
63   $command .= " 2>$fnameerr 3>$OUTPUT_DIR/tmp/prof.tmp & echo TEST-WIDGET-PID \$\!";
64
65   print "$command\n";
66
67   my ($startSec, $startUSec) = Time::HiRes::gettimeofday();
68
69   my $f;
70   open $f, "$command |";
71
72   my $pid = undef;
73
74   my $extralines  = "";
75
76   while (my $line = <$f>) {
77     print "The line is: $line";
78     if (defined $streamout) {
79       print $streamout $line;
80     }
81     chomp $line;
82     if (my ($p) = $line =~ /^TEST-WIDGET-PID (\d+)/) {
83         $pid = 0+$p;
84     } elsif ($line =~ /launched$/) {
85         print "launched detected $pid\n";
86         kill 10, $pid;
87         my $again = 1;
88         while ($again) {
89             my $t = `tail -1 $OUTPUT_DIR/tmp/prof.tmp`;
90             if ($t =~ /###PROFILING###STOP###/) {
91                 $again = 0;
92             }
93         }
94         kill 9, $pid;
95         print "killed\n";
96     } elsif ($line =~ /\[([0-9]*):([0-9]*):([0-9]*).([0-9]*)\][^)]*\): *([A-Za-z0-9 ]+) *profiling##(start|stop)/) { #additionally take point from debug
97         my ($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst) = localtime(time());
98         my $name = $5;
99         $hour = $1;
100         $min = $2;
101         $sec = $3;
102         my $msec = $4;
103         my $type = $6;
104         my $value = timelocal($sec,$min,$hour,$mday,$mon,$year);
105         my $value = $msec + 1000 * $value;
106         my $insert = "$type#$name#$value${msec}#[]\n";
107         $extralines = "$extralines$insert";
108     }
109   }
110
111   close $f;
112
113   #TODO: do it perl way
114   `cat $OUTPUT_DIR/tmp/prof.tmp | sort -k3,3 -t"#" -n > $OUTPUT_DIR/tmp/prof.tmp.new && mv $OUTPUT_DIR/tmp/prof.tmp.new $OUTPUT_DIR/tmp/prof.tmp`;
115
116   open my $fin, "<", "$OUTPUT_DIR/tmp/prof.tmp";
117   while (my $line = <$fin>) {
118     chomp $line;
119     if ($line =~ /^#Profiling_Started#/) {
120         if (defined $stream) {
121             printf $stream "#Profiling_Started#%d%06d#[]\n", $startSec, $startUSec;
122         }
123     } elsif ($line =~ /###PROFILING###STOP###/) {
124         if (defined $stream) {
125             print $stream "$extralines###PROFILING###STOP###\n";
126         }
127         } else {
128         if (defined $stream) {
129             print $stream "$line\n";
130         }
131     }
132   }
133   close $fin;
134 }
135
136 # $mode:
137 #   simple       - just run the widget, no special preparations
138 #   cold         - after cache clean
139 #   warm         - the same widget first launched w/o logs for "warm-up"
140 #   double-warm  - two warm-up launches prior to proper test
141 #   preload      - preloaded webkit library and its dependencies
142 #  TODO - OTHER MODES:
143 #     - warming-up with ANOTHER widget?
144 #     - warming-up by copying all required binaries/libraries to /dev/null
145 #     - running with all binaries/libraries placed on tmpfs (i.e. in cache)
146 #     - first clean cache, then fill it with garbage, by copying lots
147 #       of useless data from disk to /dev/null, until `free' shows small
148 #       enough free memory level
149 sub runTest {
150     my $widgetTizenId = shift;
151     my $mode = shift;
152     my $stream = shift;
153     my $streamout = shift;
154     my $fnameerr = shift;
155
156     if ($mode eq 'simple') {
157         # no preparations necessary
158     } elsif ($mode eq 'cold') {
159         `$COLD_START_PREPARE_COMMAND`;
160     } elsif ($mode eq 'warm') {
161         runWidget( $widgetTizenId, undef, undef, undef );
162     } elsif ($mode eq 'double-warm') {
163         runWidget( $widgetTizenId, undef, undef, undef );
164         runWidget( $widgetTizenId, undef, undef, undef );
165     } elsif ($mode eq 'preload') {
166         `$COLD_START_PREPARE_COMMAND`;
167         `$PRELOAD_LIBRARIES`;
168     } else {
169         die;
170     }
171     runWidget( $widgetTizenId, $stream, $streamout, $fnameerr );
172 }
173
174 ##### Widget installation
175
176 # returns \% a map: name->tizenId
177 sub dropAndInstallAll {
178     my $pwidgets = shift;
179
180     {
181         print "Uninstalling all widgets\n";
182         my @out = `$WRT_CLIENT_QUERY`;
183         for my $line (@out) {
184             if (my ($tizenId) = $line =~ /^\s+\d+.*\s+([A-Za-z0-9]+)$/) {
185                 my $command = $WRT_CLIENT_UNINSTALL;
186                 $command =~ s/\{\}/$tizenId/g;
187                 print "    uninstalling widget $tizenId [$command]\n";
188                 `$command > /dev/null 2>/dev/null`;
189             }
190         }
191     }
192     {
193         print "Checking if widget list is empty\n";
194         my @out = `$WRT_CLIENT_QUERY`;
195         for my $line (@out) {
196             if (my ($tizenId) = $line =~ /^\s+\d+.*\s+([A-Za-z0-9]+)$/) {
197                 print "WIDGET LIST NOT EMPTY!!!\n";
198                 die;
199             }
200         }
201     }
202     {
203         print "Installing all test widgets\n";
204         for my $pwidgetData (@$pwidgets) {
205             my ($package, $name) = @$pwidgetData;
206             my $command = $WRT_CLIENT_INSTALL;
207             $command =~ s/\{\}/$WIDGET_PACKAGE_DIR\/$package/g;
208             print "    installing $name ($package) [$command]\n";
209             `$command > /dev/null 2>/dev/null`;
210         }
211     }
212     {
213         print "Checking if all widgets are installed, determining tizenIds\n";
214         my %widgetMap = ();
215         for my $pwidgetData (@$pwidgets) {
216             my ($package, $name) = @$pwidgetData;
217             $widgetMap{$name} = undef;
218         }
219         my @out = `$WRT_CLIENT_QUERY`;
220         for my $line (@out) {
221             if (my ($name, $trash, $tizenId) = $line =~ /^\s*\d+\s+(([^ ]| [^ ])+)\s+.*\s+([A-Za-z0-9]{10}\.[^\s]+)\s*$/) {
222                 print "    found $name (tizenId $tizenId)\n";
223                 $widgetMap{$name} = $tizenId;
224             }
225         }
226         for my $name (keys %widgetMap) {
227             unless (defined $widgetMap{$name}) {
228                 print "    MISSING $name\n";
229                 die;
230             }
231         }
232         return \%widgetMap;
233 }
234 }
235
236
237 ##### Test schemes
238
239 # PARAMS:
240 #   \@ list of widgets  (can be undef, then will use @WIDGETS)
241 #   \@ list of modes (modes can be as in runTest)
242 #   number of repetitions of one widget/mode pair
243 sub fullRandomTest {
244     my $pwidgets = shift; $pwidgets = \@WIDGETS unless defined $pwidgets;
245 my $pmodes = shift;
246 my $repetitions = shift;
247
248 my $pwidgetMap = dropAndInstallAll( $pwidgets );
249
250 my @testList = ();
251
252 print "Preparing the test list\n";
253 for my $pwidget (@$pwidgets) {
254     my ($package, $name) = @$pwidget;
255     for my $mode (@$pmodes) {
256         for (my $number = 0; $number < $repetitions; $number++) {
257             push @testList, [$name, $mode];
258         }
259     }
260 }
261
262 @testList = List::Util::shuffle( @testList );
263
264 print "Clearing the output dir\n";
265 `rm -rf $OUTPUT_DIR`;
266
267 print "Running tests\n";
268 my %runNumbers = ();
269 my $globalTestNumber = 0;
270 my $totalTestCount = @testList;
271 for my $ptest (@testList) {
272     # find test parameters
273     my ($name, $mode) = @$ptest;
274     my $widgetTizenId = $$pwidgetMap{$name};
275     my $runNo = $runNumbers{"$mode|$widgetTizenId"};
276     print "next\n";
277     if (defined $runNo)
278     { $runNo += 1; }
279     else
280     { $runNo = 0; }
281     $runNumbers{"$mode|$widgetTizenId"} = $runNo;
282     $globalTestNumber += 1;
283     print "    Test $globalTestNumber of $totalTestCount: ".
284     "$name ($widgetTizenId) run $runNo, $mode\n";
285
286     # remove and create output dir
287     my $prepName = $name;
288     $prepName =~ s/ /_/g;
289     my $dirName = sprintf "$OUTPUT_DIR/$prepName/$mode/run%03d", $runNo;
290     `mkdir -p $dirName`;
291
292     # create output files
293     open my $outFile, ">", "$dirName/prof-raw-data" or die;
294     open my $dumpOutFile, ">", "$dirName/dump-stdout" or die;
295
296     # run test
297     runTest( $widgetTizenId, $mode, $outFile, $dumpOutFile, "$dirName/dump-stderr" );
298
299     # close output files
300     close $outFile;
301     close $dumpOutFile;
302     print "Done\n";
303 }
304 }
305
306 ##### MAIN #####
307
308 fullRandomTest( undef, ['cold', 'warm', 'preload'], 10 );