Skip to content

Commit 3218c0b

Browse files
authored
Merge pull request #48740 from Dr15Jones/changeNoProcessBehavior
Optimize 'no process' data product lookup
2 parents 35bba00 + 144b804 commit 3218c0b

16 files changed

+622
-277
lines changed

DataFormats/Provenance/interface/ProductResolverIndexHelper.h

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,7 @@ ProductRegistry is frozen.
6060
#include <memory>
6161
#include <set>
6262
#include <string>
63+
#include <string_view>
6364
#include <vector>
6465
#include <tuple>
6566
#include <unordered_map>
@@ -195,10 +196,15 @@ namespace edm {
195196
// Before the object is frozen the accessors above will
196197
// fail to find a match. Once frozen, no more new entries
197198
// can be added with insert.
198-
void setFrozen();
199+
void setFrozen(std::string_view processName);
199200

201+
/**The list of process names for data products associated to the ProductResolvers.
202+
* If no products are associated with a process for this transition, the process name will not be in this list.
203+
*/
200204
std::vector<std::string> const& lookupProcessNames() const;
201205

206+
bool producesInCurrentProcess() const { return producesInCurrentProcess_; }
207+
202208
class Range {
203209
public:
204210
Range(unsigned int begin, unsigned int end) : begin_(begin), end_(end) {}
@@ -345,6 +351,8 @@ namespace edm {
345351
edm::propagate_const<std::unique_ptr<std::set<Item>>> items_;
346352

347353
edm::propagate_const<std::unique_ptr<std::set<std::string>>> processItems_;
354+
355+
bool producesInCurrentProcess_{false};
348356
};
349357
} // namespace edm
350358
#endif

DataFormats/Provenance/src/ProductRegistry.cc

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -435,8 +435,9 @@ namespace edm {
435435
throwMissingDictionariesException(missingDictionaries, context, producedTypes, branchNamesForMissing);
436436
}
437437

438+
std::string_view processNameSV(processName ? std::string_view(*processName) : std::string_view());
438439
for (auto& iterProductLookup : new_productLookups) {
439-
iterProductLookup->setFrozen();
440+
iterProductLookup->setFrozen(processNameSV);
440441
}
441442
for (size_t i = 0; i < new_productLookups.size(); ++i) {
442443
transient_.productLookups_[i] = std::move(new_productLookups[i]);

DataFormats/Provenance/src/ProductResolverIndexHelper.cc

Lines changed: 19 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -114,7 +114,21 @@ namespace edm {
114114
if (iToIndexAndNames == std::numeric_limits<unsigned int>::max()) {
115115
return ProductResolverIndexInvalid;
116116
}
117-
return indexAndNames_[iToIndexAndNames].index();
117+
118+
auto checkForSingleProcess = [this](unsigned int index) {
119+
//0 is for blank process name. If not zero, we have a match
120+
if (indexAndNames_[index].startInProcessNames() != 0U) {
121+
return index;
122+
}
123+
//Now check to see if only one process has this type/module/instance name
124+
auto nextIndex = index + 1;
125+
while (indexAndNames_.size() > nextIndex && indexAndNames_[nextIndex].startInProcessNames() != 0U) {
126+
++nextIndex;
127+
}
128+
return (nextIndex == index + 2) ? index + 1 : index;
129+
};
130+
131+
return indexAndNames_[checkForSingleProcess(iToIndexAndNames)].index();
118132
}
119133

120134
ProductResolverIndexHelper::Matches::Matches(ProductResolverIndexHelper const* productResolverIndexHelper,
@@ -303,7 +317,7 @@ namespace edm {
303317
return insert(typeID, moduleLabel, instance, process, containedTypeID, baseTypesOfContainedType);
304318
}
305319

306-
void ProductResolverIndexHelper::setFrozen() {
320+
void ProductResolverIndexHelper::setFrozen(std::string_view processName) {
307321
if (!items_)
308322
return;
309323

@@ -360,6 +374,9 @@ namespace edm {
360374
}
361375
processNames_.push_back('\0');
362376
lookupProcessNames_.push_back(processItem);
377+
if (processItem == processName) {
378+
producesInCurrentProcess_ = true;
379+
}
363380
}
364381

365382
// Reserve memory in the vectors

DataFormats/Provenance/test/BuildFile.xml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,8 +8,8 @@
88
<use name="catch2"/>
99
</bin>
1010

11-
<bin name="testProductResolverIndexHelper" file="testRunner.cpp productResolverIndexHelper_t.cppunit.cc">
11+
<bin name="testProductResolverIndexHelper" file="productResolverIndexHelper_t.cpp">
1212
<use name="DataFormats/TestObjects"/>
13-
<use name="cppunit"/>
13+
<use name="catch2"/>
1414
<use name="DataFormats/Provenance"/>
1515
</bin>
Lines changed: 237 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,237 @@
1+
#define CATCH_CONFIG_MAIN
2+
#include <catch.hpp>
3+
4+
#include "DataFormats/Provenance/interface/EventID.h"
5+
#include "DataFormats/Provenance/interface/ProductID.h"
6+
#include "DataFormats/Provenance/interface/ProductResolverIndexHelper.h"
7+
#include "DataFormats/TestObjects/interface/ToyProducts.h"
8+
9+
#include "FWCore/Utilities/interface/Exception.h"
10+
#include "FWCore/Utilities/interface/ProductKindOfType.h"
11+
#include "FWCore/Utilities/interface/TypeID.h"
12+
13+
#include <iostream>
14+
#include <iomanip>
15+
16+
using namespace edm;
17+
18+
TEST_CASE("ProductResolverIndexHelper", "[ProductResolverIndexHelper]") {
19+
TypeID typeID_ProductID(typeid(ProductID));
20+
TypeID typeID_EventID(typeid(EventID));
21+
22+
SECTION("CreateEmpty") {
23+
edm::ProductResolverIndexHelper helper;
24+
helper.setFrozen("processA");
25+
26+
REQUIRE(helper.index(PRODUCT_TYPE, typeID_ProductID, "labelA", "instanceA", "processA") ==
27+
ProductResolverIndexInvalid);
28+
REQUIRE(helper.index(ELEMENT_TYPE, typeID_ProductID, "labelA", "instanceA", "processA") ==
29+
ProductResolverIndexInvalid);
30+
REQUIRE(helper.index(PRODUCT_TYPE, typeID_ProductID, "labelA", "instanceA", "") == ProductResolverIndexInvalid);
31+
REQUIRE(helper.index(PRODUCT_TYPE, typeID_ProductID, "labelA", "instanceA") == ProductResolverIndexInvalid);
32+
33+
edm::ProductResolverIndexHelper::Matches matches =
34+
helper.relatedIndexes(PRODUCT_TYPE, typeID_ProductID, "label_A", "instance_A");
35+
REQUIRE(matches.numberOfMatches() == 0);
36+
matches = helper.relatedIndexes(PRODUCT_TYPE, typeID_ProductID);
37+
REQUIRE(matches.numberOfMatches() == 0);
38+
39+
TypeID typeID(typeid(ProductID));
40+
REQUIRE_THROWS_AS(helper.insert(typeID, "labelA", "instanceA", "processA"), cms::Exception);
41+
}
42+
43+
SECTION("OneEntry") {
44+
edm::ProductResolverIndexHelper helper;
45+
46+
TypeID typeIDProductID(typeid(ProductID));
47+
helper.insert(typeIDProductID, "labelA", "instanceA", "processA");
48+
49+
REQUIRE(helper.index(PRODUCT_TYPE, typeID_ProductID, "labelA", "instanceA", "processA") ==
50+
ProductResolverIndexInvalid);
51+
REQUIRE(helper.index(ELEMENT_TYPE, typeID_ProductID, "labelA", "instanceA", "processA") ==
52+
ProductResolverIndexInvalid);
53+
REQUIRE(helper.index(PRODUCT_TYPE, typeID_ProductID, "labelA", "instanceA", "") == ProductResolverIndexInvalid);
54+
REQUIRE(helper.index(PRODUCT_TYPE, typeID_ProductID, "labelA", "instanceA") == ProductResolverIndexInvalid);
55+
56+
edm::ProductResolverIndexHelper::Matches matches =
57+
helper.relatedIndexes(PRODUCT_TYPE, typeID_ProductID, "label_A", "instance_A");
58+
REQUIRE(matches.numberOfMatches() == 0);
59+
matches = helper.relatedIndexes(PRODUCT_TYPE, typeID_ProductID);
60+
REQUIRE(matches.numberOfMatches() == 0);
61+
62+
helper.setFrozen("processA");
63+
64+
matches = helper.relatedIndexes(PRODUCT_TYPE, typeID_ProductID, "labelA", "instanceA");
65+
REQUIRE(matches.numberOfMatches() == 2);
66+
edm::ProductResolverIndex indexEmptyProcess = matches.index(0);
67+
edm::ProductResolverIndex indexWithProcess = matches.index(1);
68+
REQUIRE_THROWS_AS(matches.index(2), cms::Exception);
69+
REQUIRE(indexEmptyProcess < 2);
70+
REQUIRE(indexWithProcess < 2);
71+
REQUIRE(indexEmptyProcess != indexWithProcess);
72+
73+
//with only one entry, all should resolve to the one with process name
74+
REQUIRE(helper.index(PRODUCT_TYPE, typeID_ProductID, "labelA", "instanceA") == indexWithProcess);
75+
REQUIRE(helper.index(PRODUCT_TYPE, typeID_ProductID, "labelA", "instanceA", "") == indexWithProcess);
76+
REQUIRE(helper.index(PRODUCT_TYPE, typeID_ProductID, "labelA", "instanceA", 0) == indexWithProcess);
77+
REQUIRE(helper.index(PRODUCT_TYPE, typeID_ProductID, "labelA", "instanceA", "processA") == indexWithProcess);
78+
79+
REQUIRE(helper.index(PRODUCT_TYPE, typeID_ProductID, "labelA", "instance", "processA") ==
80+
ProductResolverIndexInvalid);
81+
REQUIRE(helper.index(PRODUCT_TYPE, typeID_ProductID, "labelA", "instanceAX", "processA") ==
82+
ProductResolverIndexInvalid);
83+
REQUIRE(helper.index(PRODUCT_TYPE, typeID_ProductID, "label", "instanceA", "processA") ==
84+
ProductResolverIndexInvalid);
85+
REQUIRE(helper.index(PRODUCT_TYPE, typeID_ProductID, "labelAX", "instanceA", "processA") ==
86+
ProductResolverIndexInvalid);
87+
REQUIRE(helper.index(PRODUCT_TYPE, typeID_ProductID, "labelA", "instanceA", "process") ==
88+
ProductResolverIndexInvalid);
89+
REQUIRE(helper.index(PRODUCT_TYPE, typeID_ProductID, "labelA", "instanceA", "processAX") ==
90+
ProductResolverIndexInvalid);
91+
REQUIRE(helper.index(PRODUCT_TYPE, typeID_EventID, "labelA", "instanceA", "processA") ==
92+
ProductResolverIndexInvalid);
93+
94+
REQUIRE(helper.index(ELEMENT_TYPE, typeID_ProductID, "labelA", "instanceA") == ProductResolverIndexInvalid);
95+
REQUIRE(helper.index(ELEMENT_TYPE, typeID_ProductID, "labelA", "instanceA", "processA") ==
96+
ProductResolverIndexInvalid);
97+
98+
matches = helper.relatedIndexes(PRODUCT_TYPE, typeID_ProductID);
99+
REQUIRE(matches.numberOfMatches() == 2);
100+
REQUIRE(matches.index(0) == indexEmptyProcess);
101+
REQUIRE(matches.index(1) == indexWithProcess);
102+
103+
matches = helper.relatedIndexes(PRODUCT_TYPE, typeID_EventID);
104+
REQUIRE(matches.numberOfMatches() == 0);
105+
106+
matches = helper.relatedIndexes(ELEMENT_TYPE, typeID_ProductID);
107+
REQUIRE(matches.numberOfMatches() == 0);
108+
109+
matches = helper.relatedIndexes(ELEMENT_TYPE, typeID_ProductID, "labelA", "instanceA");
110+
REQUIRE(matches.numberOfMatches() == 0);
111+
112+
{
113+
auto indexToModules = helper.indiciesForModulesInProcess("processA");
114+
REQUIRE(indexToModules.size() == 1);
115+
REQUIRE(indexToModules.count("labelA") == 1);
116+
auto const& range = indexToModules.equal_range("labelA");
117+
REQUIRE(std::get<2>(range.first->second) == indexWithProcess);
118+
}
119+
120+
{
121+
auto indexToModules = helper.indiciesForModulesInProcess("processNotHere");
122+
REQUIRE(indexToModules.size() == 0);
123+
}
124+
}
125+
126+
SECTION("ManyEntries") {
127+
edm::ProductResolverIndexHelper helper;
128+
129+
TypeID typeIDProductID(typeid(ProductID));
130+
TypeID typeIDEventID(typeid(EventID));
131+
TypeID typeIDVectorInt(typeid(std::vector<int>));
132+
TypeID typeIDSetInt(typeid(std::set<int>));
133+
TypeID typeIDVSimpleDerived(typeid(std::vector<edmtest::SimpleDerived>));
134+
135+
helper.insert(typeIDVectorInt, "labelC", "instanceC", "processC"); // 0, 1, 2
136+
helper.insert(typeIDVectorInt, "label", "instance", "process"); // 3, 4, 5
137+
helper.insert(typeIDEventID, "labelB", "instanceB", "processB"); // 6, 7
138+
helper.insert(typeIDEventID, "label", "instanceB", "processB"); // 8, 9
139+
helper.insert(typeIDEventID, "labelX", "instanceB", "processB"); // 10, 11
140+
helper.insert(typeIDEventID, "labelB", "instance", "processB"); // 12, 13
141+
helper.insert(typeIDEventID, "labelB", "instanceX", "processB"); // 14, 15
142+
helper.insert(typeIDEventID, "labelB", "instanceB", "processB1"); // 16, 5
143+
helper.insert(typeIDEventID, "labelB", "instanceB", "processB3"); // 17, 5
144+
helper.insert(typeIDEventID, "labelB", "instanceB", "processB2"); // 18, 5
145+
helper.insert(typeIDProductID, "label", "instance", "process"); // 19, 20
146+
helper.insert(typeIDEventID, "label", "instance", "process"); // 21, 22
147+
helper.insert(typeIDProductID, "labelA", "instanceA", "processA"); // 23, 24
148+
REQUIRE_THROWS_AS(helper.insert(typeIDProductID, "labelA", "instanceA", "processA"), cms::Exception); // duplicate
149+
150+
helper.insert(typeIDSetInt, "labelC", "instanceC", "processC"); // 25, 26
151+
152+
helper.insert(typeIDVSimpleDerived, "labelC", "instanceC", "processC"); // 27, 28, 29, 30
153+
154+
helper.setFrozen("processC");
155+
156+
TypeID typeID_int(typeid(int));
157+
REQUIRE(helper.index(ELEMENT_TYPE, typeID_int, "labelC", "instanceC", "processC") == ProductResolverIndexAmbiguous);
158+
REQUIRE(helper.index(ELEMENT_TYPE, typeID_int, "labelC", "instanceC", "processQ") == ProductResolverIndexInvalid);
159+
REQUIRE(helper.index(ELEMENT_TYPE, typeID_int, "labelC", "instanceC") == ProductResolverIndexAmbiguous);
160+
edm::ProductResolverIndexHelper::Matches matches = helper.relatedIndexes(ELEMENT_TYPE, typeID_int);
161+
REQUIRE(matches.numberOfMatches() == 4);
162+
REQUIRE(matches.index(0) == 5);
163+
REQUIRE(matches.index(1) == 3);
164+
REQUIRE(matches.index(2) == 2);
165+
REQUIRE(matches.index(3) == ProductResolverIndexAmbiguous);
166+
167+
TypeID typeID_vint(typeid(std::vector<int>));
168+
REQUIRE(helper.index(PRODUCT_TYPE, typeID_vint, "labelC", "instanceC", "processC") == 0);
169+
REQUIRE(helper.index(PRODUCT_TYPE, typeID_vint, "labelC", "instanceC") == 0); //only one with no process
170+
171+
TypeID typeID_sint(typeid(std::set<int>));
172+
REQUIRE(helper.index(PRODUCT_TYPE, typeID_sint, "labelC", "instanceC", "processC") == 25);
173+
REQUIRE(helper.index(PRODUCT_TYPE, typeID_sint, "labelC", "instanceC") == 25); //only one with no process
174+
175+
TypeID typeID_Simple(typeid(edmtest::Simple));
176+
REQUIRE(helper.index(ELEMENT_TYPE, typeID_Simple, "labelC", "instanceC") == 27); //only one with no process
177+
REQUIRE(helper.index(ELEMENT_TYPE, typeID_Simple, "labelC", "instanceC", "processC") == 27);
178+
179+
TypeID typeID_SimpleDerived(typeid(edmtest::SimpleDerived));
180+
REQUIRE(helper.index(ELEMENT_TYPE, typeID_SimpleDerived, "labelC", "instanceC") == 27); //only one with no process
181+
REQUIRE(helper.index(ELEMENT_TYPE, typeID_SimpleDerived, "labelC", "instanceC", "processC") == 27);
182+
183+
TypeID typeID_VSimpleDerived(typeid(std::vector<edmtest::SimpleDerived>));
184+
REQUIRE(helper.index(PRODUCT_TYPE, typeID_VSimpleDerived, "labelC", "instanceC") == 27); //only one with no process
185+
REQUIRE(helper.index(PRODUCT_TYPE, typeID_VSimpleDerived, "labelC", "instanceC", "processC") == 27);
186+
187+
matches = helper.relatedIndexes(PRODUCT_TYPE, typeID_EventID, "labelB", "instanceB");
188+
REQUIRE(matches.numberOfMatches() == 5);
189+
ProductResolverIndex indexEmptyProcess = matches.index(0);
190+
ProductResolverIndex indexB = matches.index(1);
191+
ProductResolverIndex indexB1 = matches.index(2);
192+
ProductResolverIndex indexB2 = matches.index(3);
193+
ProductResolverIndex indexB3 = matches.index(4);
194+
REQUIRE_THROWS_AS(matches.index(5), cms::Exception);
195+
REQUIRE(indexEmptyProcess == 7);
196+
REQUIRE(indexB == 6);
197+
REQUIRE(indexB1 == 16);
198+
REQUIRE(indexB2 == 18);
199+
REQUIRE(indexB3 == 17);
200+
201+
REQUIRE(std::string(matches.moduleLabel(4)) == "labelB");
202+
REQUIRE(std::string(matches.productInstanceName(4)) == "instanceB");
203+
REQUIRE(std::string(matches.processName(4)) == "processB3");
204+
REQUIRE(std::string(matches.processName(0)) == "");
205+
206+
matches = helper.relatedIndexes(ELEMENT_TYPE, typeID_Simple);
207+
REQUIRE(matches.numberOfMatches() == 2);
208+
ProductResolverIndex indexC = matches.index(1);
209+
REQUIRE_THROWS_AS(matches.index(2), cms::Exception);
210+
REQUIRE(indexC == 27);
211+
212+
{
213+
auto indexToModules = helper.indiciesForModulesInProcess("processA");
214+
REQUIRE(indexToModules.size() == 1);
215+
}
216+
{
217+
auto indexToModules = helper.indiciesForModulesInProcess("processB");
218+
REQUIRE(indexToModules.size() == 5);
219+
}
220+
{
221+
auto indexToModules = helper.indiciesForModulesInProcess("processB1");
222+
REQUIRE(indexToModules.size() == 1);
223+
}
224+
{
225+
auto indexToModules = helper.indiciesForModulesInProcess("processB2");
226+
REQUIRE(indexToModules.size() == 1);
227+
}
228+
{
229+
auto indexToModules = helper.indiciesForModulesInProcess("processB3");
230+
REQUIRE(indexToModules.size() == 1);
231+
}
232+
{
233+
auto indexToModules = helper.indiciesForModulesInProcess("processC");
234+
REQUIRE(indexToModules.size() == 3);
235+
}
236+
}
237+
}

0 commit comments

Comments
 (0)