Use historical average of test times to schedule tests.
This commit is contained in:
parent
55f012989c
commit
b4d27dc041
@ -76,6 +76,7 @@ void cmCTestMultiProcessHandler::RunTests()
|
|||||||
{
|
{
|
||||||
}
|
}
|
||||||
this->MarkFinished();
|
this->MarkFinished();
|
||||||
|
this->UpdateCostData();
|
||||||
}
|
}
|
||||||
|
|
||||||
//---------------------------------------------------------
|
//---------------------------------------------------------
|
||||||
@ -272,8 +273,7 @@ bool cmCTestMultiProcessHandler::CheckOutput()
|
|||||||
this->TestRunningMap[test] = false;
|
this->TestRunningMap[test] = false;
|
||||||
this->RunningTests.erase(p);
|
this->RunningTests.erase(p);
|
||||||
this->WriteCheckpoint(test);
|
this->WriteCheckpoint(test);
|
||||||
this->WriteCostData(test, static_cast<float>(
|
|
||||||
p->GetTestResults().ExecutionTime));
|
|
||||||
this->RunningCount -= GetProcessorsUsed(test);
|
this->RunningCount -= GetProcessorsUsed(test);
|
||||||
delete p;
|
delete p;
|
||||||
}
|
}
|
||||||
@ -281,24 +281,88 @@ bool cmCTestMultiProcessHandler::CheckOutput()
|
|||||||
}
|
}
|
||||||
|
|
||||||
//---------------------------------------------------------
|
//---------------------------------------------------------
|
||||||
void cmCTestMultiProcessHandler::ReadCostData()
|
void cmCTestMultiProcessHandler::UpdateCostData()
|
||||||
{
|
{
|
||||||
std::string fname = this->CTest->GetBinaryDir()
|
std::string fname = this->CTest->GetBinaryDir()
|
||||||
+ "/Testing/Temporary/CTestCostData.txt";
|
+ "/Testing/Temporary/CTestCostData.txt";
|
||||||
|
std::string tmpout = fname + ".tmp";
|
||||||
|
std::fstream fout;
|
||||||
|
fout.open(tmpout.c_str(), std::ios::out);
|
||||||
|
|
||||||
if(cmSystemTools::FileExists(fname.c_str(), true)
|
PropertiesMap temp = this->Properties;
|
||||||
&& this->ParallelLevel > 1)
|
|
||||||
{
|
if(cmSystemTools::FileExists(fname.c_str()))
|
||||||
|
{
|
||||||
std::ifstream fin;
|
std::ifstream fin;
|
||||||
fin.open(fname.c_str());
|
fin.open(fname.c_str());
|
||||||
|
|
||||||
std::string line;
|
std::string line;
|
||||||
while(std::getline(fin, line))
|
while(std::getline(fin, line))
|
||||||
{
|
{
|
||||||
std::vector<cmsys::String> parts =
|
std::vector<cmsys::String> parts =
|
||||||
cmSystemTools::SplitString(line.c_str(), ' ');
|
cmSystemTools::SplitString(line.c_str(), ' ');
|
||||||
|
//Format: <name> <previous_runs> <avg_cost>
|
||||||
|
if(parts.size() < 3) break;
|
||||||
|
|
||||||
int index = atoi(parts[0].c_str());
|
std::string name = parts[0];
|
||||||
float cost = static_cast<float>(atof(parts[1].c_str()));
|
int prev = atoi(parts[1].c_str());
|
||||||
|
float cost = static_cast<float>(atof(parts[2].c_str()));
|
||||||
|
|
||||||
|
int index = this->SearchByName(name);
|
||||||
|
if(index == -1)
|
||||||
|
{
|
||||||
|
// This test is not in memory. We just rewrite the entry
|
||||||
|
fout << name << " " << prev << " " << cost << "\n";
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// Update with our new average cost
|
||||||
|
fout << name << " " << this->Properties[index]->PreviousRuns << " "
|
||||||
|
<< this->Properties[index]->Cost << "\n";
|
||||||
|
temp.erase(index);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
fin.close();
|
||||||
|
cmSystemTools::RemoveFile(fname.c_str());
|
||||||
|
}
|
||||||
|
|
||||||
|
// Add all tests not previously listed in the file
|
||||||
|
for(PropertiesMap::iterator i = temp.begin(); i != temp.end(); ++i)
|
||||||
|
{
|
||||||
|
fout << i->second->Name << " " << i->second->PreviousRuns << " "
|
||||||
|
<< i->second->Cost << "\n";
|
||||||
|
}
|
||||||
|
fout.close();
|
||||||
|
cmSystemTools::RenameFile(tmpout.c_str(), fname.c_str());
|
||||||
|
}
|
||||||
|
|
||||||
|
//---------------------------------------------------------
|
||||||
|
void cmCTestMultiProcessHandler::ReadCostData()
|
||||||
|
{
|
||||||
|
//TODO variable location of the cost data file
|
||||||
|
std::string fname = this->CTest->GetBinaryDir()
|
||||||
|
+ "/Testing/Temporary/CTestCostData.txt";
|
||||||
|
if(cmSystemTools::FileExists(fname.c_str(), true))
|
||||||
|
{
|
||||||
|
std::ifstream fin;
|
||||||
|
fin.open(fname.c_str());
|
||||||
|
std::string line;
|
||||||
|
while(std::getline(fin, line))
|
||||||
|
{
|
||||||
|
std::vector<cmsys::String> parts =
|
||||||
|
cmSystemTools::SplitString(line.c_str(), ' ');
|
||||||
|
|
||||||
|
// Probably an older version of the file, will be fixed next run
|
||||||
|
if(parts.size() < 3) break;
|
||||||
|
|
||||||
|
std::string name = parts[0];
|
||||||
|
int prev = atoi(parts[1].c_str());
|
||||||
|
float cost = static_cast<float>(atof(parts[2].c_str()));
|
||||||
|
|
||||||
|
int index = this->SearchByName(name);
|
||||||
|
if(index == -1) continue;
|
||||||
|
|
||||||
|
this->Properties[index]->PreviousRuns = prev;
|
||||||
if(this->Properties[index] && this->Properties[index]->Cost == 0)
|
if(this->Properties[index] && this->Properties[index]->Cost == 0)
|
||||||
{
|
{
|
||||||
this->Properties[index]->Cost = cost;
|
this->Properties[index]->Cost = cost;
|
||||||
@ -306,7 +370,22 @@ void cmCTestMultiProcessHandler::ReadCostData()
|
|||||||
}
|
}
|
||||||
fin.close();
|
fin.close();
|
||||||
}
|
}
|
||||||
cmSystemTools::RemoveFile(fname.c_str());
|
}
|
||||||
|
|
||||||
|
//---------------------------------------------------------
|
||||||
|
int cmCTestMultiProcessHandler::SearchByName(std::string name)
|
||||||
|
{
|
||||||
|
int index = -1;
|
||||||
|
|
||||||
|
for(PropertiesMap::iterator i = this->Properties.begin();
|
||||||
|
i != this->Properties.end(); ++i)
|
||||||
|
{
|
||||||
|
if(i->second->Name == name)
|
||||||
|
{
|
||||||
|
index = i->first;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return index;
|
||||||
}
|
}
|
||||||
|
|
||||||
//---------------------------------------------------------
|
//---------------------------------------------------------
|
||||||
@ -319,24 +398,13 @@ void cmCTestMultiProcessHandler::CreateTestCostList()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//---------------------------------------------------------
|
|
||||||
void cmCTestMultiProcessHandler::WriteCostData(int index, float cost)
|
|
||||||
{
|
|
||||||
std::string fname = this->CTest->GetBinaryDir()
|
|
||||||
+ "/Testing/Temporary/CTestCostData.txt";
|
|
||||||
std::fstream fout;
|
|
||||||
fout.open(fname.c_str(), std::ios::out | std::ios::app);
|
|
||||||
fout << index << " " << cost << "\n";
|
|
||||||
fout.close();
|
|
||||||
}
|
|
||||||
|
|
||||||
//---------------------------------------------------------
|
//---------------------------------------------------------
|
||||||
void cmCTestMultiProcessHandler::WriteCheckpoint(int index)
|
void cmCTestMultiProcessHandler::WriteCheckpoint(int index)
|
||||||
{
|
{
|
||||||
std::string fname = this->CTest->GetBinaryDir()
|
std::string fname = this->CTest->GetBinaryDir()
|
||||||
+ "/Testing/Temporary/CTestCheckpoint.txt";
|
+ "/Testing/Temporary/CTestCheckpoint.txt";
|
||||||
std::fstream fout;
|
std::fstream fout;
|
||||||
fout.open(fname.c_str(), std::ios::app);
|
fout.open(fname.c_str(), std::ios::app | std::ios::out);
|
||||||
fout << index << "\n";
|
fout << index << "\n";
|
||||||
fout.close();
|
fout.close();
|
||||||
}
|
}
|
||||||
|
@ -64,8 +64,12 @@ protected:
|
|||||||
bool StartTest(int test);
|
bool StartTest(int test);
|
||||||
// Mark the checkpoint for the given test
|
// Mark the checkpoint for the given test
|
||||||
void WriteCheckpoint(int index);
|
void WriteCheckpoint(int index);
|
||||||
void WriteCostData(int index, float cost);
|
|
||||||
|
void UpdateCostData();
|
||||||
void ReadCostData();
|
void ReadCostData();
|
||||||
|
// Return index of a test based on its name
|
||||||
|
int SearchByName(std::string name);
|
||||||
|
|
||||||
void CreateTestCostList();
|
void CreateTestCostList();
|
||||||
// Removes the checkpoint file
|
// Removes the checkpoint file
|
||||||
void MarkFinished();
|
void MarkFinished();
|
||||||
|
@ -334,6 +334,7 @@ bool cmCTestRunTest::EndTest(size_t completed, size_t total, bool started)
|
|||||||
this->TestResult.CompletionStatus = "Completed";
|
this->TestResult.CompletionStatus = "Completed";
|
||||||
this->TestResult.ExecutionTime = this->TestProcess->GetTotalTime();
|
this->TestResult.ExecutionTime = this->TestProcess->GetTotalTime();
|
||||||
this->MemCheckPostProcess();
|
this->MemCheckPostProcess();
|
||||||
|
this->ComputeWeightedCost();
|
||||||
}
|
}
|
||||||
// Always push the current TestResult onto the
|
// Always push the current TestResult onto the
|
||||||
// TestHandler vector
|
// TestHandler vector
|
||||||
@ -342,7 +343,21 @@ bool cmCTestRunTest::EndTest(size_t completed, size_t total, bool started)
|
|||||||
return passed;
|
return passed;
|
||||||
}
|
}
|
||||||
|
|
||||||
//--------------------------------------------------------------
|
//----------------------------------------------------------------------
|
||||||
|
void cmCTestRunTest::ComputeWeightedCost()
|
||||||
|
{
|
||||||
|
int prev = this->TestProperties->PreviousRuns;
|
||||||
|
float avgcost = this->TestProperties->Cost;
|
||||||
|
double current = this->TestResult.ExecutionTime;
|
||||||
|
|
||||||
|
if(this->TestResult.Status == cmCTestTestHandler::COMPLETED)
|
||||||
|
{
|
||||||
|
this->TestProperties->Cost = ((prev * avgcost) + current) / (prev + 1);
|
||||||
|
this->TestProperties->PreviousRuns++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//----------------------------------------------------------------------
|
||||||
void cmCTestRunTest::MemCheckPostProcess()
|
void cmCTestRunTest::MemCheckPostProcess()
|
||||||
{
|
{
|
||||||
if(!this->TestHandler->MemCheck)
|
if(!this->TestHandler->MemCheck)
|
||||||
@ -430,6 +445,7 @@ bool cmCTestRunTest::StartTest(size_t total)
|
|||||||
&this->TestProperties->Environment);
|
&this->TestProperties->Environment);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//----------------------------------------------------------------------
|
||||||
void cmCTestRunTest::ComputeArguments()
|
void cmCTestRunTest::ComputeArguments()
|
||||||
{
|
{
|
||||||
std::vector<std::string>::const_iterator j =
|
std::vector<std::string>::const_iterator j =
|
||||||
|
@ -54,6 +54,8 @@ public:
|
|||||||
bool EndTest(size_t completed, size_t total, bool started);
|
bool EndTest(size_t completed, size_t total, bool started);
|
||||||
//Called by ctest -N to log the command string
|
//Called by ctest -N to log the command string
|
||||||
void ComputeArguments();
|
void ComputeArguments();
|
||||||
|
|
||||||
|
void ComputeWeightedCost();
|
||||||
private:
|
private:
|
||||||
void DartProcessing();
|
void DartProcessing();
|
||||||
void ExeNotFound(std::string exe);
|
void ExeNotFound(std::string exe);
|
||||||
|
@ -2274,6 +2274,7 @@ bool cmCTestTestHandler::AddTest(const std::vector<std::string>& args)
|
|||||||
test.Timeout = 0;
|
test.Timeout = 0;
|
||||||
test.Cost = 0;
|
test.Cost = 0;
|
||||||
test.Processors = 1;
|
test.Processors = 1;
|
||||||
|
test.PreviousRuns = 0;
|
||||||
if (this->UseIncludeRegExpFlag &&
|
if (this->UseIncludeRegExpFlag &&
|
||||||
!this->IncludeTestsRegularExpression.find(testname.c_str()))
|
!this->IncludeTestsRegularExpression.find(testname.c_str()))
|
||||||
{
|
{
|
||||||
|
@ -96,6 +96,7 @@ public:
|
|||||||
bool IsInBasedOnREOptions;
|
bool IsInBasedOnREOptions;
|
||||||
bool WillFail;
|
bool WillFail;
|
||||||
float Cost;
|
float Cost;
|
||||||
|
int PreviousRuns;
|
||||||
bool RunSerial;
|
bool RunSerial;
|
||||||
double Timeout;
|
double Timeout;
|
||||||
int Index;
|
int Index;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user