Reputation: 3290
I'm trying to find a fast way to do input but I've learned that using STL for such purposes might be slow.
I have a callback that fires whenever I get Keyboard input.
It creates an object with (int _key, int _state, int _life)
Everytime I receive this callback, I push_back
the object to my std::vector;
Every frame I check the top of this vector and remove the "dead" input.
The vector can be polled for whatever input is valid at that moment which means it will be searched frequently.
Optimizations:
-All the memory should be contiguous so although Link Lists are better for dynamic allocation, should I stick with STL's vector? I'm always adding to the top and removing from the bottom so what data struct should I use?
-I was thinking of having a buffer(second vector) that continuously receives new input from the callback, then each frame copy the data from that vector to the top of my active input vector. Since the active vector will be polled, would this increase performance since it won't be wasting time getting added to during the loop?
Basically I'm trying to squeeze as much performance from this vector as possible and I could use some help.
Upvotes: 1
Views: 322
Reputation: 409166
What you are describing, adding data in one end, removing in another, is the archetypical description of a queue. This is implemented in the standard library with the std::queue
class.
This queue class is a so-called container adapter, meaning it uses another container for the actual storage. By default it uses std::deque
, but that container doesn't keep its data in a contiguous memory area. However you can declare a std::queue
with almost any other standard container, like std::vector
(which is the only container guaranteed to store data in a contiguous memory area):
std::queue<int, std::vector> my_queue_with_vector;
my_queue_with_vector.push(1);
my_queue_with_vector.push(2);
my_queue_with_vector.push(3);
while (!my_queue_with_vector.empty())
{
std::cout << my_queue_with_vector.top() << '\n';
my_queue_with_vector.pop(); // Remove top element in the queue
}
Upvotes: 3
Reputation: 146910
std::deque
makes the best container. It guarantees O(1) pop_front and push_back() and has random access and a good degree (although not completely) of cache behaviour.
But if you absolutely must have complete contiguity, then you'll need to look into a custom circular buffer container (there's one in Boost IIRC), as pop_front() on a vector
is rather expensive.
Edit: As another poster has pointed out, keyboard input is so infrequent even for a very fast typist that I find it difficult to believe that this is a bottleneck in your system.
Upvotes: 3
Reputation: 5728
Short answer: It doesn't matter. std::vector and std::list can easily handle millions of insert operations per second, but most typists don't type faster than 10 characters per second on a keyboard.
Long answer: push_back and erase are usually very cheap on a vector if the vector is small (< 100) and the copy/swap operations of the objects stored on the vector are cheap. The allocations used to insert into or remove from an std:list are usually more expensive. If it becomes an issue, measure the cost.
An std::deque also has allocations and depending on the implementation is likely more expensive than the vector in your case, if my assumption that your vector rarely if ever contains more than 10 items - all of which are cheap to copy - is correct.
Upvotes: 0
Reputation: 52519
Sounds like you want a std::deque
. Adjacents elements are nearly always allocated continuously in memory and it has constant time insertion and removal at begin and end.
Upvotes: 1