Let's benchmark malloc
[WebKit-https.git] / PerformanceTests / MallocBench / MallocBench / message.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 "message.h"
28 #include <dispatch/dispatch.h>
29 #include <stdlib.h>
30 #include <strings.h>
31
32 #include "mbmalloc.h"
33
34 namespace {
35
36 size_t hash(size_t hash, unsigned short a, unsigned short b)
37 {
38     hash += a ^ b;
39     return hash;
40 }
41
42 class Node {
43     static const size_t payloadCount = 128;
44 public:
45     void* operator new(size_t size)
46     {
47         return mbmalloc(size);
48     }
49
50     void operator delete(void* p, size_t size)
51     {
52         mbfree(p, size);
53     }
54
55     Node()
56         : m_payload()
57     {
58     }
59
60     size_t hash(size_t hash)
61     {
62         for (size_t i = 0; i < payloadCount; i += 2)
63             hash = ::hash(hash, m_payload[i], m_payload[i + 1]);
64         return hash;
65     }
66
67 private:
68     unsigned short m_payload[payloadCount];
69 };
70
71 class Message {
72     static const size_t nodeCount = 1 * 1024;
73
74 public:
75     void* operator new(size_t size)
76     {
77         return mbmalloc(size);
78     }
79
80     void operator delete(void* p, size_t size)
81     {
82         mbfree(p, size);
83     }
84
85     Message()
86         : m_buffer(static_cast<Node**>(mbmalloc(nodeCount * sizeof(Node**))))
87     {
88         for (size_t i = 0; i < nodeCount; ++i)
89             m_buffer[i] = new Node;
90     }
91     
92     ~Message()
93     {
94         for (size_t i = 0; i < nodeCount; ++i)
95             delete m_buffer[i];
96         mbfree(m_buffer, nodeCount * sizeof(Node**));
97     }
98
99     size_t hash()
100     {
101         size_t hash = 0;
102         for (size_t i = 0; i < nodeCount; ++i)
103             hash = m_buffer[i]->hash(hash);
104         return hash;
105     }
106
107 private:
108     Node** m_buffer;
109 };
110
111 } // namespace
112
113 void benchmark_message_one(bool isParallel)
114 {
115     if (isParallel)
116         abort();
117
118     const size_t times = 2048;
119     const size_t quantum = 16;
120
121     dispatch_queue_t queue = dispatch_queue_create("message", 0);
122
123     for (size_t i = 0; i < times; i += quantum) {
124         for (size_t j = 0; j < quantum; ++j) {
125             Message* message = new Message;
126             dispatch_async(queue, ^{
127                 size_t hash = message->hash();
128                 if (hash)
129                     abort();
130                 delete message;
131             });
132         }
133         dispatch_sync(queue, ^{ });
134     }
135
136     dispatch_sync(queue, ^{ });
137
138     dispatch_release(queue);
139 }
140
141 void benchmark_message_many(bool isParallel)
142 {
143     if (isParallel)
144         abort();
145
146     const size_t times = 768;
147     const size_t quantum = 16;
148
149     const size_t queueCount = cpuCount() - 1;
150     dispatch_queue_t queues[queueCount];
151     for (size_t i = 0; i < queueCount; ++i)
152         queues[i] = dispatch_queue_create("message", 0);
153
154     for (size_t i = 0; i < times; i += quantum) {
155         for (size_t j = 0; j < quantum; ++j) {
156             for (size_t k = 0; k < queueCount; ++k) {
157                 Message* message = new Message;
158                 dispatch_async(queues[k], ^{
159                     size_t hash = message->hash();
160                     if (hash)
161                         abort();
162                     delete message;
163                 });
164             }
165         }
166
167         for (size_t i = 0; i < queueCount; ++i)
168             dispatch_sync(queues[i], ^{ });
169     }
170
171     for (size_t i = 0; i < queueCount; ++i)
172         dispatch_sync(queues[i], ^{ });
173
174     for (size_t i = 0; i < queueCount; ++i)
175         dispatch_release(queues[i]);
176 }