MallocBench: Added recording for nimlang website, new recording details and added...
[WebKit-https.git] / PerformanceTests / MallocBench / MallocBench / stress_aligned.cpp
1 /*
2  * Copyright (C) 2014 Apple Inc. All rights reserved.
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions
6  * are met:
7  * 1. Redistributions of source code must retain the above copyright
8  *    notice, this list of conditions and the following disclaimer.
9  * 2. Redistributions in binary form must reproduce the above copyright
10  *    notice, this list of conditions and the following disclaimer in the
11  *    documentation and/or other materials provided with the distribution.
12  *
13  * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
14  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
15  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
16  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
17  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
18  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
19  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
20  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
21  * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
23  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
24  */
25
26 #include "Benchmark.h"
27 #include "CPUCount.h"
28 #include "stress_aligned.h"
29 #include <array>
30 #include <chrono>
31 #include <cmath>
32 #include <cstdlib>
33 #include <memory>
34 #include <stddef.h>
35 #include <vector>
36
37 #include "mbmalloc.h"
38
39 namespace {
40
41 static const size_t kB = 1024;
42 static const size_t MB = kB * kB;
43
44 struct Object {
45     Object(void* pointer, size_t size, long uuid)
46         : pointer(pointer)
47         , size(size)
48         , uuid(uuid)
49     {
50     }
51
52     void* pointer;
53     size_t size;
54     long uuid;
55 };
56
57 class SizeStream {
58 public:
59     SizeStream()
60         : m_state(Small)
61         , m_count(0)
62     {
63     }
64
65     size_t next()
66     {
67         switch (m_state) {
68         case Small: {
69             if (++m_count == smallCount) {
70                 m_state = Medium;
71                 m_count = 0;
72             }
73             return random() % smallMax;
74         }
75
76         case Medium: {
77             if (++m_count == mediumCount) {
78                 m_state = Large;
79                 m_count = 0;
80             }
81             return random() % mediumMax;
82         }
83
84         case Large: {
85             if (++m_count == largeCount) {
86                 m_state = Small;
87                 m_count = 0;
88             }
89             return random() % largeMax;
90         }
91         }
92     }
93
94 private:
95     static const size_t smallCount = 1000;
96     static const size_t smallMax = 16 * kB;
97
98     static const size_t mediumCount = 100;
99     static const size_t mediumMax = 512 * kB;
100     
101     static const size_t largeCount = 10;
102     static const size_t largeMax = 4 * MB;
103
104     enum { Small, Medium, Large } m_state;
105     size_t m_count;
106 };
107
108 Object allocate(size_t alignment, size_t size)
109 {
110     Object object(mbmemalign(alignment, size), size, random());
111     if ((uintptr_t)object.pointer & (alignment - 1))
112         abort();
113     for (size_t i = 0; i < size / sizeof(long); ++i)
114         (static_cast<long*>(object.pointer))[i] = object.uuid;
115     return object;
116 }
117
118 void deallocate(const Object& object)
119 {
120     for (size_t i = 0; i < object.size / sizeof(long); ++i) {
121         if ((static_cast<long*>(object.pointer))[i] != object.uuid)
122             abort();
123     }
124
125     mbfree(object.pointer, object.size);
126 }
127
128 size_t randomAlignment()
129 {
130     switch (random() % 32) {
131     case 0:
132         return pow(2, random() % 26);
133     default:
134         return pow(2, random() % 14);
135     }
136 }
137
138 }
139
140 void benchmark_stress_aligned(CommandLine&)
141 {
142     const size_t heapSize = 100 * MB;
143     const size_t churnSize = .05 * heapSize;
144     const size_t churnCount = 100;
145     
146     srandom(1); // For consistency between runs.
147
148     std::vector<Object> objects;
149     
150     SizeStream sizeStream;
151     
152     size_t size = 0;
153     for (size_t remaining = heapSize; remaining; remaining -= std::min(remaining, size)) {
154         size = sizeStream.next();
155         objects.push_back(allocate(randomAlignment(), size));
156     }
157     
158     for (size_t i = 0; i < churnCount; ++i) {
159         std::vector<Object> objectsToFree;
160         for (size_t remaining = churnSize; remaining; remaining -= std::min(remaining, size)) {
161             size = sizeStream.next();
162             Object object = allocate(randomAlignment(), size);
163
164             size_t index = random() % objects.size();
165             objectsToFree.push_back(objects[index]);
166             objects[index] = object;
167         }
168
169         for (auto& object : objectsToFree)
170             deallocate(object);
171         
172         mbscavenge();
173     }
174     
175     for (auto& object : objects)
176         mbfree(object.pointer, object.size);
177 }