Optimizing CPU load and time in a C++ for loop - c++

I have a C++ function which is called event based on node value change. This function involves a for loop which reads around 5000 nodes for the first time and perform some calculation on them. During a read attempt, each node is assigned a node ID by comparing their subscription ID (unique for each node). During the next event this function is called again with nodes whose values are changed. Now this same process is performed, assigning node IDs (using subscription ID) in a for loop reading those 5000 stored nodes again.
The question is, is there a better way to link these nodes IDs in the first event run so that next time this event occurs, all the nodes whose value changes do not need to be checked for their node IDs? The subscription ID is a unique number here. At present this function is event based and called very frequently, so comparing 5000 nodes every second causes its CPU load to be always up.
The code:
void SubscriptionEvent::handleEvent(EventSource *source, EventArguments *args)
{
SubscriptionEventArgs* subsArgs = static_cast<SubscriptionEventArgs*>(args);
vector<string> m_devicesReset;
if (subsArgs->eventType == SubscriptionEventArgs::VALUECHANGE)
{
AgrClient *client = static_cast<AgrClient *>(source);
OpcUa_UInt32 i = 0;
bool valueChange = false;
if(m_firstEvent == true)
{
for (i = 0; i < subsArgs->dataNotifications->length(); i++)
{
if (OpcUa_IsGood((*subsArgs->dataNotifications)[i].Value.StatusCode))
{
UaNodeId nodeId;
UaStatus status = client->getNodeIdForSubscriptionId((*subsArgs->dataNotifications)[i].ClientHandle, nodeId); //improve
}
}
}
}
}
}
The below input argument
(*subsArgs->dataNotifications)[i].ClientHandle
is the subscription ID I provide every time to get the nodeId. This last line is the code is to be improved, because the function getNodeIdForSubscriptionId() runs through a for loop to search for the nodeId for the provided subscription ID.

Related

How do I access data in a class stored in a node through queue pointers?

In my current assignment I'm having trouble figuring out how I can access this particular piece of data.
To start off, the assignment calls for data to be pulled from a file to simulate a store operating normally. The only thing is, the data being pulled is about the customer. Specifically it's when the customer enters a queue and how long it takes for the cashiers to process their order.
Right now how I have customer data stored in an array of classes.
for(int i = 0; i < entries; i++)
{
/* !!!!!IMPORTANT!!!!!
* The way this program extracts file data assumes that the file will
follow a specific format
* results will vary heavily based on how the file is set up
*
* before docking points please make sure that the file follows the format
*
* "Number of entries"
* "Customer Number", "Arrival Time", "Service Time"
* "Customer Number", "Arrival Time", "Service Time"
* "Customer Number", "Arrival Time", "Service Time"
*/
xfiles >> dataEntry;
fileData[i].setNumber(dataEntry);
//inserts a number from the file into the "number" variable in the customer class.
xfiles >> dataEntry;
fileData[i].setArrival(dataEntry);
//inserts a number from the file into the "arrival" variable in the customer class.
xfiles >> dataEntry;
fileData[i].setServTime(dataEntry);
//inserts a number from the file into the "servTime" variable in the customer class.
}
xfiles.close();
It's not included with the code but there is a line that takes in account for entries earlier in the program.
In my next block I have to queue and process customers simultaneously through a period of time. I have an idea how what I should do to queue them but I'm not too sure how I should proceed on processing them. For what I know right now I believe I might want to do a conditional statement to check if a certain customer from the array have been queued or not.
The piece of data I'm currently trying to access would be the arrival time that was stored in the class.
So something like,
fileData[i].returnArrival();
but since that class is stored in a queue I'm not sure how I would be able to access it.
Right now how I have everything queued is
for(int x = 0; x < 570; x++)
{
if(cusTime == x)
{
if(scully.isFull() = false)
scully.enqueue(fileData[cusTime]);
else if(mulder.isFull() = false)
mulder.enqueue(fileData[cusTime]);
else if(skinner.isFull() = false)
skinner.enqueue(fileData[cusTime]);
else
cout << "queues are full, disposing..\n";
}
cusTime++;
}
At first I thought it would be something like
scully.returnFront()->temp->returnClass()->fileData.returnArrival();
but I'm unsure about since temp is only a pointer declared within the queue class.
There was another suggestion from a friend of mine who suggested it would probably be something like this instead, but I ended up getting segmentation errors when I ran the code.
scully.returnFront()->returnClass().returnArrival();
I think it should be the following:
scully.returnFront().returnArrival()
Because you enqueue the items from your array. Thus, returnFront() retrieves an item on which your methods should be possible.
After discussing it a bit with the professor and TA the cause of the problem was that the return front function was returning a pointer making it more difficult to access the data within the node. A solution was to have the return front function return the Class associated with the data and have the return statement return a pointer that's pointing to the class function that returns the class stored in the node.
so
Node *returnFront();
was changed to
Customer returnFront();
changes within the function was
return front;
to
return front->returnClass();
these changes made it easier to access the Customer class data from inside the main file. So I was able to instantiate a new place holding variable for the class.
Customer scullyTemp;
And after that store the data from inside the class that was stored in the node through an assignment statement.
scullyTemp = scully.returnFront();
scullyTemp.returnArrival();
It might be a little more complicated than it needs to be, but for now it does what I need it to do.

