From: Toine Siebelink Date: Tue, 26 Sep 2023 17:17:31 +0000 (+0000) Subject: Merge "CM Data Subscriptions PoC/Performance test fixes" X-Git-Tag: 3.3.8~5 X-Git-Url: https://gerrit.onap.org/r/gitweb?a=commitdiff_plain;h=7bacf478fc69fb97d2abf29c4678552f58575b74;hp=-c;p=cps.git Merge "CM Data Subscriptions PoC/Performance test fixes" --- 7bacf478fc69fb97d2abf29c4678552f58575b74 diff --combined integration-test/src/test/groovy/org/onap/cps/integration/performance/ncmp/CmDataSubscriptionsPerfTest.groovy index 7e7dedfc3,7601d30a4..cf5c3f689 --- a/integration-test/src/test/groovy/org/onap/cps/integration/performance/ncmp/CmDataSubscriptionsPerfTest.groovy +++ b/integration-test/src/test/groovy/org/onap/cps/integration/performance/ncmp/CmDataSubscriptionsPerfTest.groovy @@@ -26,7 -26,7 +26,7 @@@ import org.onap.cps.spi.model.DataNod import static org.onap.cps.spi.FetchDescendantsOption.INCLUDE_ALL_DESCENDANTS -class CmDataSubscribersPerfTest extends NcmpPerfTestBase { +class CmDataSubscriptionsPerfTest extends NcmpPerfTestBase { def datastore1cmHandlePlaceHolder = '{"datastores":{"datastore":[{"name":"ds-1","cm-handles":{"cm-handle":[]}}]}}' def xPathForDataStore1CmHandles = '/datastores/datastore[@name="ds-1"]/cm-handles' @@@ -55,47 -55,63 +55,63 @@@ recordAndAssertPerformance("Query all subscribers", 1_000, durationInMillis) } - def 'Worst case new subscription (200x10 new entries).'() { - given: 'a new subscription with non-matching data' - def subscribers = createLeafList('subscribers',1, subscriberIdPrefix) - def filters = '"filters":' + createJsonArray('filter',numberOfFiltersPerCmHandle,'xpath','other_' + xpathPrefix,subscribers) - def cmHandles = createJsonArray('cm-handle',numberOfCmHandlesPerCmDataSubscription,'id','other' + cmHandlePrefix, filters) - when: 'Insert a new subscription' - stopWatch.start() - cpsDataService.saveData(NCMP_PERFORMANCE_TEST_DATASPACE, CM_DATA_SUBSCRIPTIONS_ANCHOR, xPathForDataStore1CmHandles, cmHandles, now) - stopWatch.stop() - def durationInMillis = stopWatch.getTotalTimeMillis() - then: 'insert new subscription with 1 second' - recordAndAssertPerformance("Insert new subscription", 1_000, durationInMillis) - } - def 'Worst case subscription update (200x10 matching entries).'() { given: 'all filters are queried' def cpsPath = '//filter' def result = objectUnderTest.queryDataNodes(NCMP_PERFORMANCE_TEST_DATASPACE, CM_DATA_SUBSCRIPTIONS_ANCHOR, cpsPath, INCLUDE_ALL_DESCENDANTS) + and: 'there are the expected number of subscribers per subscription' + assert result.collect {it.leaves.subscribers.size()}.sum() == totalNumberOfEntries * numberOfCmDataSubscribers and: 'find all entries for an existing subscriptions' def matches = querySubscriptionsByIteration(result, 1) - when: 'Update all subscriptions found' + when: 'update all subscriptions found' stopWatch.start() - /* the production code version of this should manipulate the original subscribersAsArray of course - but for the (performance) poc creating another array with one extra element suffices - */ - def jsonPerPath = [:] - matches.each { xpath, subscribersAsArray -> + HashMap> filterEntriesPerPath = [:] + matches.each { dataNode, subscribersAsArray -> def updatedSubscribers = createLeafList('subscribers', 1 + numberOfCmDataSubscribers, subscriberIdPrefix) - def filterEntry = '{"filter": {"xpath":"' + xpath + '", ' + updatedSubscribers + ' } }' - def parentPath = xpath.toString().substring(0, xpath.toString().indexOf('/filter[@xpath=')) - jsonPerPath.put(parentPath, filterEntry) + def filterEntry = '{"xpath":"' + dataNode.leaves.xpath + '", ' + updatedSubscribers + ' }' + def parentPath = dataNode.xpath.toString().substring(0, dataNode.xpath.toString().indexOf('/filter[@xpath=')) + filterEntriesPerPath.putIfAbsent(parentPath, new ArrayList()) + filterEntriesPerPath.get(parentPath).add(filterEntry) + } + HashMap jsonPerPath = [:] + filterEntriesPerPath.each { parentPath, filterEntries -> + jsonPerPath.put(parentPath, '{"filter": [' + filterEntries.join(',') + ']}') } - cpsDataService.updateDataNodesAndDescendants(NCMP_PERFORMANCE_TEST_DATASPACE, CM_DATA_SUBSCRIPTIONS_ANCHOR, jsonPerPath, now) + + // NOTE Below fails as updateDataNodesAndDescendants can't handle JSON lists! + // cpsDataService.updateDataNodesAndDescendants(NCMP_PERFORMANCE_TEST_DATASPACE, CM_DATA_SUBSCRIPTIONS_ANCHOR, jsonPerPath, now) + + // So update for each CM-handle instead: + jsonPerPath.each { parentPath, json -> + // Around 8.5 seconds for long strings, 4.8 with short strings + // cpsDataService.updateDataNodeAndDescendants(NCMP_PERFORMANCE_TEST_DATASPACE, CM_DATA_SUBSCRIPTIONS_ANCHOR, parentPath, json, now) + // Around 6.5 seconds for long strings, 3.3 seconds with short strings + cpsDataService.updateNodeLeaves(NCMP_PERFORMANCE_TEST_DATASPACE, CM_DATA_SUBSCRIPTIONS_ANCHOR, parentPath, json, now) + } + stopWatch.stop() def durationInMillis = stopWatch.getTotalTimeMillis() - then: 'Update matching subscription within 8 seconds' - //TODO Toine check with Daniel if this can be optimized quickly without really changing production code - // ie is there a better way of doing these 2,000 updates + then: 'a subscriber has been added to each filter entry' + def resultAfter = objectUnderTest.queryDataNodes(NCMP_PERFORMANCE_TEST_DATASPACE, CM_DATA_SUBSCRIPTIONS_ANCHOR, cpsPath, INCLUDE_ALL_DESCENDANTS) + assert resultAfter.collect {it.leaves.subscribers.size()}.sum() == totalNumberOfEntries * (1 + numberOfCmDataSubscribers) + and: 'update matching subscription within 8 seconds' recordAndAssertPerformance("Update matching subscription", 8_000, durationInMillis) } + def 'Worst case new subscription (200x10 new entries).'() { + given: 'a new subscription with non-matching data' + def subscribers = createLeafList('subscribers',1, subscriberIdPrefix) + def filters = '"filters":' + createJsonArray('filter',numberOfFiltersPerCmHandle,'xpath','other_' + xpathPrefix,subscribers) + def cmHandles = createJsonArray('cm-handle',numberOfCmHandlesPerCmDataSubscription,'id','other' + cmHandlePrefix, filters) + when: 'Insert a new subscription' + stopWatch.start() + cpsDataService.saveData(NCMP_PERFORMANCE_TEST_DATASPACE, CM_DATA_SUBSCRIPTIONS_ANCHOR, xPathForDataStore1CmHandles, cmHandles, now) + stopWatch.stop() + def durationInMillis = stopWatch.getTotalTimeMillis() + then: 'insert new subscription with 1 second' + recordAndAssertPerformance("Insert new subscription", 1_000, durationInMillis) + } + def querySubscriptionsByIteration(Collection allSubscriptionsAsDataNodes, targetSubscriptionSequenceNumber) { def matches = [:] allSubscriptionsAsDataNodes.each { @@@ -104,7 -120,7 +120,7 @@@ def targetSubscriptionId = subscriberIdPrefix + '-' + ( targetSubscriptionSequenceNumber > 0 ? targetSubscriptionSequenceNumber : 1 + random.nextInt(numberOfCmDataSubscribers) ) if (subscribersAsSet.contains(targetSubscriptionId)) { - matches.put(it.xpath, subscribersAsArray) + matches.put(it, subscribersAsArray) } } return matches