All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.jgroups.tests.RoundTripRpc Maven / Gradle / Ivy

Go to download

This artifact provides a single jar that contains all classes required to use remote EJB and JMS, including all dependencies. It is intended for use by those not using maven, maven users should just import the EJB and JMS BOM's instead (shaded JAR's cause lots of problems with maven, as it is very easy to inadvertently end up with different versions on classes on the class path).

There is a newer version: 34.0.0.Final
Show newest version
package org.jgroups.tests;

import org.jgroups.*;
import org.jgroups.blocks.MethodCall;
import org.jgroups.blocks.RequestOptions;
import org.jgroups.blocks.ResponseMode;
import org.jgroups.blocks.RpcDispatcher;
import org.jgroups.util.AverageMinMax;
import org.jgroups.util.Util;

import java.lang.reflect.Method;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.atomic.AtomicInteger;


/**
 * Class that measure RTT for multicast messages between 2 cluster members. See {@link RpcDispatcherSpeedTest} for
 * RPCs
 * @author Bela Ban
 */
public class RoundTripRpc implements Receiver {
    protected JChannel            channel;
    protected RpcDispatcher       disp;
    protected int                 num_msgs=20000;
    protected int                 num_senders=1; // number of sender threads
    protected boolean             oob=true, dont_bundle, details;
    protected Invoker[]           invokers;
    protected static final Method requestMethod;

    static {
        try {
            requestMethod=RoundTripRpc.class.getDeclaredMethod("request", short.class);
        }
        catch(NoSuchMethodException e) {
            throw new RuntimeException(e);
        }
    }


    protected void start(String props, String name) throws Exception {
        channel=new JChannel(props).name(name);
        disp=new RpcDispatcher(channel, this).setReceiver(this);
        disp.setMethodLookup(ignored -> requestMethod);
        channel.connect("rt");
        View view=channel.getView();
        if(view.size() > 2)
            System.err.printf("More than 2 members found (%s); terminating\n", view);
        else
            loop();
        Util.close(channel, disp);
    }

    public static short request(short id) {
        return id;
    }



    public void viewAccepted(View view) {
        System.out.println("view = " + view);
    }

    protected void loop() {
        boolean looping=true;
        while(looping) {
            int c=Util.keyPress(String.format("[1] send [2] num_msgs (%d) [3] senders (%d)\n" +
                                                "[o] oob (%b) [b] dont_bundle (%b) [d] details (%b) [x] exit\n",
                                              num_msgs, num_senders, oob, dont_bundle, details));
            try {
                switch(c) {
                    case '1':
                        invokeRequests();
                        break;
                    case '2':
                        num_msgs=Util.readIntFromStdin("num_msgs: ");
                        break;
                    case '3':
                        num_senders=Util.readIntFromStdin("num_senders: ");
                        break;
                    case 'o':
                        oob=!oob;
                        break;
                    case 'b':
                        dont_bundle=!dont_bundle;
                        break;
                    case 'd':
                        details=!details;
                        break;
                    case 'x':
                    case -1:
                        looping=false;
                        break;
                }
            }
            catch(Throwable t) {
                t.printStackTrace();
            }
        }
    }

    protected void invokeRequests() throws Exception {
        View view=channel.getView();
        if(view.size() != 2) {
            System.err.printf("Cluster must have exactly 2 members: %s\n", view);
            return;
        }

        Address target=Util.pickNext(view.getMembers(), channel.getAddress());
        final CountDownLatch latch=new CountDownLatch(1);
        final AtomicInteger sent_msgs=new AtomicInteger(0);
        invokers=new Invoker[num_senders];
        for(int i=0; i < num_senders; i++) {
            invokers[i]=new Invoker((short)i, latch, sent_msgs, target);
            invokers[i].start();
        }

        long start=System.nanoTime();
        latch.countDown(); // start all sender threads
        for(Invoker invoker : invokers)
            invoker.join();
        long total_time=System.nanoTime()-start;
        double msgs_sec=num_msgs / (total_time / 1_000_000_000.0);

        AverageMinMax avg=null;
        if(details)
            System.out.println("");
        for(Invoker invoker : invokers) {
            if(details)
                System.out.printf("%d: %s\n", invoker.id, print(invoker.avg));
            if(avg == null)
                avg=invoker.avg;
            else
                avg.merge(invoker.avg);
        }

        System.out.printf(Util.bold("\n\nreqs/sec = %.2f, " +
                                      "round-trip = min/avg/max: %.2f / %.2f / %.2f us\n\n"),
                          msgs_sec, avg.min()/1000.0, avg.average() / 1000.0, avg.max()/1000.0);
    }

    protected static String print(AverageMinMax avg) {
        return String.format("round-trip min/avg/max = %.2f / %.2f / %.2f us",
                             avg.min() / 1000.0, avg.average() / 1000.0, avg.max() / 1000.0);
    }


    protected class Invoker extends Thread {
        protected final short            id;
        protected final CountDownLatch   latch;
        protected final AtomicInteger    sent_msgs; // current number of messages; senders stop if sent_msgs >= num_msgs
        protected final int              print;
        protected final Address          target;
        protected final AverageMinMax    avg=new AverageMinMax(); // in ns

        public Invoker(short id, CountDownLatch latch, AtomicInteger sent_msgs, Address target) {
            this.id=id;
            this.latch=latch;
            this.sent_msgs=sent_msgs;
            this.target=target;
            print=Math.max(1, num_msgs / 10);
        }

        public void run() {
            try {
                latch.await();
            }
            catch(InterruptedException e) {
                e.printStackTrace();
            }
            RequestOptions opts=new RequestOptions(ResponseMode.GET_ALL, 0);
            if(oob) opts.flags(Message.Flag.OOB);
            if(dont_bundle) opts.flags(Message.Flag.DONT_BUNDLE);
            MethodCall call=new MethodCall((short)1, id);
            for(;;) {
                int num=sent_msgs.getAndIncrement();
                if(num > num_msgs)
                    break;
                if(num > 0 && num % print == 0)
                    System.out.printf(".");
                try {
                    long start=System.nanoTime();
                    disp.callRemoteMethod(target, call, opts);
                    long time=System.nanoTime()-start;
                    avg.add(time);
                }
                catch(Exception e) {
                    e.printStackTrace();
                }
            }
        }
    }


    public static void main(String[] args) throws Exception {
        String props=null, name=null;
        for(int i=0; i < args.length; i++) {
            if(args[i].equals("-props")) {
                props=args[++i];
                continue;
            }
            if(args[i].equals("-name")) {
                name=args[++i];
                continue;
            }
            help();
            return;
        }
        new RoundTripRpc().start(props, name);
    }



    private static void help() {
        System.out.println("RoundTripRpc [-props ] [-name name]");
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy