Ejemplo n.º 1
0
    public static void Main(string[] args)
    {
        var benchmarksnames = new string[0];
        var architecture    = Environment.Is64BitOperatingSystem ? "amd64" : "x86";
        var commit          = String.Empty;
        var timeout         = Int32.MaxValue;
        var sshkey          = String.Empty;
        var upload          = false;

        var optindex = 0;

        for (; optindex < args.Length; ++optindex)
        {
            if (args [optindex] == "-b" || args [optindex] == "--benchmarks")
            {
                benchmarksnames = args [++optindex].Split(',').Select(s => s.Trim()).Union(benchmarksnames).ToArray();
            }
            else if (args [optindex] == "-a" || args [optindex] == "--architecture")
            {
                architecture = args [++optindex];
            }
            else if (args [optindex] == "-c" || args [optindex] == "--commit")
            {
                commit = args [++optindex];
            }
            else if (args [optindex] == "-t" || args [optindex] == "--timeout")
            {
                timeout = Int32.Parse(args [++optindex]);
            }
            else if (args [optindex] == "--sshkey")
            {
                sshkey = args [++optindex];
            }
            else if (args [optindex] == "-u" || args [optindex] == "--upload")
            {
                upload = true;
            }
            else if (args [optindex].StartsWith("--help"))
            {
                UsageAndExit();
            }
            else if (args [optindex] == "--")
            {
                optindex += 1;
                break;
            }
            else if (args [optindex].StartsWith("-"))
            {
                Console.Error.WriteLine("unknown parameter {0}", args [optindex]);
                UsageAndExit();
            }
            else
            {
                break;
            }
        }

        if (args.Length - optindex < 3)
        {
            UsageAndExit(null, 1);
        }

        var testsdir      = args [optindex++];
        var benchmarksdir = args [optindex++];
        var configfiles   = args.Skip(optindex).ToArray();

        var benchmarks = Benchmark.LoadAllFrom(benchmarksdir, benchmarksnames).OrderBy(b => b.Name).ToArray();
        var configs    = configfiles.Select(c => Config.LoadFrom(c)).ToArray();

        var revision = String.IsNullOrEmpty(commit) ? Revision.Last("mono", architecture) : Revision.Get("mono", architecture, commit);

        if (revision == null)
        {
            Console.Out.WriteLine("Revision not found");
            Environment.Exit(2);
        }

        var revisionfolder = Directory.CreateDirectory(Path.Combine(Path.GetTempPath(), Path.GetRandomFileName())).FullName;
        var profilesfolder = Directory.CreateDirectory(Path.Combine(revisionfolder, String.Join("_", revision.CommitDate.ToString("s").Replace(':', '-'), revision.Commit))).FullName;

        if (!revision.FetchInto(revisionfolder))
        {
            Environment.Exit(0);
        }

        var profiles = new List <ProfileResult> (benchmarks.Length * configs.Length);

        foreach (var benchmark in benchmarks)
        {
            foreach (var config in configs)
            {
                Console.Out.WriteLine("Profiling benchmark \"{0}\" with config \"{1}\"", benchmark.Name, config.Name);

                var timedout = false;

                var info = new ProcessStartInfo {
                    FileName         = Path.Combine(revisionfolder, "mono"),
                    WorkingDirectory = Path.Combine(testsdir, benchmark.TestDirectory),
                    UseShellExecute  = false,
                };

                foreach (var env in config.MonoEnvironmentVariables)
                {
                    if (env.Key == "MONO_PATH" || env.Key == "LD_LIBRARY_PATH")
                    {
                        continue;
                    }

                    info.EnvironmentVariables.Add(env.Key, env.Value);
                }

                info.EnvironmentVariables.Add("MONO_PATH", revisionfolder);
                info.EnvironmentVariables.Add("LD_LIBRARY_PATH", revisionfolder);

                var envvar = String.Join(" ", config.MonoEnvironmentVariables.Union(new KeyValuePair <string, string>[] { new KeyValuePair <string, string> ("MONO_PATH", revisionfolder), new KeyValuePair <string, string> ("LD_LIBRARY_PATH", revisionfolder) })
                                         .Select(kv => kv.Key + "=" + kv.Value));

                var arguments = String.Join(" ", config.MonoOptions.Union(benchmark.CommandLine));

                var profile = new ProfileResult {
                    DateTime = DateTime.Now, Benchmark = benchmark, Config = config, Revision = revision, Timedout = timedout, Runs = new ProfileResult.Run [config.Count]
                };

                for (var i = 0; i < config.Count; ++i)
                {
                    var profilefilename = String.Join("_", new string [] { ProfileFilename(profile), i.ToString() }) + ".mlpd";

                    info.Arguments = String.Format("--profile=log:counters,countersonly,nocalls,noalloc,output={0} ", Path.Combine(
                                                       profilesfolder, profilefilename)) + arguments;

                    Console.Out.WriteLine("$> {0} {1} {2}", envvar, info.FileName, info.Arguments);

                    timeout = benchmark.Timeout > 0 ? benchmark.Timeout : timeout;

                    var sw = Stopwatch.StartNew();

                    var process = Process.Start(info);

                    var success = process.WaitForExit(timeout < 0 ? -1 : (Math.Min(Int32.MaxValue / 1000, timeout) * 1000));

                    sw.Stop();

                    if (!success)
                    {
                        process.Kill();
                    }

                    Console.Out.WriteLine("-> ({0}/{1}) {2}", i + 1, config.Count, success ? sw.Elapsed.ToString() : "timeout!");

                    profile.Runs [i] = new ProfileResult.Run {
                        Index          = i,
                        WallClockTime  = success ? TimeSpan.FromTicks(sw.ElapsedTicks) : TimeSpan.Zero,
                        ProfilerOutput = profilefilename
                    };

                    profile.Timedout = profile.Timedout || !success;
                }

                profiles.Add(profile);
            }
        }

        Parallel.ForEach(profiles, profile => {
            Parallel.ForEach(profile.Runs, run => {
                run.Counters     = ProfileResult.Run.ParseCounters(Path.Combine(profilesfolder, run.ProfilerOutput));
                run.CountersFile = ProfileFilename(profile) + "_" + run.Index + ".counters.json.gz";
                run.StoreCountersTo(Path.Combine(profilesfolder, run.CountersFile));
            });

            profile.StoreTo(Path.Combine(profilesfolder, ProfileFilename(profile) + ".json.gz"), true);
        });

        if (upload)
        {
            Console.Out.WriteLine("Copying files to storage from \"{0}\"", profilesfolder);
            SCPToRemote(sshkey, profilesfolder, "/volume1/storage/benchmarker/runs/mono/" + architecture);
        }
    }