Let's benchmark malloc
[WebKit-https.git] / PerformanceTests / MallocBench / MallocBench / fragment.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 "CPUCount.h"
27 #include "fragment.h"
28 #include <stdlib.h>
29 #include <strings.h>
30
31 #include "mbmalloc.h"
32
33 namespace {
34
35 class Node {
36 public:
37     void* operator new(size_t size)
38     {
39         return mbmalloc(size);
40     }
41
42     void operator delete(void* p, size_t size)
43     {
44         mbfree(p, size);
45     }
46
47     Node()
48         : m_next(0)
49         , m_payload()
50     {
51     }
52
53     Node(Node* next)
54         : m_next(next)
55         , m_payload()
56     {
57     }
58     
59     Node* next() { return m_next; }
60     
61     void validate()
62     {
63         for (size_t i = 0; i < sizeof(m_payload); ++i) {
64             if (m_payload[i])
65                 abort();
66         }
67     }
68
69 private:
70     Node* m_next;
71     char m_payload[32 - sizeof(Node*)];
72 };
73
74 } // namespace
75
76 void validate(Node* head)
77 {
78     for (Node* node = head; node; node = node->next())
79         node->validate();
80 }
81
82 void benchmark_fragment(bool isParallel)
83 {
84     size_t nodeCount = 128 * 1024;
85     if (isParallel)
86         nodeCount /= cpuCount();
87     size_t replaceCount = nodeCount / 4;
88     size_t times = 25;
89
90     srandom(0); // For consistency between runs.
91
92     for (size_t i = 0; i < times; ++i) {
93         Node** nodes = static_cast<Node**>(mbmalloc(nodeCount * sizeof(Node*)));
94         for (size_t i = 0; i < nodeCount; ++i)
95             nodes[i] = new Node;
96
97         for (size_t i = 0; i < replaceCount; ++i) {
98             size_t node = random() % nodeCount;
99
100             delete nodes[node];
101             nodes[node] = new Node;
102         }
103
104         for (size_t node = 0; node < nodeCount; ++node)
105             delete nodes[node];
106         mbfree(nodes, nodeCount * sizeof(Node*));
107     }
108 }
109
110 void benchmark_fragment_iterate(bool isParallel)
111 {
112     size_t nodeCount = 512 * 1024;
113     size_t times = 32;
114     if (isParallel)
115         nodeCount /= cpuCount();
116     size_t replaceCount = nodeCount / 4;
117
118     srandom(0); // For consistency between runs.
119
120     Node** nodes = static_cast<Node**>(mbmalloc(nodeCount * sizeof(Node*)));
121     for (size_t i = 0; i < nodeCount; ++i)
122         nodes[i] = new Node;
123
124     Node* head = 0;
125     for (size_t i = 0; i < replaceCount; ++i) {
126         size_t node = random() % nodeCount;
127
128         delete nodes[node];
129         nodes[node] = 0;
130         head = new Node(head);
131     }
132     
133     for (size_t i = 0; i < times; ++i)
134         validate(head);
135
136     for (Node* next ; head; head = next) {
137         next = head->next();
138         delete head;
139     }
140
141     for (size_t node = 0; node < nodeCount; ++node) {
142         if (!nodes[node])
143             continue;
144         delete nodes[node];
145     }
146     mbfree(nodes, nodeCount * sizeof(Node*));
147 }