Skip to content

Commit bace89b

Browse files
committed
Added a workaround for another edge case in corid assignment involving multiple sequential zero-runtime functions; in such cases, a function can claim a maximum of 1 correlation ID. + unit test
1 parent 5498df6 commit bace89b

2 files changed

Lines changed: 144 additions & 3 deletions

File tree

src/ad/ADParser.cpp

Lines changed: 29 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -684,6 +684,7 @@ std::vector<Event_t> ADParser::getEvents() const{
684684

685685
unsigned long last_func_entry = 0; //record the entry of the currently open function
686686
size_t off_t[3] = {0,0,0};
687+
bool func_has_corid = false;
687688

688689
while(data_t[0] != nullptr || data_t[1] != nullptr || data_t[2] != nullptr){
689690
//Determine what kind of func event it is (if !nullptr)
@@ -718,12 +719,37 @@ std::vector<Event_t> ADParser::getEvents() const{
718719

719720
//Catch edge case where ENTRY, CORRID, EXIT all have the same timestamp. We will assume the corrid is associated with this function event
720721
if(earliest == FUNC && func_event_type == EXIT && data_t[FUNC]->ts() == last_func_entry &&
721-
counter_is_correlation_id && data_t[COUNTER]->ts() == last_func_entry)
722-
earliest = COUNTER;
722+
counter_is_correlation_id && data_t[COUNTER]->ts() == last_func_entry){
723+
//There is an ambiguity here in cases where ENTRY,COUNTER,EXIT and the ENTRY,COUNTER of the *next* function all have the same timestamp
724+
//this can cause the current function to claim the correlation ID which should rightfully belong to the next function
725+
//To prevent this we impose a rule (which may not always be true but is perhaps the best we can manage!) that in such cases, a zero-length function
726+
//can claim only one correlation ID
727+
728+
//First determine if an uncoming entry event has the same timestamp
729+
unsigned long cur_ts = data_t[FUNC]->ts();
730+
bool entry_same_timestamp = false;
731+
Event_t* fdata = data_t[FUNC];
732+
for(size_t off = off_t[FUNC]+1; off < ndata_t[FUNC]; off++){
733+
++fdata;
734+
if(fdata->ts() != cur_ts) break;
735+
else if(func_event_type_map_v[fdata->eid()] == ENTRY){
736+
entry_same_timestamp = true; break;
737+
}
738+
}
739+
740+
//Then we can impose the rule
741+
if(!entry_same_timestamp || (entry_same_timestamp && !func_has_corid))
742+
earliest = COUNTER; //function will claim the corid
743+
}
723744

724745
//Record function entry time for logic above
725-
if(earliest == FUNC && func_event_type == ENTRY)
746+
if(earliest == FUNC && func_event_type == ENTRY){
726747
last_func_entry = data_t[FUNC]->ts();
748+
func_has_corid = false;
749+
}
750+
751+
if(earliest == COUNTER && counter_is_correlation_id)
752+
func_has_corid = true; //note that a function has at least 1 corid attached
727753

728754
out.push_back(*data_t[earliest]);
729755
++data_t[earliest];

test/unit_tests/ad/ADParser.cpp

Lines changed: 115 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -85,6 +85,7 @@ struct SSTrw{
8585
};
8686

8787

88+
#if 1
8889
TEST(ADParserTestConstructor, opensTimesoutCorrectlySST){
8990
std::string filename = "commfile";
9091
bool got_err= false;
@@ -620,6 +621,7 @@ TEST(ADParserTestFuncDataIO, funcDataLocalToGlobalIndexReplacementWorks){
620621
psthr.join();
621622
std::cout << "Main thread finished" << std::endl;
622623
}
624+
#endif
623625

624626
//Events same up to id string (set by parser) or idx (set by static count in unit test header)
625627
bool same_up_to_id_string(const Event_t &l, const Event_t &r){
@@ -954,3 +956,116 @@ TEST(ADParserTest, CorrelationIDeventOrderCorrectly){
954956
}
955957
}
956958
}
959+
960+
961+
962+
963+
964+
TEST(ADParserTest, CorrelationIDeventEdgeCases){
965+
std::unordered_map<int, std::string> event_types = { {0,"ENTRY"}, {1,"EXIT"}, {2,"SEND"}, {3,"RECV"} };
966+
std::unordered_map<int, std::string> func_names = { {12,"MYFUNC"}, {13,"OTHERFUNC"} };
967+
std::unordered_map<int, std::string> counter_names = { {99,"Correlation ID"} };
968+
969+
int ENTRY = 0;
970+
int EXIT = 1;
971+
int SEND = 2;
972+
int RECV = 3;
973+
int CORRID = 99;
974+
int MYFUNC = 12;
975+
int OTHERFUNC = 13;
976+
977+
int pid=0, tid=0, rid=0;
978+
979+
980+
{
981+
std::cout << "Show that a function will claim a correlation ID if ENTRY, EXIT and COUNTER all have the same timestamp" << std::endl;
982+
// Usually an EXIT event will be prioritized over a COUNTER if they have the same timestamp and the counter is a corid
983+
// because corids are associated with ENTRY events, but the basic logic doesn't work for the case when all 3 have the same timestamp
984+
// We deal with this edge case explicitly
985+
986+
std::vector<Event_t> events = {
987+
createFuncEvent_t(pid, rid, tid, ENTRY, MYFUNC, 100),
988+
createFuncEvent_t(pid, rid, tid, EXIT, MYFUNC, 100),
989+
createCounterEvent_t(pid, rid, tid, CORRID, 1256, 100), //correlation ID associated with function
990+
createFuncEvent_t(pid, rid, tid, ENTRY, OTHERFUNC, 101),
991+
createFuncEvent_t(pid, rid, tid, EXIT, OTHERFUNC, 102)
992+
};
993+
994+
ADParser parser("",0,rid,"BPFile");
995+
parser.setFuncDataCapacity(100);
996+
parser.setCommDataCapacity(100);
997+
parser.setCounterDataCapacity(100);
998+
parser.setFuncMap(func_names);
999+
parser.setEventTypeMap(event_types);
1000+
parser.setCounterMap(counter_names);
1001+
1002+
for(int i=0;i<events.size();i++){
1003+
if(events[i].type() == EventDataType::FUNC)
1004+
parser.addFuncData(events[i].get_ptr());
1005+
else if(events[i].type() == EventDataType::COMM)
1006+
parser.addCommData(events[i].get_ptr());
1007+
else if(events[i].type() == EventDataType::COUNT)
1008+
parser.addCounterData(events[i].get_ptr());
1009+
else
1010+
FAIL() << "Invalid EventDataType";
1011+
}
1012+
1013+
std::vector<Event_t> events_out = parser.getEvents();
1014+
1015+
EXPECT_EQ(events_out.size(), events.size());
1016+
1017+
std::vector<int> order = {0,2,1,3,4};
1018+
for(int i=0;i<5;i++){
1019+
std::cout << "Expect " << events[order[i]].get_json().dump() << " got " << events_out[i].get_json().dump() << std::endl;
1020+
EXPECT_TRUE( same_up_to_id_string(events_out[i], events[order[i]]) );
1021+
}
1022+
}
1023+
1024+
{
1025+
std::cout << "Show that if an ENTRY, CORID, EXIT and the next ENTRY, CORID all coindice, the first function will claim only one of the CORIDs" << std::endl;
1026+
std::vector<Event_t> events = {
1027+
createFuncEvent_t(pid, rid, tid, ENTRY, MYFUNC, 100), //0
1028+
createFuncEvent_t(pid, rid, tid, EXIT, MYFUNC, 100), //1
1029+
createFuncEvent_t(pid, rid, tid, ENTRY, OTHERFUNC, 100), //2
1030+
createFuncEvent_t(pid, rid, tid, EXIT, OTHERFUNC, 100), //3
1031+
createFuncEvent_t(pid, rid, tid, ENTRY, MYFUNC, 100), //4
1032+
createFuncEvent_t(pid, rid, tid, EXIT, MYFUNC, 100), //5
1033+
createCounterEvent_t(pid, rid, tid, CORRID, 1256, 100), //6
1034+
createCounterEvent_t(pid, rid, tid, CORRID, 1257, 100), //7
1035+
createCounterEvent_t(pid, rid, tid, CORRID, 1258, 100) //8
1036+
};
1037+
1038+
ADParser parser("",0,rid,"BPFile");
1039+
parser.setFuncDataCapacity(100);
1040+
parser.setCommDataCapacity(100);
1041+
parser.setCounterDataCapacity(100);
1042+
parser.setFuncMap(func_names);
1043+
parser.setEventTypeMap(event_types);
1044+
parser.setCounterMap(counter_names);
1045+
1046+
for(int i=0;i<events.size();i++){
1047+
if(events[i].type() == EventDataType::FUNC)
1048+
parser.addFuncData(events[i].get_ptr());
1049+
else if(events[i].type() == EventDataType::COMM)
1050+
parser.addCommData(events[i].get_ptr());
1051+
else if(events[i].type() == EventDataType::COUNT)
1052+
parser.addCounterData(events[i].get_ptr());
1053+
else
1054+
FAIL() << "Invalid EventDataType";
1055+
}
1056+
1057+
std::vector<Event_t> events_out = parser.getEvents();
1058+
1059+
EXPECT_EQ(events_out.size(), events.size());
1060+
1061+
std::vector<int> order = {0,6,1,2,7,3,4,8,5};
1062+
for(int i=0;i<order.size();i++){
1063+
std::cout << "Expect " << events[order[i]].get_json().dump() << " got " << events_out[i].get_json().dump() << std::endl;
1064+
EXPECT_TRUE( same_up_to_id_string(events_out[i], events[order[i]]) );
1065+
}
1066+
}
1067+
1068+
1069+
1070+
1071+
}

0 commit comments

Comments
 (0)