1 /*
2  * Copyright 2013 Google Inc.
3  *
4  * Use of this source code is governed by a BSD-style license that can be
5  * found in the LICENSE file.
6  */
7 
8 #include "bench/Benchmark.h"
9 #include "include/core/SkString.h"
10 #include "include/private/SkTemplates.h"
11 #include "include/utils/SkRandom.h"
12 #include "src/core/SkTSort.h"
13 
14 #include <algorithm>
15 #include <stdlib.h>
16 
17 static const int N = 1000;
18 
rand_proc(int array[N])19 static void rand_proc(int array[N]) {
20     SkRandom rand;
21     for (int i = 0; i < N; ++i) {
22         array[i] = rand.nextS();
23     }
24 }
25 
randN_proc(int array[N])26 static void randN_proc(int array[N]) {
27     SkRandom rand;
28     int mod = N / 10;
29     for (int i = 0; i < N; ++i) {
30         array[i] = rand.nextU() % mod;
31     }
32 }
33 
forward_proc(int array[N])34 static void forward_proc(int array[N]) {
35     for (int i = 0; i < N; ++i) {
36         array[i] = i;
37     }
38 }
39 
backward_proc(int array[N])40 static void backward_proc(int array[N]) {
41     for (int i = 0; i < N; ++i) {
42         array[i] = -i;
43     }
44 }
45 
same_proc(int array[N])46 static void same_proc(int array[N]) {
47     for (int i = 0; i < N; ++i) {
48         array[i] = N;
49     }
50 }
51 
52 typedef void (*SortProc)(int array[N]);
53 
54 enum Type {
55     kRand, kRandN, kFore, kBack, kSame
56 };
57 
58 static const struct {
59     const char* fName;
60     SortProc    fProc;
61 } gRec[] = {
62     { "rand", rand_proc },
63     { "rand10", randN_proc },
64     { "forward", forward_proc },
65     { "backward", backward_proc },
66     { "repeated", same_proc },
67 };
68 
skqsort_sort(int array[N])69 static void skqsort_sort(int array[N]) {
70     SkTQSort<int>(array, array + N);
71 }
72 
skheap_sort(int array[N])73 static void skheap_sort(int array[N]) {
74     SkTHeapSort<int>(array, N);
75 }
76 
77 extern "C" {
int_compare(const void * a,const void * b)78     static int int_compare(const void* a, const void* b) {
79         const int ai = *(const int*)a;
80         const int bi = *(const int*)b;
81         return ai < bi ? -1 : (ai > bi);
82     }
83 }
84 
qsort_sort(int array[N])85 static void qsort_sort(int array[N]) {
86     qsort(array, N, sizeof(int), int_compare);
87 }
88 
stdsort_sort(int array[N])89 static void stdsort_sort(int array[N]) {
90     std::sort(array, array+N);
91 }
92 
93 enum SortType {
94     kSKQSort, kSKHeap, kQSort, kStdSort,
95 };
96 
97 static const struct {
98     const char* fName;
99     SortProc    fProc;
100 } gSorts[] = {
101     { "skqsort", skqsort_sort },
102     { "skheap",   skheap_sort },
103     { "qsort",     qsort_sort },
104     { "stdsort", stdsort_sort },
105 };
106 
107 class SortBench : public Benchmark {
108     SkString           fName;
109     const Type         fType;
110     const SortProc     fSortProc;
111     SkAutoTMalloc<int> fUnsorted;
112 
113 public:
SortBench(Type t,SortType s)114     SortBench(Type t, SortType s) : fType(t), fSortProc(gSorts[s].fProc) {
115         fName.printf("sort_%s_%s", gSorts[s].fName, gRec[t].fName);
116     }
117 
isSuitableFor(Backend backend)118     bool isSuitableFor(Backend backend) override {
119         return backend == kNonRendering_Backend;
120     }
121 
122 protected:
onGetName()123     const char* onGetName() override {
124         return fName.c_str();
125     }
126 
127     // Delayed initialization only done if onDraw will be called.
onDelayedSetup()128     void onDelayedSetup() override {
129         fUnsorted.reset(N);
130         gRec[fType].fProc(fUnsorted.get());
131     }
132 
onDraw(int loops,SkCanvas *)133     void onDraw(int loops, SkCanvas*) override {
134         SkAutoTMalloc<int> sorted(N);
135         for (int i = 0; i < loops; i++) {
136             memcpy(sorted.get(), fUnsorted.get(), N*sizeof(int));
137             fSortProc(sorted.get());
138 #ifdef SK_DEBUG
139             for (int j = 1; j < N; ++j) {
140                 SkASSERT(sorted[j - 1] <= sorted[j]);
141             }
142 #endif
143         }
144     }
145 
146 private:
147     using INHERITED = Benchmark;
148 };
149 
150 ///////////////////////////////////////////////////////////////////////////////
151 
NewSkQSort(Type t)152 static Benchmark* NewSkQSort(Type t) {
153     return new SortBench(t, kSKQSort);
154 }
NewSkHeap(Type t)155 static Benchmark* NewSkHeap(Type t) {
156     return new SortBench(t, kSKHeap);
157 }
NewQSort(Type t)158 static Benchmark* NewQSort(Type t) {
159     return new SortBench(t, kQSort);
160 }
NewStdSort(Type t)161 static Benchmark* NewStdSort(Type t) {
162     return new SortBench(t, kStdSort);
163 }
164 
165 DEF_BENCH( return NewSkQSort(kRand); )
166 DEF_BENCH( return NewSkHeap(kRand); )
167 DEF_BENCH( return NewQSort(kRand); )
168 DEF_BENCH( return NewStdSort(kRand); )
169 
170 DEF_BENCH( return NewSkQSort(kRandN); )
171 DEF_BENCH( return NewSkHeap(kRandN); )
172 DEF_BENCH( return NewQSort(kRandN); )
173 DEF_BENCH( return NewStdSort(kRandN); )
174 
175 DEF_BENCH( return NewSkQSort(kFore); )
176 DEF_BENCH( return NewSkHeap(kFore); )
177 DEF_BENCH( return NewQSort(kFore); )
178 DEF_BENCH( return NewStdSort(kFore); )
179 
180 DEF_BENCH( return NewSkQSort(kBack); )
181 DEF_BENCH( return NewSkHeap(kBack); )
182 DEF_BENCH( return NewQSort(kBack); )
183 DEF_BENCH( return NewStdSort(kBack); )
184 
185 DEF_BENCH( return NewSkQSort(kSame); )
186 DEF_BENCH( return NewSkHeap(kSame); )
187 DEF_BENCH( return NewQSort(kSame); )
188 DEF_BENCH( return NewStdSort(kSame); )
189