blob: b3d1a02b9c7a215c14a0b785e8872209fe56ec36 [file] [log] [blame]
/*
* Copyright 2012 Google Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
// Author: jmarantz@google.com (Joshua Marantz)
//
// Tests a few different alternatives to implementing an ordered container
// supporting push_back and pop_front.
//
//
// Benchmark Time(ns) CPU(ns) Iterations
// ----------------------------------------------------------
// BM_List4 4846 4830 142857
// BM_Deque4 747 750 1000000
// BM_VectorDeque4 468 470 1489362
// BM_DequeUsingStdVector4 1874 1873 368421
// BM_List100 118003 118292 5833
// BM_Deque100 16389 16457 43750
// BM_VectorDeque100 10296 10214 63636
// BM_DequeUsingStdVector100 75617 74286 8750
#include <deque>
#include <list>
#include <vector>
#include "base/logging.h"
#include "pagespeed/kernel/base/benchmark.h"
#include "pagespeed/kernel/base/vector_deque.h"
// Implementation of deque subset interface using vector, with O(N)
// mutations at front and no extra memory. This is for benchmarking
// comparison. Surprisingly it beats List even @ 100 elements.
template<class T>
class DequeUsingStdVector : public std::vector<T> {
public:
void push_front(const T& value) { this->insert(this->begin(), value); }
void pop_front() { this->erase(this->begin()); }
};
template<class Deque> static void FourElementWorkout(int iters,
int num_elements) {
for (int iter = 0; iter < iters; ++iter) {
Deque deque;
// Simple usage as pure stack or queue, but not at the same time.
for (int i = 0; i < num_elements; ++i) { deque.push_back(i); }
for (int i = 0; i < num_elements; ++i) {
CHECK_EQ(i, deque.front());
deque.pop_front();
}
for (int i = 0; i < num_elements; ++i) { deque.push_front(i); }
for (int i = num_elements - 1; i >= 0; --i) {
CHECK_EQ(i, deque.front());
deque.pop_front();
}
for (int i = 0; i < num_elements; ++i) { deque.push_front(i); }
for (int i = 0; i < num_elements; ++i) {
CHECK_EQ(i, deque.back());
deque.pop_back();
}
for (int i = 0; i < num_elements; ++i) { deque.push_back(i); }
for (int i = num_elements - 1; i >= 0; --i) {
CHECK_EQ(i, deque.back());
deque.pop_back();
}
// Comingled pushes to front or back of queue.
for (int i = 0; i < num_elements / 2; ++i) {
deque.push_back(i);
deque.push_front(i);
}
for (int i = 0; i < num_elements; ++i) { deque.pop_back(); }
for (int i = 0; i < num_elements / 2; ++i) {
deque.push_back(i);
deque.push_front(i);
}
for (int i = 0; i < num_elements; ++i) {
deque.pop_front();
}
for (int i = 0; i < num_elements / 2; ++i) {
deque.push_front(i);
deque.push_back(i);
}
for (int i = 0; i < num_elements; ++i) { deque.pop_back(); }
for (int i = 0; i < num_elements / 2; ++i) {
deque.push_front(i);
deque.push_back(i);
}
for (int i = 0; i < num_elements; ++i) { deque.pop_front(); }
// Chasing 1 value pushed onto the back and popped from front.
for (int i = 0; i < 10 * num_elements; ++i) {
deque.push_back(i);
CHECK_EQ(i, deque.front());
deque.pop_front();
}
// Chasing 2 values pushed onto the back and popped from front.
deque.push_back(-1);
for (int i = 0; i < 10 * num_elements; ++i) {
deque.push_back(i);
CHECK_EQ(i - 1, deque.front());
deque.pop_front();
}
deque.pop_front();
// Chasing 1 value pushed onto the front and popped from back.
for (int i = 0; i < 10 * num_elements; ++i) {
deque.push_front(i);
CHECK_EQ(i, deque.back());
deque.pop_back();
}
// Chasing 2 values pushed onto the front and popped from back.
deque.push_front(-1);
for (int i = 0; i < 10 * num_elements; ++i) {
deque.push_front(i);
CHECK_EQ(i - 1, deque.back());
deque.pop_back();
}
deque.pop_back();
}
}
static void BM_List4(int iters) {
FourElementWorkout<std::list<int> >(iters, 4);
}
static void BM_Deque4(int iters) {
FourElementWorkout<std::deque<int> >(iters, 4);
}
static void BM_VectorDeque4(int iters) {
FourElementWorkout<net_instaweb::VectorDeque<int> >(iters, 4);
}
static void BM_DequeUsingStdVector4(int iters) {
FourElementWorkout<DequeUsingStdVector<int> >(iters, 4);
}
static void BM_List100(int iters) {
FourElementWorkout<std::list<int> >(iters, 100);
}
static void BM_Deque100(int iters) {
FourElementWorkout<std::deque<int> >(iters, 100);
}
static void BM_VectorDeque100(int iters) {
FourElementWorkout<net_instaweb::VectorDeque<int> >(iters, 100);
}
static void BM_DequeUsingStdVector100(int iters) {
FourElementWorkout<DequeUsingStdVector<int> >(iters, 100);
}
BENCHMARK(BM_List4);
BENCHMARK(BM_Deque4);
BENCHMARK(BM_VectorDeque4);
BENCHMARK(BM_DequeUsingStdVector4);
BENCHMARK(BM_List100);
BENCHMARK(BM_Deque100);
BENCHMARK(BM_VectorDeque100);
BENCHMARK(BM_DequeUsingStdVector100);