Optimise service provider handler look-up
With the increased use of chained service providers as a
way of extending a core service provider, a simple optimisation
is possible that reduces the average handler look-up time
when handling a call request. This change adds an opcode
range check such that the handler look-up for a service
provider is only performed if the opcode falls within
the opcode range handled by the service provider.
Signed-off-by: Julian Hall <julian.hall@arm.com>
Change-Id: I8c1e9c699349bd8bd2603c0834fbcd005caa36b3
diff --git a/components/service/common/provider/service_provider.c b/components/service/common/provider/service_provider.c
index 19bd088..e2f21da 100644
--- a/components/service/common/provider/service_provider.c
+++ b/components/service/common/provider/service_provider.c
@@ -12,9 +12,11 @@
uint32_t opcode)
{
const struct service_handler *handler = NULL;
- size_t index = 0;
- if (sp->num_handlers) {
+ if ((opcode >= sp->opcode_range_lo) && (opcode <= sp->opcode_range_hi)) {
+
+ size_t index = 0;
+
while (index < sp->num_handlers) {
if (service_handler_get_opcode(&sp->handlers[index]) == opcode) {
handler = &sp->handlers[index];
@@ -27,6 +29,28 @@
return handler;
}
+static void set_opcode_range(struct service_provider *sp)
+{
+ uint32_t lo = UINT32_MAX;
+ uint32_t hi = 0;
+
+ /* Determine opcode range so that this service may be skipped
+ * without having to iterate over all handlers. This reduces
+ * the time to find a qualifying handler when multiple service
+ * providers are chained.
+ */
+ for (size_t index = 0; index < sp->num_handlers; index++) {
+
+ uint32_t opcode = service_handler_get_opcode(&sp->handlers[index]);
+
+ if (opcode < lo) lo = opcode;
+ if (opcode > hi) hi = opcode;
+ }
+
+ sp->opcode_range_lo = lo;
+ sp->opcode_range_hi = hi;
+}
+
static rpc_status_t receive(struct rpc_interface *rpc_iface, struct call_req *req)
{
rpc_status_t rpc_status;
@@ -63,6 +87,8 @@
sp->num_handlers = num_handlers;
sp->successor = NULL;
+
+ set_opcode_range(sp);
}
void service_provider_extend(struct service_provider *context,
diff --git a/components/service/common/provider/service_provider.h b/components/service/common/provider/service_provider.h
index a4f15e4..a0e853e 100644
--- a/components/service/common/provider/service_provider.h
+++ b/components/service/common/provider/service_provider.h
@@ -47,6 +47,8 @@
struct rpc_interface iface;
const struct service_handler *handlers;
size_t num_handlers;
+ uint32_t opcode_range_lo;
+ uint32_t opcode_range_hi;
struct rpc_interface *successor;
};