From 52739eaaf797d9f800a55c2e77982dc8be6661c6 Mon Sep 17 00:00:00 2001 From: danielhanrahan Date: Thu, 4 Jan 2024 13:26:34 +0000 Subject: Add performance tests for saveListElements Add performance tests for CpsDataService methods: - saveListElements - saveListElementsBatch Results show that saveListElementsBatch (used only by NCMP for saving CM-handles) has extremely poor performance compared to saveListElements, which is over 4x faster and uses less memory. Issue-ID: CPS-2019 Signed-off-by: danielhanrahan Change-Id: I89d634c69b3790f1e1a79e2ff5392db5a45c761b --- .../performance/cps/WritePerfTest.groovy | 89 ++++++++++++++++++---- 1 file changed, 75 insertions(+), 14 deletions(-) (limited to 'integration-test') diff --git a/integration-test/src/test/groovy/org/onap/cps/integration/performance/cps/WritePerfTest.groovy b/integration-test/src/test/groovy/org/onap/cps/integration/performance/cps/WritePerfTest.groovy index 2d38a0dfb6..a5669baf6a 100644 --- a/integration-test/src/test/groovy/org/onap/cps/integration/performance/cps/WritePerfTest.groovy +++ b/integration-test/src/test/groovy/org/onap/cps/integration/performance/cps/WritePerfTest.groovy @@ -1,6 +1,6 @@ /* * ============LICENSE_START======================================================= - * Copyright (C) 2023 Nordix Foundation + * Copyright (C) 2023-2024 Nordix Foundation * ================================================================================ * Licensed under the Apache License, Version 2.0 (the 'License'); * you may not use this file except in compliance with the License. @@ -25,21 +25,24 @@ import org.onap.cps.integration.performance.base.CpsPerfTestBase class WritePerfTest extends CpsPerfTestBase { + static final def WRITE_TEST_ANCHOR = 'writeTestAnchor' + def 'Writing openroadm data has linear time.'() { given: 'an empty anchor exists for openroadm' - cpsAnchorService.createAnchor(CPS_PERFORMANCE_TEST_DATASPACE, LARGE_SCHEMA_SET, 'writeAnchor') + cpsAnchorService.createAnchor(CPS_PERFORMANCE_TEST_DATASPACE, LARGE_SCHEMA_SET, WRITE_TEST_ANCHOR) and: 'a list of device nodes to add' def jsonData = generateOpenRoadData(totalNodes) when: 'device nodes are added' resourceMeter.start() - cpsDataService.saveData(CPS_PERFORMANCE_TEST_DATASPACE, 'writeAnchor', jsonData, OffsetDateTime.now()) + cpsDataService.saveData(CPS_PERFORMANCE_TEST_DATASPACE, WRITE_TEST_ANCHOR, jsonData, OffsetDateTime.now()) resourceMeter.stop() - def durationInSeconds = resourceMeter.getTotalTimeInSeconds() then: 'the operation takes less than #expectedDuration and memory used is within limit' - recordAndAssertResourceUsage("Writing ${totalNodes} devices", expectedDuration, durationInSeconds, memoryLimit, resourceMeter.getTotalMemoryUsageInMB()) + recordAndAssertResourceUsage("Writing ${totalNodes} devices", + expectedDuration, resourceMeter.getTotalTimeInSeconds(), + memoryLimit, resourceMeter.getTotalMemoryUsageInMB()) cleanup: - cpsDataService.deleteDataNodes(CPS_PERFORMANCE_TEST_DATASPACE, 'writeAnchor', OffsetDateTime.now()) - cpsAnchorService.deleteAnchor(CPS_PERFORMANCE_TEST_DATASPACE, 'writeAnchor') + cpsDataService.deleteDataNodes(CPS_PERFORMANCE_TEST_DATASPACE, WRITE_TEST_ANCHOR, OffsetDateTime.now()) + cpsAnchorService.deleteAnchor(CPS_PERFORMANCE_TEST_DATASPACE, WRITE_TEST_ANCHOR) where: totalNodes || expectedDuration | memoryLimit 50 || 4 | 100 @@ -50,21 +53,22 @@ class WritePerfTest extends CpsPerfTestBase { def 'Writing bookstore data has exponential time.'() { given: 'an anchor containing a bookstore with a single category' - cpsAnchorService.createAnchor(CPS_PERFORMANCE_TEST_DATASPACE, BOOKSTORE_SCHEMA_SET, 'writeAnchor') + cpsAnchorService.createAnchor(CPS_PERFORMANCE_TEST_DATASPACE, BOOKSTORE_SCHEMA_SET, WRITE_TEST_ANCHOR) def parentNodeData = '{"bookstore": { "categories": [{ "code": 1, "name": "Test", "books" : [] }] }}' - cpsDataService.saveData(CPS_PERFORMANCE_TEST_DATASPACE, 'writeAnchor', parentNodeData, OffsetDateTime.now()) + cpsDataService.saveData(CPS_PERFORMANCE_TEST_DATASPACE, WRITE_TEST_ANCHOR, parentNodeData, OffsetDateTime.now()) and: 'a list of books to add' def booksData = '{"books":[' + (1..totalBooks).collect {'{ "title": "' + it + '" }' }.join(',') + ']}' when: 'books are added' resourceMeter.start() - cpsDataService.saveData(CPS_PERFORMANCE_TEST_DATASPACE, 'writeAnchor', '/bookstore/categories[@code=1]', booksData, OffsetDateTime.now()) + cpsDataService.saveData(CPS_PERFORMANCE_TEST_DATASPACE, WRITE_TEST_ANCHOR, '/bookstore/categories[@code=1]', booksData, OffsetDateTime.now()) resourceMeter.stop() - def durationInSeconds = resourceMeter.getTotalTimeInSeconds() then: 'the operation takes less than #expectedDuration and memory used is within limit' - recordAndAssertResourceUsage("Writing ${totalBooks} books", expectedDuration, durationInSeconds, memoryLimit, resourceMeter.getTotalMemoryUsageInMB()) + recordAndAssertResourceUsage("Writing ${totalBooks} books", + expectedDuration, resourceMeter.getTotalTimeInSeconds(), + memoryLimit, resourceMeter.getTotalMemoryUsageInMB()) cleanup: - cpsDataService.deleteDataNodes(CPS_PERFORMANCE_TEST_DATASPACE, 'writeAnchor', OffsetDateTime.now()) - cpsAnchorService.deleteAnchor(CPS_PERFORMANCE_TEST_DATASPACE, 'writeAnchor') + cpsDataService.deleteDataNodes(CPS_PERFORMANCE_TEST_DATASPACE, WRITE_TEST_ANCHOR, OffsetDateTime.now()) + cpsAnchorService.deleteAnchor(CPS_PERFORMANCE_TEST_DATASPACE, WRITE_TEST_ANCHOR) where: totalBooks || expectedDuration | memoryLimit 800 || 1 | 50 @@ -73,4 +77,61 @@ class WritePerfTest extends CpsPerfTestBase { 6400 || 18 | 200 } + def 'Writing openroadm list data using saveListElements.'() { + given: 'an anchor and empty container node for openroadm' + cpsAnchorService.createAnchor(CPS_PERFORMANCE_TEST_DATASPACE, LARGE_SCHEMA_SET, WRITE_TEST_ANCHOR) + cpsDataService.saveData(CPS_PERFORMANCE_TEST_DATASPACE, WRITE_TEST_ANCHOR, + '{ "openroadm-devices": { "openroadm-device": []}}', now) + and: 'a list of device nodes to add' + def innerNode = readResourceDataFile('openroadm/innerNode.json') + def jsonListData = '{ "openroadm-device": [' + + (1..totalNodes).collect { innerNode.replace('NODE_ID_HERE', it.toString()) }.join(',') + + ']}' + when: 'device nodes are added' + resourceMeter.start() + cpsDataService.saveListElements(CPS_PERFORMANCE_TEST_DATASPACE, WRITE_TEST_ANCHOR, '/openroadm-devices', jsonListData, OffsetDateTime.now()) + resourceMeter.stop() + then: 'the operation takes less than #expectedDuration and memory used is within limit' + recordAndAssertResourceUsage("Saving list of ${totalNodes} devices", + expectedDuration, resourceMeter.getTotalTimeInSeconds(), + memoryLimit, resourceMeter.getTotalMemoryUsageInMB()) + cleanup: + cpsDataService.deleteDataNodes(CPS_PERFORMANCE_TEST_DATASPACE, WRITE_TEST_ANCHOR, OffsetDateTime.now()) + cpsAnchorService.deleteAnchor(CPS_PERFORMANCE_TEST_DATASPACE, WRITE_TEST_ANCHOR) + where: + totalNodes || expectedDuration | memoryLimit + 50 || 4 | 200 + 100 || 7 | 200 + 200 || 14 | 250 + 400 || 28 | 250 + } + + def 'Writing openroadm list data using saveListElementsBatch.'() { + given: 'an anchor and empty container node for openroadm' + cpsAnchorService.createAnchor(CPS_PERFORMANCE_TEST_DATASPACE, LARGE_SCHEMA_SET, WRITE_TEST_ANCHOR) + cpsDataService.saveData(CPS_PERFORMANCE_TEST_DATASPACE, WRITE_TEST_ANCHOR, + '{ "openroadm-devices": { "openroadm-device": []}}', now) + and: 'a list of device nodes to add' + def innerNode = readResourceDataFile('openroadm/innerNode.json') + def multipleJsonData = (1..totalNodes).collect { + '{ "openroadm-device": [' + innerNode.replace('NODE_ID_HERE', it.toString()) + ']}' } + when: 'device nodes are added' + resourceMeter.start() + cpsDataService.saveListElementsBatch(CPS_PERFORMANCE_TEST_DATASPACE, WRITE_TEST_ANCHOR, '/openroadm-devices', multipleJsonData, OffsetDateTime.now()) + resourceMeter.stop() + then: 'the operation takes less than #expectedDuration and memory used is within limit' + recordAndAssertResourceUsage("Saving batch of ${totalNodes} lists", + expectedDuration, resourceMeter.getTotalTimeInSeconds(), + memoryLimit, resourceMeter.getTotalMemoryUsageInMB()) + cleanup: + cpsDataService.deleteDataNodes(CPS_PERFORMANCE_TEST_DATASPACE, WRITE_TEST_ANCHOR, OffsetDateTime.now()) + cpsAnchorService.deleteAnchor(CPS_PERFORMANCE_TEST_DATASPACE, WRITE_TEST_ANCHOR) + where: + totalNodes || expectedDuration | memoryLimit + 50 || 16 | 500 + 100 || 32 | 500 + 200 || 64 | 1000 + 400 || 128 | 1250 + } + } -- cgit 1.2.3-korg