| /* | 
 |  * Copyright 2013 Google Inc. | 
 |  * | 
 |  * Use of this source code is governed by a BSD-style license that can be | 
 |  * found in the LICENSE file. | 
 |  */ | 
 |  | 
 | #include "bench/Benchmark.h" | 
 | #include "include/core/SkString.h" | 
 | #include "include/private/SkTemplates.h" | 
 | #include "include/utils/SkRandom.h" | 
 | #include "src/core/SkTSort.h" | 
 |  | 
 | #include <algorithm> | 
 | #include <stdlib.h> | 
 |  | 
 | static const int N = 1000; | 
 |  | 
 | static void rand_proc(int array[N]) { | 
 |     SkRandom rand; | 
 |     for (int i = 0; i < N; ++i) { | 
 |         array[i] = rand.nextS(); | 
 |     } | 
 | } | 
 |  | 
 | static void randN_proc(int array[N]) { | 
 |     SkRandom rand; | 
 |     int mod = N / 10; | 
 |     for (int i = 0; i < N; ++i) { | 
 |         array[i] = rand.nextU() % mod; | 
 |     } | 
 | } | 
 |  | 
 | static void forward_proc(int array[N]) { | 
 |     for (int i = 0; i < N; ++i) { | 
 |         array[i] = i; | 
 |     } | 
 | } | 
 |  | 
 | static void backward_proc(int array[N]) { | 
 |     for (int i = 0; i < N; ++i) { | 
 |         array[i] = -i; | 
 |     } | 
 | } | 
 |  | 
 | static void same_proc(int array[N]) { | 
 |     for (int i = 0; i < N; ++i) { | 
 |         array[i] = N; | 
 |     } | 
 | } | 
 |  | 
 | typedef void (*SortProc)(int array[N]); | 
 |  | 
 | enum Type { | 
 |     kRand, kRandN, kFore, kBack, kSame | 
 | }; | 
 |  | 
 | static const struct { | 
 |     const char* fName; | 
 |     SortProc    fProc; | 
 | } gRec[] = { | 
 |     { "rand", rand_proc }, | 
 |     { "rand10", randN_proc }, | 
 |     { "forward", forward_proc }, | 
 |     { "backward", backward_proc }, | 
 |     { "repeated", same_proc }, | 
 | }; | 
 |  | 
 | static void skqsort_sort(int array[N]) { | 
 |     SkTQSort<int>(array, array + N); | 
 | } | 
 |  | 
 | static void skheap_sort(int array[N]) { | 
 |     SkTHeapSort<int>(array, N); | 
 | } | 
 |  | 
 | extern "C" { | 
 |     static int int_compare(const void* a, const void* b) { | 
 |         const int ai = *(const int*)a; | 
 |         const int bi = *(const int*)b; | 
 |         return ai < bi ? -1 : (ai > bi); | 
 |     } | 
 | } | 
 |  | 
 | static void qsort_sort(int array[N]) { | 
 |     qsort(array, N, sizeof(int), int_compare); | 
 | } | 
 |  | 
 | static void stdsort_sort(int array[N]) { | 
 |     std::sort(array, array+N); | 
 | } | 
 |  | 
 | enum SortType { | 
 |     kSKQSort, kSKHeap, kQSort, kStdSort, | 
 | }; | 
 |  | 
 | static const struct { | 
 |     const char* fName; | 
 |     SortProc    fProc; | 
 | } gSorts[] = { | 
 |     { "skqsort", skqsort_sort }, | 
 |     { "skheap",   skheap_sort }, | 
 |     { "qsort",     qsort_sort }, | 
 |     { "stdsort", stdsort_sort }, | 
 | }; | 
 |  | 
 | class SortBench : public Benchmark { | 
 |     SkString           fName; | 
 |     const Type         fType; | 
 |     const SortProc     fSortProc; | 
 |     SkAutoTMalloc<int> fUnsorted; | 
 |  | 
 | public: | 
 |     SortBench(Type t, SortType s) : fType(t), fSortProc(gSorts[s].fProc) { | 
 |         fName.printf("sort_%s_%s", gSorts[s].fName, gRec[t].fName); | 
 |     } | 
 |  | 
 |     bool isSuitableFor(Backend backend) override { | 
 |         return backend == kNonRendering_Backend; | 
 |     } | 
 |  | 
 | protected: | 
 |     const char* onGetName() override { | 
 |         return fName.c_str(); | 
 |     } | 
 |  | 
 |     // Delayed initialization only done if onDraw will be called. | 
 |     void onDelayedSetup() override { | 
 |         fUnsorted.reset(N); | 
 |         gRec[fType].fProc(fUnsorted.get()); | 
 |     } | 
 |  | 
 |     void onDraw(int loops, SkCanvas*) override { | 
 |         SkAutoTMalloc<int> sorted(N); | 
 |         for (int i = 0; i < loops; i++) { | 
 |             memcpy(sorted.get(), fUnsorted.get(), N*sizeof(int)); | 
 |             fSortProc(sorted.get()); | 
 | #ifdef SK_DEBUG | 
 |             for (int j = 1; j < N; ++j) { | 
 |                 SkASSERT(sorted[j - 1] <= sorted[j]); | 
 |             } | 
 | #endif | 
 |         } | 
 |     } | 
 |  | 
 | private: | 
 |     using INHERITED = Benchmark; | 
 | }; | 
 |  | 
 | /////////////////////////////////////////////////////////////////////////////// | 
 |  | 
 | static Benchmark* NewSkQSort(Type t) { | 
 |     return new SortBench(t, kSKQSort); | 
 | } | 
 | static Benchmark* NewSkHeap(Type t) { | 
 |     return new SortBench(t, kSKHeap); | 
 | } | 
 | static Benchmark* NewQSort(Type t) { | 
 |     return new SortBench(t, kQSort); | 
 | } | 
 | static Benchmark* NewStdSort(Type t) { | 
 |     return new SortBench(t, kStdSort); | 
 | } | 
 |  | 
 | DEF_BENCH( return NewSkQSort(kRand); ) | 
 | DEF_BENCH( return NewSkHeap(kRand); ) | 
 | DEF_BENCH( return NewQSort(kRand); ) | 
 | DEF_BENCH( return NewStdSort(kRand); ) | 
 |  | 
 | DEF_BENCH( return NewSkQSort(kRandN); ) | 
 | DEF_BENCH( return NewSkHeap(kRandN); ) | 
 | DEF_BENCH( return NewQSort(kRandN); ) | 
 | DEF_BENCH( return NewStdSort(kRandN); ) | 
 |  | 
 | DEF_BENCH( return NewSkQSort(kFore); ) | 
 | DEF_BENCH( return NewSkHeap(kFore); ) | 
 | DEF_BENCH( return NewQSort(kFore); ) | 
 | DEF_BENCH( return NewStdSort(kFore); ) | 
 |  | 
 | DEF_BENCH( return NewSkQSort(kBack); ) | 
 | DEF_BENCH( return NewSkHeap(kBack); ) | 
 | DEF_BENCH( return NewQSort(kBack); ) | 
 | DEF_BENCH( return NewStdSort(kBack); ) | 
 |  | 
 | DEF_BENCH( return NewSkQSort(kSame); ) | 
 | DEF_BENCH( return NewSkHeap(kSame); ) | 
 | DEF_BENCH( return NewQSort(kSame); ) | 
 | DEF_BENCH( return NewStdSort(kSame); ) |