Iterators in event manager for game becoming invalidated upon unregister

I am writing an EventManager class for a game I am making for school. It utilizes a double queue system for events and holds an unordered_map consisting of events types and vectors of ID's registered to respond to the particular events. The problem I am having is that certain events (like when you click the play button for the main menu)may cause an actor to unregister events. While this is intentional it causes problems with the iterators which is not intentional. In the example where it switches from the main menu to the game it destroys all the actors(buttons and such) that are part of the main menu. These, in turn, unregister themselves with the event manager which deletes their id from the corresponding vector stored in the unordered_map and invalidates the iterator throwing an exception at the beginning of the loop. As such no event can cause an actor to unregister anything. This is undesirable because some trigger objects in the game may be one time triggers at which point they need to unregister themselves from receiving more events. Any help or ideas would be greatly appreciated.
void EventManager::Flush()
{
Event* current;
while (m_eventList[m_current].size() > 0)
{
current = m_eventList[m_current].front();
m_eventList[m_current].pop_front();
unordered_map<string, vector<IDTYPE>>::iterator it = m_registeredEvents.find(current->GetType());
if (it == m_registeredEvents.end())
continue;
vector<IDTYPE>* toProcessAct = &(it->second);
vector<IDTYPE>::iterator actIt = toProcessAct->begin();
while (actIt != toProcessAct->end()) //this becomes invalid
{
Actor* temp = ACTORS->GetActor(*actIt);
if (temp == NULL)
actIt = toProcessAct->erase(actIt);
else
{
actIt++;
temp->Process(current); //Because this may unregister events
}
}
delete current; current = 0;
}
Swap();
}
void EventManager::UnregisterEvent(string Event, IDTYPE actor)
{
unordered_map<string, vector<IDTYPE>>::iterator it = m_registeredEvents.find(Event);
//Found
if (it != m_registeredEvents.end())
{
//Find if actor is already registered
vector<IDTYPE>::iterator actIt = it->second.begin();
while (actIt != it->second.end())
{
if (actor == *actIt)
{
it->second.erase(actIt);
return;
}
actIt++;
}
}
}
This is a good way to shoot yourself in the foot
Event* current; // not the issue here but you should always initialize your variables.
while (m_eventList[m_current].size() > 0) {
current = m_eventList[m_current].front(); // current points the the first element
m_eventList[m_current].pop_front(); // now the first element gets destroyed
unordered_map<string, vector<IDTYPE>>::iterator it = m_registeredEvents.find(current->GetType()); // its pure coincident if this works.
pop_front() destroys the front element making the pointer invalid and you enter undefined behaviour. Make a copy of the record instead, then you also don't have problems with destroying it.
Further all iterators to elements after the a delete are invalid, so if your code saves iterators as a state you will get hurt, just presume all deletes makes all iterators to that or related containers invalid to be safe.
If you are running a multi-threaded program you have the further problem that other threads could change the content, use at least a mutex to protect it.
OK, now for what you actually asked for:
while (actIt != toProcessAct->end()) { // end() should update but actIt doesn't.
Actor* temp = ACTORS->GetActor(*actIt);
if (temp == NULL)
actIt = toProcessAct->erase(actIt);
else {
actIt = temp->Process(actIt, current); // make Process return the new valid It
}
}
delete current; // would fail as there is a continue higher up!!!
current = 0; // if using C++11 use nullptr instead else NULL
Make Process return the new valid Iterator or toProcessAct->end() if no more are valid after actIt.
One solution can be to iterate over a copy of event handlers vector, that is instead of
vector<IDTYPE>* toProcessAct = &(it->second);
write
vector<IDTYPE> toProcessAct = it->second;
(and make corresponding changes for the code to compile).
Also probably it will be faster if you make a copy of the whole m_registeredEvents in the start of Flush(), so you won't have to copy vectors several times.
Another solution would be to make unregistration deferred, that is UnregisterEvent() instead of executing instantly would enqueue the unregistration request into separate queue and execute it later, for example at the end of Flush().

priority_queue becomes extremely slow in debug mode

I am currently writing an A* pathfinding algorithm for a game and came across a very strange performance problem regarding priority_queue's.
I am using a typical 'open nodes list', where I store found, but yet unprocessed nodes. This is implemented as an STL priority_queue (openList) of pointers to PathNodeRecord objects, which store information about a visited node. They are sorted by the estimated cost to get there (estimatedTotalCost).
Now I noticed that whenever the pathfinding method is called, the respective AI thread gets completely stuck and takes several (~5) seconds to process the algorithm and calculate the path. Subsequently I used the VS2013 profiler to see, why and where it was taking so long.
As it turns out, the pushing to and popping from the open list (the priority_queue) takes up a very large amount of time. I am no expert in STL containers, but I never had problems with their efficiency before and this is just weird to me.
The strange thing is that this only occurs while using VS's 'Debug' build configuration. The 'Release' conf. works fine for me and the times are back to normal.
Am I doing something fundamentally wrong here or why is the priority_queue performing so badly for me? The current situation is unacceptable to me, so if I cannot resolve it soon, I will need to fall back to using a simpler container and inserting it to the right place manually.
Any pointers to why this might be occuring would be very helpful!
.
Here is a snippet of what the profiler shows me:
http://i.stack.imgur.com/gEyD3.jpg
.
Code parts:
Here is the relevant part of the pathfinding algorithm, where it loops the open list until there are no open nodes:
// set up arrays and other variables
PathNodeRecord** records = new PathNodeRecord*[graph->getNodeAmount()]; // holds records for all nodes
std::priority_queue<PathNodeRecord*> openList; // holds records of open nodes, sorted by estimated rest cost (most promising node first)
// null all record pointers
memset(records, NULL, sizeof(PathNodeRecord*) * graph->getNodeAmount());
// set up record for start node and put into open list
PathNodeRecord* startNodeRecord = new PathNodeRecord();
startNodeRecord->node = startNode;
startNodeRecord->connection = NULL;
startNodeRecord->closed = false;
startNodeRecord->costToHere = 0.f;
startNodeRecord->estimatedTotalCost = heuristic->estimate(startNode, goalNode);
records[startNode] = startNodeRecord;
openList.push(startNodeRecord);
// ### pathfind algorithm ###
// declare current node variable
PathNodeRecord* currentNode = NULL;
// loop-process open nodes
while (openList.size() > 0) // while there are open nodes to process
{
// retrieve most promising node and immediately remove from open list
currentNode = openList.top();
openList.pop(); // ### THIS IS, WHERE IT GETS STUCK
// if current node is the goal node, end the search here
if (currentNode->node == goalNode)
break;
// look at connections outgoing from this node
for (auto connection : graph->getConnections(currentNode->node))
{
// get end node
PathNodeRecord* toNodeRecord = records[connection->toNode];
if (toNodeRecord == NULL) // UNVISITED -> path record needs to be created and put into open list
{
// set up path node record
toNodeRecord = new PathNodeRecord();
toNodeRecord->node = connection->toNode;
toNodeRecord->connection = connection;
toNodeRecord->closed = false;
toNodeRecord->costToHere = currentNode->costToHere + connection->cost;
toNodeRecord->estimatedTotalCost = toNodeRecord->costToHere + heuristic->estimate(connection->toNode, goalNode);
// store in record array
records[connection->toNode] = toNodeRecord;
// put into open list for future processing
openList.push(toNodeRecord);
}
else if (!toNodeRecord->closed) // OPEN -> evaluate new cost to here and, if better, update open list entry; otherwise skip
{
float newCostToHere = currentNode->costToHere + connection->cost;
if (newCostToHere < toNodeRecord->costToHere)
{
// update record
toNodeRecord->connection = connection;
toNodeRecord->estimatedTotalCost = newCostToHere + (toNodeRecord->estimatedTotalCost - toNodeRecord->costToHere);
toNodeRecord->costToHere = newCostToHere;
}
}
else // CLOSED -> evaluate new cost to here and, if better, put back on open list and reset closed status; otherwise skip
{
float newCostToHere = currentNode->costToHere + connection->cost;
if (newCostToHere < toNodeRecord->costToHere)
{
// update record
toNodeRecord->connection = connection;
toNodeRecord->estimatedTotalCost = newCostToHere + (toNodeRecord->estimatedTotalCost - toNodeRecord->costToHere);
toNodeRecord->costToHere = newCostToHere;
// reset node to open and push into open list
toNodeRecord->closed = false;
openList.push(toNodeRecord); // ### THIS IS, WHERE IT GETS STUCK
}
}
}
// set node to closed
currentNode->closed = true;
}
Here is my PathNodeRecord with the 'less' operator overloading to enable sorting in priority_queue:
namespace AI
{
struct PathNodeRecord
{
Node node;
NodeConnection* connection;
float costToHere;
float estimatedTotalCost;
bool closed;
// overload less operator comparing estimated total cost; used by priority queue
// nodes with a higher estimated total cost are considered "less"
bool operator < (const PathNodeRecord &otherRecord)
{
return this->estimatedTotalCost > otherRecord.estimatedTotalCost;
}
};
}
std::priority_queue<PathNodeRecord*> openList
I think the reason is that you have a priority_queue of pointers to PathNodeRecord.
and there is no ordering defined for the pointers.
try changing it to std::priority_queue<PathNodeRecord> first, if it makes a difference then all you need is passing on your own comparator that knows how to compare pointers to PathNodeRecord, it will just dereference the pointers first and then do the comparison.
EDIT:
taking a wild guess about why did you get an extremely slow execution time, I think the pointers were compared based on their address. and the addresses were allocated starting from one point in memory and going up.
and so that resulted in the extreme case of your heap (the heap as in data structure not the memory part), so your heap was actually a list, (a tree where each node had one children node and so on).
and so you operation took a linear time, again just a guess.
You cannot expect a debug build to be as fast as a release optimized one, but you seems to do a lot of dynamic allocation that may interact badly with the debug runtime.
I suggest you to add _NO_DEBUG_HEAP=1 in the environment setting of the debug property page of your project.

Using glutTimerFunc with glutMouseFunc

I am trying to do a little game, and in my game I have some squares and when the user click on these squares, they got highlighted. To achieve this effect I am using glutMouseFunc with glutTimerFunc.
When the user clicks on the screen I pick the pixel and identify the square I need to highlight. Once the square is identified I call glutTimerFunc. The function registred with glutTimerFunc increase the value of each component of color by 0.01 until they reach one max value defined by me, then this value goes back to a minimum value.
glutTimerFunc execute in 60 milliseconds and I get a almost smooth shine effect.
My problem is, if I click on two squares very fast, the effect starts on the first square, but don't finish, so the square remains highlighted and the second squares do the entire effect. If I click like a crazy man on every square, all of them got highlighted.
How can I make this effect of shining terminate even if I click on other square?
Here is a snippet of code
void Memoria::shineEffect(GLint value) {
if(value == 1) {
for(GLint i = 0; i < 3; i++) {
if(colors[selectedSquare][i] > 0) {
colors[selectedSquare][i] += COLOR_INCREASE;
if(colors[selectedSquare][i] >= MAX) {
colors[selectedSquare][i] = MAX;
value = -1;
}
}
}
glutTimerFunc(FPS, timeWrapper, value);
}
else {
if(value == -1) {
for(GLint i = 0; i < 3; i++) {
if(colors[selectedSquare][i] > 0) {
colors[selectedSquare][i] -= COLOR_INCREASE;
if(colors[selectedSquare][i] <= MIN) {
value = 0;
colors[selectedSquare][i] = MIN;
}
}
}
glutTimerFunc(FPS, timeWrapper, value);
}
}
}
timeWrapper calls shineEffect if the value passed in the parameter is 1 or -1.
You want the shineEffect function to go through one highlight loop at least, and then stop if the highlighted item has changed. It's more a UI code design issue rather than an OpenGL or GLUT one.
The mechanic you need to implement is pretty straightforward:
install once for all an updateHighlights function with glutTimerFunc: this function will be responsible of updating the highlights of all the clicked elements,
create a queue of elements: each time an element has been clicked, add it to the queue,
The task performed by the updateHighLights function should be as follow:
if the queue contains one element, keep cycling its highlight as you already do in your program
if the queue contain more than one element, for each element in the queue,
step the highlight cycle
if the cycle is over, and the element is not the last one, remove the element from the queue
Here's another perhaps more flexible take on your problem.
The Glut event loop machinery is very simple design: there's only one hook to put your "idle work" code, so it's probably more flexible to install a function there which calls a list of others functions. That list could be then modified with a set primitive, to install or remove specific tasks to perform during idle time. This could be much more flexible than the "one function" approach of GLUT.
For instance, you could isolate your current highlight code in one function with a struct containing the element to highlight, and have the function remove itself from the list when its element is done through a highlight cycle and isn't active anymore.
Since you are using C++, it should be easy to bundle all these functionalities in classes:
one class for the list of idle tasks
one base class for idle tasks
one derived idle task class for the purpose of highlighting a square (with fields for the square and for the active status)
one class to keep track of the active square, so that it may be easily deactivated and replaced by the new active one. This one would be accessed by the glutMouseFunc function.

For Looping Link List using Templates

Having used the various search engines (and the wonderful stackoverflow database), I have found some similar situations, but they are either far more complex, or not nearly as complex as what I'm trying to accomplish.
C++ List Looping
Link Error Using Templates
C++:Linked List Ordering
Pointer Address Does Not Change In A Link List
I'm trying to work with Link List and Node templates to store and print non-standard class objects (in this case, a collection of categorized contacts). Particularly, I want to print multiple objects that have the same category, out of a bunch of objects with different categories. When printing by category, I compare an sub-object tmpCategory (= "business") with the category part of a categorized contact.
But how to extract this data for comparison in int main()?
Here's what I'm thinking. I create a GetItem member function in LinkList.tem This would initialize the pointer cursor and then run a For loop until the function input matches the iteration number. At which point, GetItem returns object Type using (cursor -> data).
template <class Type>
Type LinkList<Type>::GetItem(int itemNumber) const
{
Node<Type>* cursor = NULL;
for(cursor = first;
cursor != NULL;
cursor = (cursor -> next))
{
for(int i = 0; i < used; i++)
{
if(itemNumber == i)
{
return(cursor -> data);
}
}
}
}
Here's where int main() comes in. I set my comparison object tmpCategory to a certain value (in this case, "Business"). Then, I run a For loop that iterates for cycles equal to the number of Nodes I have (as determined by a function GetUsed()). Inside that loop, I call GetItem, using the current iteration number. Theoretically, this would let the int main loop return the corresponding Node from LinkList.tem. From there, I call the category from the object inside that Node's data (which currently works), which would be compared with tmpCategory. If there's a match, the loop will print out the entire Node's data object.
tmpCategory = "Business";
for(int i = 0; i < myCategorizedContact.GetUsed(); i++)
{
if(myCategorizedContact.GetItem(i).getCategory() == tmpCategory)
cout << myCategorizedContact.GetItem(i);
}
The problem is that the currently setup (while it does run), it returns nothing at all. Upon further testing ( cout << myCategorizedContact.GetItem(i).getCategory() ), I found that it's just printing out the category of the first Node over and over again. I want the overall scheme to evaluate for every Node and print out matching data, not just spit out the same Node.
Any ideas/suggestions are greatly appreciated.
Please look at this very carefully:
template <class Type>
Type LinkList<Type>::GetItem(int itemNumber) const
{
Node<Type>* cursor = NULL;
// loop over all items in the linked list
for(cursor = first;
cursor != NULL;
cursor = (cursor -> next))
{
// for each item in the linked list, run a for-loop
// counter from 0 to (used-1).
for(int i = 0; i < used; i++)
{
// if the passed in itemNumber matches 'i' anytime
// before we reach the end of the for-loop, return
// whatever the current cursor is.
if(itemNumber == i)
{
return(cursor -> data);
}
}
}
}
You're not walking the cursor down the list itemNumber times. The very first item cursor references will kick off the inner-for-loop. The moment that loop index reaches itemNumber you return. You never advance your cursor if the linked list has at least itemNumber items in the list.. In fact, the two of them (cursor and itemNumber) are entirely unrelated in your implementation of this function. And to really add irony, since used and cursor are entirely unrelated, if used is ever less than itemNumber, it will ALWAYS be so, since used doesn't change when cursor advances through the outer loop. Thus cursor eventually becomes NULL and the results of this function are undefined (no return value). In summary, as written you will always either return the first item (if itemNumber < used), or undefined behavior since you have no return value.
I believe you need something like the following instead:
template< class Type >
Type LinkList<Type>::GetItem(int itemNumber) const
{
const Node<Type>* cursor = first;
while (cursor && itemNumber-- > 0)
cursor = cursor->next;
if (cursor)
return cursor->data;
// note: this is here because you're definition is to return
// an item COPY. This case would be better off returning a
// `const Type*` instead, which would at least allow you to
// communicate to the caller that there was no item at the
// proposed index (because the list is undersized) and return
// NULL, which the caller could check.
return Type();
}