| Index: dm/DM.cpp
|
| diff --git a/dm/DM.cpp b/dm/DM.cpp
|
| index a046421908e7ee6be0694c2bbb57b653c26fc53f..236fce870808b2b220c3378c2711d84e8a35d13f 100644
|
| --- a/dm/DM.cpp
|
| +++ b/dm/DM.cpp
|
| @@ -9,7 +9,6 @@
|
| #include "DMJsonWriter.h"
|
| #include "DMSrcSink.h"
|
| #include "DMSrcSinkAndroid.h"
|
| -#include "OverwriteLine.h"
|
| #include "ProcStats.h"
|
| #include "SkBBHFactory.h"
|
| #include "SkChecksum.h"
|
| @@ -82,10 +81,10 @@ static void fail(ImplicitString err) {
|
| gFailures.push_back(err);
|
| }
|
|
|
| -static int32_t gPending = 0; // Atomic. Total number of running and queued tasks.
|
|
|
| // We use a spinlock to make locking this in a signal handler _somewhat_ safe.
|
| -SK_DECLARE_STATIC_SPINLOCK(gRunningAndTallyMutex);
|
| +SK_DECLARE_STATIC_SPINLOCK(gMutex);
|
| +static int32_t gPending;
|
| static SkTArray<SkString> gRunning;
|
| static SkTHashMap<SkString, int> gNoteTally;
|
|
|
| @@ -94,8 +93,9 @@ static void done(double ms,
|
| ImplicitString name, ImplicitString note, ImplicitString log) {
|
| SkString id = SkStringPrintf("%s %s %s %s", config.c_str(), src.c_str(),
|
| srcOptions.c_str(), name.c_str());
|
| + int pending;
|
| {
|
| - SkAutoTAcquire<SkPODSpinlock> lock(gRunningAndTallyMutex);
|
| + SkAutoTAcquire<SkPODSpinlock> lock(gMutex);
|
| for (int i = 0; i < gRunning.count(); i++) {
|
| if (gRunning[i] == id) {
|
| gRunning.removeShuffle(i);
|
| @@ -109,19 +109,7 @@ static void done(double ms,
|
| gNoteTally.set(note, 1);
|
| }
|
| }
|
| - }
|
| - if (!log.isEmpty()) {
|
| - log.prepend("\n");
|
| - }
|
| - auto pending = sk_atomic_dec(&gPending)-1;
|
| - if (!FLAGS_quiet && note.isEmpty()) {
|
| - SkDebugf("%s(%4d/%-4dMB %6d) %s\t%s%s", FLAGS_verbose ? "\n" : kSkOverwriteLine
|
| - , sk_tools::getCurrResidentSetSizeMB()
|
| - , sk_tools::getMaxResidentSetSizeMB()
|
| - , pending
|
| - , HumanizeMs(ms).c_str()
|
| - , id.c_str()
|
| - , log.c_str());
|
| + pending = --gPending;
|
| }
|
| // We write our dm.json file every once in a while in case we crash.
|
| // Notice this also handles the final dm.json when pending == 0.
|
| @@ -134,10 +122,25 @@ static void start(ImplicitString config, ImplicitString src,
|
| ImplicitString srcOptions, ImplicitString name) {
|
| SkString id = SkStringPrintf("%s %s %s %s", config.c_str(), src.c_str(),
|
| srcOptions.c_str(), name.c_str());
|
| - SkAutoTAcquire<SkPODSpinlock> lock(gRunningAndTallyMutex);
|
| + SkAutoTAcquire<SkPODSpinlock> lock(gMutex);
|
| gRunning.push_back(id);
|
| }
|
|
|
| +static void print_status() {
|
| + static SkMSec start_ms = SkTime::GetMSecs();
|
| +
|
| + int curr = sk_tools::getCurrResidentSetSizeMB(),
|
| + peak = sk_tools::getMaxResidentSetSizeMB();
|
| + SkString elapsed = HumanizeMs(SkTime::GetMSecs() - start_ms);
|
| +
|
| + SkAutoTAcquire<SkPODSpinlock> lock(gMutex);
|
| + SkDebugf("\n%s elapsed, %d active, %d queued, %dMB RAM, %dMB peak\n",
|
| + elapsed.c_str(), gRunning.count(), gPending - gRunning.count(), curr, peak);
|
| + for (auto& task : gRunning) {
|
| + SkDebugf("\t%s\n", task.c_str());
|
| + }
|
| +}
|
| +
|
| #if defined(SK_BUILD_FOR_WIN32)
|
| static void setup_crash_handler() {
|
| // TODO: custom crash handler like below to print out what was running
|
| @@ -150,12 +153,8 @@ static void start(ImplicitString config, ImplicitString src,
|
| const int kSignals[] = { SIGABRT, SIGBUS, SIGFPE, SIGILL, SIGSEGV };
|
| for (int sig : kSignals) {
|
| signal(sig, [](int sig) {
|
| - SkAutoTAcquire<SkPODSpinlock> lock(gRunningAndTallyMutex);
|
| - SkDebugf("\nCaught signal %d [%s] while running %d tasks:\n",
|
| - sig, strsignal(sig), gRunning.count());
|
| - for (auto& task : gRunning) {
|
| - SkDebugf("\t%s\n", task.c_str());
|
| - }
|
| + SkDebugf("\nCaught signal %d [%s].\n", sig, strsignal(sig));
|
| + print_status();
|
| });
|
| }
|
| }
|
| @@ -901,9 +900,6 @@ struct Task {
|
| if (!FLAGS_dryRun && note.isEmpty()) {
|
| SkBitmap bitmap;
|
| SkDynamicMemoryWStream stream;
|
| - if (FLAGS_pre_log) {
|
| - SkDebugf("\nRunning %s->%s", name.c_str(), task.sink.tag.c_str());
|
| - }
|
| start(task.sink.tag.c_str(), task.src.tag, task.src.options, name.c_str());
|
| Error err = task.sink->draw(*task.src, &bitmap, &stream, &log);
|
| if (!err.isEmpty()) {
|
| @@ -1102,9 +1098,6 @@ static void run_test(skiatest::Test test) {
|
| if (!FLAGS_dryRun && whyBlacklisted.isEmpty()) {
|
| start("unit", "test", "", test.name);
|
| GrContextFactory factory;
|
| - if (FLAGS_pre_log) {
|
| - SkDebugf("\nRunning test %s", test.name);
|
| - }
|
| test.proc(&reporter, &factory);
|
| }
|
| done(now_ms()-timerStart, "unit", "test", "", test.name, note, "");
|
| @@ -1112,31 +1105,21 @@ static void run_test(skiatest::Test test) {
|
|
|
| /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
|
|
|
| -// Some runs (mostly, Valgrind) are so slow that the bot framework thinks we've hung.
|
| -// This prints something every once in a while so that it knows we're still working.
|
| -static void start_keepalive() {
|
| - struct Loop {
|
| - static void forever(void*) {
|
| - for (;;) {
|
| - static const int kSec = 300;
|
| - #if defined(SK_BUILD_FOR_WIN)
|
| - Sleep(kSec * 1000);
|
| - #else
|
| - sleep(kSec);
|
| - #endif
|
| - SkString running;
|
| - {
|
| - SkAutoTAcquire<SkPODSpinlock> lock(gRunningAndTallyMutex);
|
| - for (int i = 0; i < gRunning.count(); i++) {
|
| - running.appendf("\n\t%s", gRunning[i].c_str());
|
| - }
|
| - }
|
| - SkDebugf("\nCurrently running:%s\n", running.c_str());
|
| - }
|
| +DEFINE_int32(status_sec, 15, "Print status this often (and if we crash).");
|
| +
|
| +SkThread* start_status_thread() {
|
| + auto thread = new SkThread([] (void*) {
|
| + for (;;) {
|
| + print_status();
|
| + #if defined(SK_BUILD_FOR_WIN)
|
| + Sleep(FLAGS_status_sec * 1000);
|
| + #else
|
| + sleep(FLAGS_status_sec);
|
| + #endif
|
| }
|
| - };
|
| - static SkThread* intentionallyLeaked = new SkThread(Loop::forever);
|
| - intentionallyLeaked->start();
|
| + });
|
| + thread->start();
|
| + return thread;
|
| }
|
|
|
| #define PORTABLE_FONT_PREFIX "Toy Liberation "
|
| @@ -1156,13 +1139,12 @@ extern SkTypeface* (*gCreateTypefaceDelegate)(const char [], SkTypeface::Style )
|
| int dm_main();
|
| int dm_main() {
|
| setup_crash_handler();
|
| +
|
| JsonWriter::DumpJson(); // It's handy for the bots to assume this is ~never missing.
|
| SkAutoGraphics ag;
|
| SkTaskGroup::Enabler enabled(FLAGS_threads);
|
| gCreateTypefaceDelegate = &create_from_name;
|
|
|
| - start_keepalive();
|
| -
|
| gather_gold();
|
| gather_uninteresting_hashes();
|
|
|
| @@ -1173,8 +1155,9 @@ int dm_main() {
|
| gather_tests();
|
|
|
| gPending = gSrcs.count() * gSinks.count() + gParallelTests.count() + gSerialTests.count();
|
| - SkDebugf("%d srcs * %d sinks + %d tests == %d tasks\n",
|
| + SkDebugf("%d srcs * %d sinks + %d tests == %d tasks",
|
| gSrcs.count(), gSinks.count(), gParallelTests.count() + gSerialTests.count(), gPending);
|
| + SkAutoTDelete<SkThread> statusThread(start_status_thread());
|
|
|
| // Kick off as much parallel work as we can, making note of any serial work we'll need to do.
|
| SkTaskGroup parallel;
|
| @@ -1220,13 +1203,12 @@ int dm_main() {
|
| SkDebugf("%d failures\n", gFailures.count());
|
| return 1;
|
| }
|
| - if (gPending > 0) {
|
| - SkDebugf("Hrm, we didn't seem to run everything we intended to! Please file a bug.\n");
|
| - return 1;
|
| - }
|
| - #ifdef SK_PDF_IMAGE_STATS
|
| +
|
| +#ifdef SK_PDF_IMAGE_STATS
|
| SkPDFImageDumpStats();
|
| - #endif // SK_PDF_IMAGE_STATS
|
| +#endif // SK_PDF_IMAGE_STATS
|
| +
|
| + print_status();
|
| SkDebugf("Finished!\n");
|
| return 0;
|
| }
|
|
|