The compiler might be able to optimize the
at()
call since it knows the index is in bounds. Also, you need to account for the time taken by the test itself.
To get around these, I put the actual
at()
and
[]
calls into functions in a separate compilation unit. I also included a function that just returns 1:
1 2 3 4 5 6 7 8 9 10 11 12 13
|
#include <vector>
int doAt(std::vector<int> &v, size_t i) {
return v.at(i);
}
int doBracket(std::vector<int> &v, size_t i) {
return v[i];
}
int doNil(std::vector<int> &v, size_t i) {
return 1;
}
|
Then I modified poteto's code to call these functions:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58
|
#include <iostream>
#include <vector>
#include <chrono>
//timers.
typedef std::chrono::steady_clock::time_point TIMER_U;
typedef double TIMER_RESULT_U;
TIMER_U get_time(){
return std::chrono::steady_clock::now();
}
template<size_t resolution = 1000>
TIMER_RESULT_U timer_delta(const TIMER_U &start, const TIMER_U &end)
{
return std::chrono::duration_cast< std::chrono::duration<TIMER_RESULT_U, std::ratio<1, resolution>>>(end-start).count();
}
extern int doAt(std::vector<int> &v, size_t i);
extern int doBracket(std::vector<int> &v, size_t i);
extern int doNil(std::vector<int> &v, size_t i);
int main()
{
std::vector<int> v;
v.resize(1000000,1);
int count = 0;
TIMER_U t1 = get_time();
for(int i = 0; i < v.size(); ++i)
{
count += doAt(v,i);
}
TIMER_U t2 = get_time();
std::cout <<"at() time: "<<timer_delta(t1,t2)<<", i:"<<count<<std::endl;
t1 = get_time();
for(int i = 0; i < v.size(); ++i)
{
count += doBracket(v,i);
}
t2 = get_time();
std::cout <<"[] time: "<<timer_delta(t1,t2)<<", i:"<<count<<std::endl;
t1 = get_time();
for(int i = 0; i < v.size(); ++i)
{
count += doNil(v,i);
}
t2 = get_time();
std::cout <<"nil time: "<<timer_delta(t1,t2)<<", i:"<<count<<std::endl;
return 0;
}
|
Compiling with g++ -O4 and running several times, I get these times:
at() time: 1.6251, i:1000000
[] time: 1.4352, i:2000000
nil time: 1.2668, i:3000000
Subtracting the nil time gives the time difference for at() vs. []:
at() time: 0.3583
[] time: 0.1684
So it appears that at() is actually more than twice as slow.