This is an automated email from the ASF dual-hosted git repository. pingtimeout pushed a commit to branch main in repository https://gitbox.apache.org/repos/asf/polaris-tools.git
The following commit(s) were added to refs/heads/main by this push: new 6c2d4d4 Small Benchmarks improvements (#25) 6c2d4d4 is described below commit 6c2d4d45f44b60a06eeca549bc80f7205cb082e0 Author: Pierre Laporte <pie...@pingtimeout.fr> AuthorDate: Thu Jul 10 09:28:56 2025 +0200 Small Benchmarks improvements (#25) feat: enhance n-ary tree operations and standardize Gatling action names Add tree traversal methods to NAryTreeBuilder: - childrenOf(): compute all child node ordinals for a given parent - siblingsOf(): compute all sibling node ordinals for a given node Standardize Gatling HTTP action names for consistent reporting: - "Create XXX" for entity creation - "Fetch single XXX" for individual entity retrieval - "Fetch child XXX" for bulk child entity retrieval - "Update XXX" for entity updates - "Check XXX exists" for existence validation This improves benchmark report readability and provides more tree navigation utilities for hierarchical namespace operations. --- .../polaris/benchmarks/NAryTreeBuilder.scala | 33 ++++++++++++++++++++++ .../benchmarks/actions/NamespaceActions.scala | 8 +++--- .../polaris/benchmarks/actions/TableActions.scala | 10 +++---- .../polaris/benchmarks/actions/ViewActions.scala | 10 +++---- .../simulations/ReadUpdateTreeDataset.scala | 31 ++++++++++---------- 5 files changed, 62 insertions(+), 30 deletions(-) diff --git a/benchmarks/src/gatling/scala/org/apache/polaris/benchmarks/NAryTreeBuilder.scala b/benchmarks/src/gatling/scala/org/apache/polaris/benchmarks/NAryTreeBuilder.scala index 326ef6d..582b5de 100644 --- a/benchmarks/src/gatling/scala/org/apache/polaris/benchmarks/NAryTreeBuilder.scala +++ b/benchmarks/src/gatling/scala/org/apache/polaris/benchmarks/NAryTreeBuilder.scala @@ -47,6 +47,22 @@ case class NAryTreeBuilder(nsWidth: Int, nsDepth: Int) { pathToRoot(parent, ordinal :: acc) } + /** + * Computes the ordinals of all child nodes for a given node. + * + * @param ordinal the ordinal of the parent node + * @return a list of ordinals representing the child nodes + */ + def childrenOf(ordinal: Int): List[Int] = + if (depthOf(ordinal) >= nsDepth - 1) { + // Node is a leaf, has no children + List.empty + } else { + // For a node with ordinal p, its children have ordinals: p*nsWidth + 1, p*nsWidth + 2, ..., p*nsWidth + nsWidth + val firstChild = ordinal * nsWidth + 1 + (firstChild until firstChild + nsWidth).toList + } + /** * Calculates the depth of a node in the n-ary tree based on its ordinal. * @@ -100,4 +116,21 @@ case class NAryTreeBuilder(nsWidth: Int, nsDepth: Int) { val lastLevel = nsDepth - 1 math.pow(nsWidth, lastLevel).toInt } + + /** + * Computes the ordinals of all sibling nodes for a given node. + * + * @param ordinal the ordinal of the node + * @return a list of ordinals representing the sibling nodes (excluding the node itself) + */ + def siblingsOf(ordinal: Int): List[Int] = + if (ordinal == 0) { + // Root node has no siblings + List.empty + } else { + // Get parent ordinal + val parent = (ordinal - 1) / nsWidth + // Get all children of parent (siblings including self) and exclude self + childrenOf(parent).filter(_ != ordinal) + } } diff --git a/benchmarks/src/gatling/scala/org/apache/polaris/benchmarks/actions/NamespaceActions.scala b/benchmarks/src/gatling/scala/org/apache/polaris/benchmarks/actions/NamespaceActions.scala index 7a5f5f0..1fedc70 100644 --- a/benchmarks/src/gatling/scala/org/apache/polaris/benchmarks/actions/NamespaceActions.scala +++ b/benchmarks/src/gatling/scala/org/apache/polaris/benchmarks/actions/NamespaceActions.scala @@ -173,7 +173,7 @@ case class NamespaceActions( * There is no limit to the number of users that can fetch namespaces concurrently. */ val fetchNamespace: ChainBuilder = exec( - http("Fetch Namespace") + http("Fetch single namespace") .get("/api/catalog/v1/#{catalogName}/namespaces/#{namespaceMultipartPath}") .header("Authorization", "Bearer #{accessToken}") .check(status.is(200)) @@ -206,15 +206,15 @@ case class NamespaceActions( * structure. */ val fetchAllChildrenNamespaces: ChainBuilder = exec( - http("Fetch all Namespaces under specific parent") + http("Fetch child namespaces") .get("/api/catalog/v1/#{catalogName}/namespaces?parent=#{namespaceMultipartPath}") .header("Authorization", "Bearer #{accessToken}") .check(status.is(200)) ) val updateNamespaceProperties: ChainBuilder = - retryOnHttpStatus(maxRetries, retryableHttpCodes, "Update namespace properties")( - http("Update Namespace Properties") + retryOnHttpStatus(maxRetries, retryableHttpCodes, "Update namespace")( + http("Update namespace") .post("/api/catalog/v1/#{catalogName}/namespaces/#{namespaceMultipartPath}/properties") .header("Authorization", "Bearer #{accessToken}") .header("Content-Type", "application/json") diff --git a/benchmarks/src/gatling/scala/org/apache/polaris/benchmarks/actions/TableActions.scala b/benchmarks/src/gatling/scala/org/apache/polaris/benchmarks/actions/TableActions.scala index 1d5b951..67e0ac0 100644 --- a/benchmarks/src/gatling/scala/org/apache/polaris/benchmarks/actions/TableActions.scala +++ b/benchmarks/src/gatling/scala/org/apache/polaris/benchmarks/actions/TableActions.scala @@ -149,7 +149,7 @@ case class TableActions( * * There is no limit to the number of users that can create tables concurrently. */ - val createTable: ChainBuilder = retryOnHttpStatus(maxRetries, retryableHttpCodes, "Create table")( + val createTable: ChainBuilder = retryOnHttpStatus(maxRetries, retryableHttpCodes, "Create Table")( http("Create Table") .post("/api/catalog/v1/#{catalogName}/namespaces/#{multipartNamespace}/tables") .header("Authorization", "Bearer #{accessToken}") @@ -181,7 +181,7 @@ case class TableActions( * There is no limit to the number of users that can fetch tables concurrently. */ val fetchTable: ChainBuilder = exec( - http("Fetch Table") + http("Fetch single Table") .get("/api/catalog/v1/#{catalogName}/namespaces/#{multipartNamespace}/tables/#{tableName}") .header("Authorization", "Bearer #{accessToken}") .check(status.is(200)) @@ -209,7 +209,7 @@ case class TableActions( * given namespace, supporting bulk retrieval of table metadata. */ val fetchAllTables: ChainBuilder = exec( - http("Fetch all Tables under parent namespace") + http("Fetch children Tables") .get("/api/catalog/v1/#{catalogName}/namespaces/#{multipartNamespace}/tables") .header("Authorization", "Bearer #{accessToken}") .check(status.is(200)) @@ -222,8 +222,8 @@ case class TableActions( * There is no limit to the number of users that can update table properties concurrently. */ val updateTable: ChainBuilder = - retryOnHttpStatus(maxRetries, retryableHttpCodes, "Update table metadata")( - http("Update table metadata") + retryOnHttpStatus(maxRetries, retryableHttpCodes, "Update Table")( + http("Update Table") .post("/api/catalog/v1/#{catalogName}/namespaces/#{multipartNamespace}/tables/#{tableName}") .header("Authorization", "Bearer #{accessToken}") .header("Content-Type", "application/json") diff --git a/benchmarks/src/gatling/scala/org/apache/polaris/benchmarks/actions/ViewActions.scala b/benchmarks/src/gatling/scala/org/apache/polaris/benchmarks/actions/ViewActions.scala index 14bf698..99ff175 100644 --- a/benchmarks/src/gatling/scala/org/apache/polaris/benchmarks/actions/ViewActions.scala +++ b/benchmarks/src/gatling/scala/org/apache/polaris/benchmarks/actions/ViewActions.scala @@ -134,7 +134,7 @@ case class ViewActions( ) } - val createView: ChainBuilder = retryOnHttpStatus(maxRetries, retryableHttpCodes, "Create view")( + val createView: ChainBuilder = retryOnHttpStatus(maxRetries, retryableHttpCodes, "Create View")( http("Create View") .post("/api/catalog/v1/#{catalogName}/namespaces/#{multipartNamespace}/views") .header("Authorization", "Bearer #{accessToken}") @@ -171,7 +171,7 @@ case class ViewActions( ) val fetchView: ChainBuilder = exec( - http("Fetch View") + http("Fetch single View") .get("/api/catalog/v1/#{catalogName}/namespaces/#{multipartNamespace}/views/#{viewName}") .header("Authorization", "Bearer #{accessToken}") .check(status.is(200)) @@ -195,7 +195,7 @@ case class ViewActions( ) val fetchAllViews: ChainBuilder = exec( - http("Fetch all Views under parent namespace") + http("Fetch children Views") .get("/api/catalog/v1/#{catalogName}/namespaces/#{multipartNamespace}/views") .header("Authorization", "Bearer #{accessToken}") .check(status.is(200)) @@ -208,8 +208,8 @@ case class ViewActions( * There is no limit to the number of users that can update table properties concurrently. */ val updateView: ChainBuilder = - retryOnHttpStatus(maxRetries, retryableHttpCodes, "Update View metadata")( - http("Update View metadata") + retryOnHttpStatus(maxRetries, retryableHttpCodes, "Update View")( + http("Update View") .post("/api/catalog/v1/#{catalogName}/namespaces/#{multipartNamespace}/views/#{viewName}") .header("Authorization", "Bearer #{accessToken}") .header("Content-Type", "application/json") diff --git a/benchmarks/src/gatling/scala/org/apache/polaris/benchmarks/simulations/ReadUpdateTreeDataset.scala b/benchmarks/src/gatling/scala/org/apache/polaris/benchmarks/simulations/ReadUpdateTreeDataset.scala index 4d5ebb9..2304920 100644 --- a/benchmarks/src/gatling/scala/org/apache/polaris/benchmarks/simulations/ReadUpdateTreeDataset.scala +++ b/benchmarks/src/gatling/scala/org/apache/polaris/benchmarks/simulations/ReadUpdateTreeDataset.scala @@ -54,7 +54,6 @@ class ReadUpdateTreeDataset extends Simulation { // -------------------------------------------------------------------------------- // Helper values // -------------------------------------------------------------------------------- - private val numNamespaces: Int = dp.nAryTree.numberOfNodes private val accessToken: AtomicReference[String] = new AtomicReference() private val shouldRefreshToken: AtomicBoolean = new AtomicBoolean(true) @@ -64,6 +63,21 @@ class ReadUpdateTreeDataset extends Simulation { private val tblActions = TableActions(dp, wp, accessToken) private val viewActions = ViewActions(dp, wp, accessToken) + private val nsListFeeder = new CircularIterator(nsActions.namespaceIdentityFeeder) + private val nsExistsFeeder = new CircularIterator(nsActions.namespaceIdentityFeeder) + private val nsFetchFeeder = new CircularIterator(nsActions.namespaceFetchFeeder) + private val nsUpdateFeeder = nsActions.namespacePropertiesUpdateFeeder() + + private val tblListFeeder = new CircularIterator(tblActions.tableIdentityFeeder) + private val tblExistsFeeder = new CircularIterator(tblActions.tableIdentityFeeder) + private val tblFetchFeeder = new CircularIterator(tblActions.tableFetchFeeder) + private val tblUpdateFeeder = tblActions.propertyUpdateFeeder() + + private val viewListFeeder = new CircularIterator(viewActions.viewIdentityFeeder) + private val viewExistsFeeder = new CircularIterator(viewActions.viewIdentityFeeder) + private val viewFetchFeeder = new CircularIterator(viewActions.viewFetchFeeder) + private val viewUpdateFeeder = viewActions.propertyUpdateFeeder() + // -------------------------------------------------------------------------------- // Authentication related workloads: // * Authenticate and store the access token for later use every minute @@ -91,21 +105,6 @@ class ReadUpdateTreeDataset extends Simulation { session } - private val nsListFeeder = new CircularIterator(nsActions.namespaceIdentityFeeder) - private val nsExistsFeeder = new CircularIterator(nsActions.namespaceIdentityFeeder) - private val nsFetchFeeder = new CircularIterator(nsActions.namespaceFetchFeeder) - private val nsUpdateFeeder = nsActions.namespacePropertiesUpdateFeeder() - - private val tblListFeeder = new CircularIterator(tblActions.tableIdentityFeeder) - private val tblExistsFeeder = new CircularIterator(tblActions.tableIdentityFeeder) - private val tblFetchFeeder = new CircularIterator(tblActions.tableFetchFeeder) - private val tblUpdateFeeder = tblActions.propertyUpdateFeeder() - - private val viewListFeeder = new CircularIterator(viewActions.viewIdentityFeeder) - private val viewExistsFeeder = new CircularIterator(viewActions.viewIdentityFeeder) - private val viewFetchFeeder = new CircularIterator(viewActions.viewFetchFeeder) - private val viewUpdateFeeder = viewActions.propertyUpdateFeeder() - // -------------------------------------------------------------------------------- // Workload: Randomly read and write entities // --------------------------------------------------------------------------------