r7295: added an irpc benchmark. It gets about 16k messages/sec on my laptop,
authorAndrew Tridgell <tridge@samba.org>
Sun, 5 Jun 2005 07:30:44 +0000 (07:30 +0000)
committerGerald (Jerry) Carter <jerry@samba.org>
Wed, 10 Oct 2007 18:17:38 +0000 (13:17 -0500)
compared to about 20k messages/sec for the raw messaging layer. I
think that is quite acceptable given the extra functionality.
(This used to be commit a05d38d1d91f1f54d3e3794a596b468992594852)

source4/lib/messaging/irpc.h
source4/lib/messaging/messaging.c
source4/torture/local/irpc.c

index a483c78c7034add17843251b1300fac893d9cc8a..93cadddd34a88e24dd0de1f0dc4c63399594d635 100644 (file)
@@ -28,7 +28,7 @@ struct irpc_message {
 };
 
 /* don't allow calls to take too long */
-#define IRPC_CALL_TIMEOUT 10
+#define IRPC_CALL_TIMEOUT 20
 
 
 /* the server function type */
@@ -44,6 +44,9 @@ typedef NTSTATUS (*irpc_function_t)(struct irpc_message *, void *r);
 #define IRPC_CALL(msg_ctx, server_id, pipename, funcname, ptr) \
    irpc_call(msg_ctx, server_id, &dcerpc_table_ ## pipename, DCERPC_ ## funcname, ptr)
 
+#define IRPC_CALL_SEND(msg_ctx, server_id, pipename, funcname, ptr) \
+   irpc_call_send(msg_ctx, server_id, &dcerpc_table_ ## pipename, DCERPC_ ## funcname, ptr)
+
 
 /*
   a pending irpc call
index b605fa049432b4d0ed24dd0c3e0121ab645ad226..be89c97e5b633c0ba67947ed2667e6938dc298bc 100644 (file)
@@ -315,7 +315,7 @@ NTSTATUS messaging_send(struct messaging_context *msg, uint32_t server,
                if (msg->pending == NULL) {
                        EVENT_FD_WRITEABLE(msg->event.fde);
                }
-               DLIST_ADD(msg->pending, rec);
+               DLIST_ADD_END(msg->pending, rec, struct messaging_rec *);
                return NT_STATUS_OK;
        }
 
@@ -426,20 +426,27 @@ struct irpc_list {
 */
 NTSTATUS irpc_register(struct messaging_context *msg_ctx, 
                       const struct dcerpc_interface_table *table, 
-                      int call, irpc_function_t fn)
+                      int callnum, irpc_function_t fn)
 {
        struct irpc_list *irpc;
 
-       irpc = talloc(msg_ctx, struct irpc_list);
-       NT_STATUS_HAVE_NO_MEMORY(irpc);
+       /* override an existing handler, if any */
+       for (irpc=msg_ctx->irpc; irpc; irpc=irpc->next) {
+               if (irpc->table == table && irpc->callnum == callnum) {
+                       break;
+               }
+       }
+       if (irpc == NULL) {
+               irpc = talloc(msg_ctx, struct irpc_list);
+               NT_STATUS_HAVE_NO_MEMORY(irpc);
+               DLIST_ADD(msg_ctx->irpc, irpc);
+       }
 
        irpc->table   = table;
-       irpc->callnum = call;
+       irpc->callnum = callnum;
        irpc->fn      = fn;
        GUID_from_string(irpc->table->uuid, &irpc->uuid);
 
-       DLIST_ADD(msg_ctx->irpc, irpc);
-
        return NT_STATUS_OK;
 }
 
index 3dc8c01da8d35a8d34ae49081ebe2fe27b7f1d4d..65564fc7b7b447ac4c7a101321c12ba597520203 100644 (file)
@@ -46,9 +46,6 @@ static BOOL test_addone(TALLOC_CTX *mem_ctx, struct messaging_context *msg_ctx)
        NTSTATUS status;
        uint32_t res;
 
-       /* register the server side function */
-       IRPC_REGISTER(msg_ctx, rpcecho, ECHO_ADDONE, irpc_AddOne);
-
        /* make the call */
        r.in.in_data = random();
        r.out.out_data = &res;
@@ -71,6 +68,75 @@ static BOOL test_addone(TALLOC_CTX *mem_ctx, struct messaging_context *msg_ctx)
        return True;    
 }
 
+
+static void irpc_callback(struct irpc_request *irpc)
+{
+       int *pong_count = (int *)irpc->async.private;
+       NTSTATUS status = irpc_call_recv(irpc);
+       if (!NT_STATUS_IS_OK(status)) {
+               printf("irpc call failed - %s\n", nt_errstr(status));
+       }
+       (*pong_count)++;
+}
+
+/*
+  test echo speed
+*/
+static BOOL test_speed(TALLOC_CTX *mem_ctx, 
+                      struct messaging_context *msg_ctx,
+                      struct event_context *ev)
+{
+       int ping_count = 0;
+       int pong_count = 0;
+       BOOL ret = True;
+       struct timeval tv;
+       struct echo_AddOne r;
+       uint32_t res;
+
+       tv = timeval_current();
+
+       r.in.in_data = 0;
+       r.out.out_data = &res;
+
+       printf("Sending echo for 10 seconds\n");
+       while (timeval_elapsed(&tv) < 10.0) {
+               struct irpc_request *irpc;
+
+               irpc = IRPC_CALL_SEND(msg_ctx, MSG_ID, rpcecho, ECHO_ADDONE, &r);
+               if (irpc == NULL) {
+                       printf("AddOne send failed\n");
+                       return False;
+               }
+
+               irpc->async.fn = irpc_callback;
+               irpc->async.private = &pong_count;
+
+               ping_count++;
+
+               while (ping_count > pong_count + 20) {
+                       event_loop_once(ev);
+               }
+       }
+
+       printf("waiting for %d remaining replies (done %d)\n", 
+              ping_count - pong_count, pong_count);
+       while (timeval_elapsed(&tv) < 30 && pong_count < ping_count) {
+               event_loop_once(ev);
+       }
+
+       if (ping_count != pong_count) {
+               printf("ping test failed! received %d, sent %d\n", 
+                      pong_count, ping_count);
+               ret = False;
+       }
+
+       printf("echo rate of %.0f messages/sec\n", 
+              (ping_count+pong_count)/timeval_elapsed(&tv));
+
+       return ret;
+}
+
+
 BOOL torture_local_irpc(void) 
 {
        TALLOC_CTX *mem_ctx = talloc_init("torture_local_irpc");
@@ -83,7 +149,11 @@ BOOL torture_local_irpc(void)
        ev = event_context_init(mem_ctx);
        msg_ctx = messaging_init(mem_ctx, MSG_ID, ev);
 
+       /* register the server side function */
+       IRPC_REGISTER(msg_ctx, rpcecho, ECHO_ADDONE, irpc_AddOne);
+
        ret &= test_addone(mem_ctx, msg_ctx);
+       ret &= test_speed(mem_ctx, msg_ctx, ev);
 
        talloc_free(mem_ctx);