| /* |
| * Copyright (C) 2014 Apple Inc. All rights reserved. |
| * |
| * Redistribution and use in source and binary forms, with or without |
| * modification, are permitted provided that the following conditions |
| * are met: |
| * 1. Redistributions of source code must retain the above copyright |
| * notice, this list of conditions and the following disclaimer. |
| * 2. Redistributions in binary form must reproduce the above copyright |
| * notice, this list of conditions and the following disclaimer in the |
| * documentation and/or other materials provided with the distribution. |
| * |
| * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY |
| * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE |
| * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR |
| * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR |
| * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, |
| * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, |
| * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR |
| * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY |
| * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
| * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE |
| * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
| */ |
| |
| #include "CPUCount.h" |
| #include "fragment.h" |
| #include <stdlib.h> |
| #include <strings.h> |
| |
| #include "mbmalloc.h" |
| |
| namespace { |
| |
| class Node { |
| public: |
| void* operator new(size_t size) |
| { |
| return mbmalloc(size); |
| } |
| |
| void operator delete(void* p, size_t size) |
| { |
| mbfree(p, size); |
| } |
| |
| Node() |
| : m_next(0) |
| , m_payload() |
| { |
| } |
| |
| Node(Node* next) |
| : m_next(next) |
| , m_payload() |
| { |
| } |
| |
| Node* next() { return m_next; } |
| |
| void validate() |
| { |
| for (size_t i = 0; i < sizeof(m_payload); ++i) { |
| if (m_payload[i]) |
| abort(); |
| } |
| } |
| |
| private: |
| Node* m_next; |
| char m_payload[32 - sizeof(Node*)]; |
| }; |
| |
| } // namespace |
| |
| void validate(Node* head) |
| { |
| for (Node* node = head; node; node = node->next()) |
| node->validate(); |
| } |
| |
| void benchmark_fragment(CommandLine& commandLine) |
| { |
| size_t nodeCount = 128 * 1024; |
| if (commandLine.isParallel()) |
| nodeCount /= cpuCount(); |
| size_t replaceCount = nodeCount / 4; |
| size_t times = 25; |
| |
| srandom(0); // For consistency between runs. |
| |
| for (size_t i = 0; i < times; ++i) { |
| Node** nodes = static_cast<Node**>(mbmalloc(nodeCount * sizeof(Node*))); |
| for (size_t i = 0; i < nodeCount; ++i) |
| nodes[i] = new Node; |
| |
| for (size_t i = 0; i < replaceCount; ++i) { |
| size_t node = random() % nodeCount; |
| |
| delete nodes[node]; |
| nodes[node] = new Node; |
| } |
| |
| for (size_t node = 0; node < nodeCount; ++node) |
| delete nodes[node]; |
| mbfree(nodes, nodeCount * sizeof(Node*)); |
| } |
| } |
| |
| void benchmark_fragment_iterate(CommandLine& commandLine) |
| { |
| size_t nodeCount = 512 * 1024; |
| size_t times = 20; |
| if (commandLine.isParallel()) |
| nodeCount /= cpuCount(); |
| size_t replaceCount = nodeCount / 4; |
| |
| srandom(0); // For consistency between runs. |
| |
| Node** nodes = static_cast<Node**>(mbmalloc(nodeCount * sizeof(Node*))); |
| for (size_t i = 0; i < nodeCount; ++i) |
| nodes[i] = new Node; |
| |
| Node* head = 0; |
| for (size_t i = 0; i < replaceCount; ++i) { |
| size_t node = random() % nodeCount; |
| |
| delete nodes[node]; |
| nodes[node] = 0; |
| head = new Node(head); |
| } |
| |
| for (size_t i = 0; i < times; ++i) |
| validate(head); |
| |
| for (Node* next ; head; head = next) { |
| next = head->next(); |
| delete head; |
| } |
| |
| for (size_t node = 0; node < nodeCount; ++node) { |
| if (!nodes[node]) |
| continue; |
| delete nodes[node]; |
| } |
| mbfree(nodes, nodeCount * sizeof(Node*)); |
| } |