From 15d0cf91a6d4eb7350aa7f69d48607de92484ac9 Mon Sep 17 00:00:00 2001 From: danielhanrahan Date: Tue, 26 Sep 2023 13:16:05 +0100 Subject: CM Data Subscriptions PoC/Performance test fixes There were some issues in original update test that caused no updates to be written. This fixes those issues and adds verifies the subscriber count. Issue-ID: CPS-1881 Signed-off-by: danielhanrahan Change-Id: I7b5a5e95bee247d1b1d52f5bc5e8567b8871a659 --- .../ncmp/CmDataSubscriptionsPerfTest.groovy | 72 +++++++++++++--------- 1 file changed, 44 insertions(+), 28 deletions(-) diff --git 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 index 00e2d07b3d..7601d30a47 100644 --- 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 @@ -55,47 +55,63 @@ class CmDataSubscribersPerfTest extends NcmpPerfTestBase { 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 @@ class CmDataSubscribersPerfTest extends NcmpPerfTestBase { 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 -- cgit 1.2.3-korg