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

org.jgroups.util.RpcStats Maven / Gradle / Ivy

There is a newer version: 5.3.13.Final
Show newest version
package org.jgroups.util;

import org.jgroups.Address;
import org.jgroups.Global;
import org.jgroups.protocols.RTTHeader;

import java.util.Arrays;
import java.util.Collection;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.atomic.AtomicInteger;

import static java.util.concurrent.TimeUnit.NANOSECONDS;

/**
 * Keeps track of stats for sync and async unicasts and multicasts
 * @author Bela Ban
 * @since  3.6.8
 */
public class RpcStats {
    protected final AtomicInteger           sync_unicasts=new AtomicInteger(0);
    protected final AtomicInteger           async_unicasts=new AtomicInteger(0);
    protected final AtomicInteger           sync_multicasts=new AtomicInteger(0);
    protected final AtomicInteger           async_multicasts=new AtomicInteger(0);
    protected final AtomicInteger           sync_anycasts=new AtomicInteger(0);
    protected final AtomicInteger           async_anycasts=new AtomicInteger(0);
    protected volatile Map  stats;
    protected volatile Map rtt_stats;

    public enum Type {MULTICAST, UNICAST, ANYCAST}

    public RpcStats(boolean extended_stats) {
        extendedStats(extended_stats);
    }

    public int unicasts(boolean sync)    {return sync? sync_unicasts.get()   : async_unicasts.get();}
    public int multicasts(boolean sync)  {return sync? sync_multicasts.get() : async_multicasts.get();}
    public int anycasts(boolean sync)    {return sync? sync_anycasts.get()   : async_anycasts.get();}

    public boolean  extendedStats()          {return stats != null;}
    public RpcStats extendedStats(boolean f) {
        if(f) {
            if(stats == null)
                stats=new ConcurrentHashMap<>();
        }
        else
            stats=null;
        return this;
    }

    public void reset() {
        if(stats != null)
            stats.clear();
        if(rtt_stats != null)
            rtt_stats.clear();
        for(AtomicInteger ai: Arrays.asList(sync_unicasts, async_unicasts, sync_multicasts, async_multicasts, sync_anycasts, async_anycasts))
            ai.set(0);
    }

    public void add(Type type, Address dest, boolean sync, long time) {
        update(type, sync);
        addToResults(dest, sync, time);
    }

    public void addAnycast(boolean sync, long time, Collection
dests) { update(Type.ANYCAST, sync); if(dests != null) for(Address dest: dests) addToResults(dest, sync, time); } public void addRTTStats(Address sender, RTTHeader hdr) { if(hdr == null) return; if(this.rtt_stats == null) this.rtt_stats=new ConcurrentHashMap<>(); Address key=sender == null? Global.NULL_ADDRESS : sender; RTTStat rtt_stat=rtt_stats.computeIfAbsent(key, k -> new RTTStat()); rtt_stat.add(hdr); } public void retainAll(Collection
members) { Map map; if(members == null || (map=stats) == null) return; map.keySet().retainAll(members); if(rtt_stats != null) rtt_stats.keySet().retainAll(members); } public String printStatsByDest() { if(stats == null) return "(no stats)"; StringBuilder sb=new StringBuilder("\n"); for(Map.Entry entry: stats.entrySet()) { Address dst=entry.getKey(); sb.append(String.format("%s: %s\n", dst == Global.NULL_ADDRESS? "" : dst, entry.getValue())); } return sb.toString(); } public String printRTTStatsByDest() { if(rtt_stats == null) return "(no RTT stats)"; StringBuilder sb=new StringBuilder("\n"); for(Map.Entry entry: rtt_stats.entrySet()) { Address dst=entry.getKey(); sb.append(String.format("%s:\n%s\n", dst == Global.NULL_ADDRESS? "" : dst, entry.getValue())); } return sb.toString(); } public String toString() { return String.format("sync mcasts: %d, async mcasts: %d, sync ucasts: %d, async ucasts: %d, sync acasts: %d, async acasts: %d", sync_multicasts.get(), async_multicasts.get(), sync_unicasts.get(), async_unicasts.get(), sync_anycasts.get(), async_anycasts.get()); } protected void update(Type type, boolean sync) { switch(type) { case MULTICAST: if(sync) sync_multicasts.incrementAndGet(); else async_multicasts.incrementAndGet(); break; case UNICAST: if(sync) sync_unicasts.incrementAndGet(); else async_unicasts.incrementAndGet(); break; case ANYCAST: if(sync) sync_anycasts.incrementAndGet(); else async_anycasts.incrementAndGet(); break; } } protected void addToResults(Address dest, boolean sync, long time) { Map map=stats; if(map == null) return; if(dest == null) dest=Global.NULL_ADDRESS; Result res=map.computeIfAbsent(dest, k -> new Result()); res.add(sync, time); } protected static class Result { protected long sync, async; protected final AverageMinMax avg=new AverageMinMax(); protected long sync() {return sync;} protected long async() {return async;} protected long min() {return avg.min();} protected long max() {return avg.max();} protected synchronized double avg() {return avg.average();} protected synchronized void add(boolean sync, long time) { if(sync) this.sync++; else this.async++; if(time > 0) avg.add(time); } public String toString() { double avg_us=avg()/1000.0; // convert nanos to microsecs double min_us=avg.min()/1000.0; // us double max_us=avg.max()/1000.0; // us return String.format("async: %d, sync: %d, round-trip min/avg/max (us): %.2f / %.2f / %.2f", async, sync, min_us, avg_us, max_us); } } protected static class RTTStat { protected final AverageMinMax total_time=new AverageMinMax(); // RTT for a sync request protected final AverageMinMax down_req_time=new AverageMinMax(); // send until the req is serialized protected final AverageMinMax network_req_time=new AverageMinMax(); // serialization of req until deserialization protected final AverageMinMax network_rsp_time=new AverageMinMax(); // serialization of rsp until deserialization protected final AverageMinMax req_up_time=new AverageMinMax(); // deserialization of req until dispatching to app protected final AverageMinMax rsp_up_time=new AverageMinMax(); // deserialization of rsp until after dispatching to app protected final AverageMinMax processing_time=new AverageMinMax(); // time between reception of req and sending of rsp protected void add(RTTHeader hdr) { if(hdr == null) return; long tmp; if((tmp=hdr.totalTime()) > 0) total_time.add(tmp); if((tmp=hdr.downRequest()) > 0) down_req_time.add(tmp); if((tmp=hdr.networkRequest()) > 0) network_req_time.add(tmp); if((tmp=hdr.networkResponse()) > 0) network_rsp_time.add(tmp); if((tmp=hdr.upReq()) > 0) req_up_time.add(tmp); if((tmp=hdr.processingTime()) > 0) processing_time.add(tmp); if((tmp=hdr.upRsp()) > 0) rsp_up_time.add(tmp); } public String toString() { return String.format(" total: %s\n down-req: %s\n network req: %s\n network rsp: %s\n" + " up-req: %s\n up-rsp: %s\n processing time: %s\n", total_time.toString(NANOSECONDS), down_req_time.toString(NANOSECONDS), network_req_time.toString(NANOSECONDS), network_rsp_time.toString(NANOSECONDS), req_up_time.toString(NANOSECONDS), rsp_up_time.toString(NANOSECONDS), processing_time.toString(NANOSECONDS)); } } }




© 2015 - 2024 Weber Informatics LLC | Privacy Policy