private synchronized void runWiFiRRcStatistics(TraceData.Analysis analysisData) { ProfileWiFi profile = (ProfileWiFi) analysisData.getProfile(); List<PacketInfo> packets = analysisData.getPackets(); for (RrcStateRange rrc : this.rrc) { double d = rrc.getEndTime() - rrc.getBeginTime(); double energy = profile.energy(rrc.getBeginTime(), rrc.getEndTime(), rrc.getState(), packets); this.totalRRCEnergy += energy; switch (rrc.getState()) { case WIFI_ACTIVE: wifiActiveTime += d; this.wifiActiveEnergy += energy; break; case WIFI_TAIL: wifiActiveTime += d; this.wifiActiveEnergy += energy; wifiTailTime += d; this.wifiTailEnergy += energy; break; case WIFI_IDLE: wifiIdleTime += d; this.wifiIdleEnergy += energy; break; } } long bytes = analysisData.getTotalBytes(); this.joulesPerKilobyte = bytes != 0 ? totalRRCEnergy / (bytes / 1000.0) : 0.0; }
/** * Method to calculate the maximum segment size of each packets. * * @return Set of mss values of the packets. */ private Set<Integer> calculateMssLargerPacketSizeSet() { Set<Integer> mssLargerPacketSizeSet = new HashSet<Integer>(); long totLargePkts = 0; Map<Integer, Integer> packetSizeToCountMap = analysis.getPacketSizeToCountMap(); for (Map.Entry<Integer, Integer> entry : packetSizeToCountMap.entrySet()) { Integer keyValuePacketSize = entry.getKey(); Integer valueCount = entry.getValue(); if ((keyValuePacketSize > 1000) && (valueCount > 1)) { totLargePkts += valueCount; } } if (totLargePkts > 0) { for (Map.Entry<Integer, Integer> entry : packetSizeToCountMap.entrySet()) { Integer keyValuePacketSize = entry.getKey(); Integer valueCount = entry.getValue(); if ((keyValuePacketSize > 1000) && (valueCount > 1)) { double fractionLargePkts = (double) valueCount / (double) totLargePkts; if (fractionLargePkts > 0.3f) { mssLargerPacketSizeSet.add(keyValuePacketSize); } } } } else { Integer keyValuePacketSize = 1460; mssLargerPacketSizeSet.add(keyValuePacketSize); } return mssLargerPacketSizeSet; }
/** 3G RRC state time modification. */ private synchronized void run3GRRcStatistics(TraceData.Analysis analysisData) { final Profile3G prof3g = (Profile3G) analysisData.getProfile(); List<PacketInfo> packets = analysisData.getPackets(); for (RrcStateRange rrc : this.rrc) { double energy = prof3g.energy(rrc.getBeginTime(), rrc.getEndTime(), rrc.getState(), packets); double d = rrc.getEndTime() - rrc.getBeginTime(); switch (rrc.getState()) { case STATE_IDLE: idleTime += d; this.idleEnergy += energy; break; case STATE_DCH: dchTime += d; this.dchEnergy += energy; break; case TAIL_DCH: dchTime += d; dchTailTime += d; this.dchEnergy += energy; this.dchTailEnergy += energy; break; case STATE_FACH: fachTime += d; this.fachEnergy += energy; break; case TAIL_FACH: fachTime += d; fachTailTime += d; this.fachTailEnergy += energy; this.fachEnergy += energy; break; case PROMO_IDLE_DCH: idleToDch++; idleToDchTime += d; this.idleToDchEnergy += energy; break; case PROMO_FACH_DCH: fachToDch++; fachToDchTime += d; this.fachToDchEnergy += energy; break; } } this.totalRRCEnergy = fachEnergy + dchEnergy + fachToDchEnergy + idleToDchEnergy + idleEnergy; long bytes = analysisData.getTotalBytes(); this.joulesPerKilobyte = bytes != 0 ? totalRRCEnergy / (bytes / 1000.0) : 0.0; }
/** * Getter for the payloadlength of overall packets. * * @return */ private long getPayloadLenBkg() { long r = 0; for (PacketInfo p : analysis.getPackets()) { if (p.getAppName() == null) { r += p.getPayloadLen(); } } return r; }
/** * Method orginally found in whatif.cpp * * @param packets returns timestampList - List of doubles */ private Map<PacketInfo, Double> normalizeCore(List<PacketInfo> packets) { // Step 1: Identify Promotions List<RrcStateRange> promoDelays = new ArrayList<RrcStateRange>(); for (RrcStateRange rrc : analysis.getRrcStateMachine().getRRcStateRanges()) { RRCState state = rrc.getState(); if (state == RRCState.PROMO_FACH_DCH || state == RRCState.PROMO_IDLE_DCH) promoDelays.add(rrc); } Collections.sort(promoDelays); PacketTimestamp[] timeStampList = new PacketTimestamp[packets.size()]; for (int i = 0; i < packets.size(); i++) { timeStampList[i] = new PacketTimestamp(packets.get(i)); } // Step 2: Remove all promo delays int m = promoDelays.size(); double timeStampShift = 0.0f; int j = 0; int j0 = -1; // "in-the-middle" position double middlePos = 0; // How to initialize?? for (int i = 0; i < timeStampList.length; i++) { double timeStamp = timeStampList[i].timestamp; while (j < m && timeStamp >= promoDelays.get(j).getEndTime() - EPS) { if (j0 != -1) { assert (j0 == j && i > 0 && promoDelays.get(j).getEndTime() >= middlePos); timeStampShift += promoDelays.get(j).getEndTime() - middlePos; j0 = -1; } else { timeStampShift += promoDelays.get(j).getEndTime() - promoDelays.get(j).getBeginTime(); } j++; } if (j < m && (promoDelays.get(j).getBeginTime() - EPS) < timeStamp && timeStamp < (promoDelays.get(j).getEndTime() + EPS)) { if (j0 == -1) { timeStampShift += timeStamp - promoDelays.get(j).getBeginTime(); middlePos = timeStamp; j0 = j; } else { assert (j0 == j && i > 0); assert (timeStamp >= middlePos); timeStampShift += timeStamp - middlePos; middlePos = timeStamp; } } timeStampList[i].timestamp = timeStampList[i].timestamp - timeStampShift; assert (i == 0 || timeStampList[i].timestamp >= timeStampList[i - 1].timestamp); } Map<PacketInfo, Double> result = new LinkedHashMap<PacketInfo, Double>(timeStampList.length); for (int i = 0; i < timeStampList.length; ++i) { result.put(timeStampList[i].packet, timeStampList[i].timestamp); } return result; }
/** LTE RRC state time modification. */ private synchronized void runLTERRcStatistics(TraceData.Analysis analysisData) { ProfileLTE profile = (ProfileLTE) analysisData.getProfile(); List<PacketInfo> packets = analysisData.getPackets(); for (RrcStateRange rrc : this.rrc) { double d = rrc.getEndTime() - rrc.getBeginTime(); double energy = profile.energy(rrc.getBeginTime(), rrc.getEndTime(), rrc.getState(), packets); this.totalRRCEnergy += energy; switch (rrc.getState()) { case LTE_IDLE: lteIdleTime += d; this.lteIdleEnergy += energy; break; case LTE_PROMOTION: lteIdleToCRPromotionTime += d; this.lteIdleToCRPromotionEnergy += energy; break; case LTE_CONTINUOUS: lteCrTime += d; this.lteCrEnergy += energy; break; case LTE_CR_TAIL: lteCrTime += d; lteCrTailTime += d; this.lteCrEnergy += energy; this.lteCrTailEnergy += energy; break; case LTE_DRX_SHORT: lteDrxShortTime += d; this.lteDrxShortEnergy += energy; break; case LTE_DRX_LONG: lteDrxLongTime += d; this.lteDrxLongEnergy += energy; break; } } long bytes = analysisData.getTotalBytes(); this.joulesPerKilobyte = bytes != 0 ? totalRRCEnergy / (bytes / 1000.0) : 0.0; }
/** * Initializes an instance of the BurstCollectionAnalysis class, using the specified trace * analysis data. * * @param analysis - An Analysis object containing the trace analysis data. */ public BurstCollectionAnalysis(TraceData.Analysis analysis) { this.analysis = analysis; this.profile = analysis.getProfile(); this.mss = calculateMssLargerPacketSizeSet(); groupIntoBursts(); if (this.burstCollection.size() > 0) { analyzeBursts(); computeBurstEnergyRadioResource(); diagnosisPeriodicRequest(); analyzeBurstStat(analysis); validateUnnecessaryConnections(); validatePeriodicConnections(); } }
/** * Initializes an instance of the RrcStateMachine class using the specified analysisData. * * @param analysisData The trace analysis data. */ public RRCStateMachine(TraceData.Analysis analysisData) { TimeRange timeRange = analysisData.getFilter().getTimeRange(); if (timeRange == null) { this.rrc = RrcStateRange.runTrace(analysisData); } else { this.rrc = getRRCStatesForTheTimeRange( RrcStateRange.runTrace(analysisData), timeRange.getBeginTime(), timeRange.getEndTime()); } if (logger.isLoggable(Level.FINER)) { for (RrcStateRange r : rrc) { logger.finer( r.getState() + ": " + (r.getEndTime() - r.getBeginTime()) + " " + analysisData .getProfile() .energy( r.getBeginTime(), r.getEndTime(), r.getState(), analysisData.getPackets())); } } this.packetsDuration = analysisData.getPacketsDuration(); this.traceDuration = analysisData.getTraceData().getTraceDuration(); final Profile profile = analysisData.getProfile(); if (profile instanceof Profile3G) { // Perform analysis on 3G RRC data run3GRRcStatistics(analysisData); } else if (profile instanceof ProfileLTE) { // Perform analysis on LTE RRC data runLTERRcStatistics(analysisData); } else if (profile instanceof ProfileWiFi) { // Perform analysis on LTE RRC data runWiFiRRcStatistics(analysisData); } if (logger.isLoggable(Level.FINE)) { logger.fine("===== RRC State Machine Simulation ====="); logger.fine("CELL_DCH: " + getDchTime() + "(" + (getDchTimeRatio() * 100) + "%)"); logger.fine("CELL_FACH: " + getFachTime() + "(" + (getFachTimeRatio() * 100) + "%)"); logger.fine("IDLE: " + getIdleTime() + "(" + (getIdleTimeRatio() * 100) + "%)"); logger.fine( "IDLE->DCH: " + getIdleToDchTime() + "(" + (getIdleToDchTimeRatio() * 100) + "%)"); logger.fine( "FACH->DCH: " + getFachToDchTime() + "(" + (getFachToDchTimeRatio() * 100) + "%)"); logger.fine("DCH Tail Ratio = : " + getDchTailRatio()); logger.fine("FACH Tail Ratio = : " + getFachTailRatio()); logger.fine("Promotion Ratio = : " + getPromotionRatio()); logger.fine(""); } }
/** Burst data's analyzed to categorize the periodic bursts. */ private void diagnosisPeriodicRequest() { Map<String, List<Double>> requestHost2tsList = new HashMap<String, List<Double>>(); Map<String, List<Double>> requestObj2tsList = new HashMap<String, List<Double>>(); Map<InetAddress, List<Double>> connIP2tsList = new HashMap<InetAddress, List<Double>>(); Set<String> hostPeriodicInfoSet = new HashSet<String>(); periodicCount = 0; diffPeriodicCount = 0; minimumPeriodicRepeatTime = 0.0; for (TCPSession b : analysis.getTcpSessions()) { // Get a list of timestamps of established sessions with each remote // IP PacketInfo p = b.getPackets().get(0); if (p.getTcpInfo() == TcpInfo.TCP_ESTABLISH) { List<Double> res = connIP2tsList.get(b.getRemoteIP()); if (res == null) { res = new ArrayList<Double>(); connIP2tsList.put(b.getRemoteIP(), res); } res.add(Double.valueOf(p.getTimeStamp())); } // Get a list of timestamps of HTTP requests to hosts/object names for (HttpRequestResponseInfo rr : b.getRequestResponseInfo()) { PacketInfo pkt = rr.getFirstDataPacket(); if (rr.getDirection() == HttpRequestResponseInfo.Direction.REQUEST) { Double ts0 = Double.valueOf(pkt.getTimeStamp()); if (rr.getHostName() != null) { List<Double> tempRequestHostEventList = requestHost2tsList.get(rr.getHostName()); if (tempRequestHostEventList == null) { tempRequestHostEventList = new ArrayList<Double>(); requestHost2tsList.put(rr.getHostName(), tempRequestHostEventList); } tempRequestHostEventList.add(ts0); } if (rr.getObjName() != null) { String objName = rr.getObjNameWithoutParams(); List<Double> tempRequestObjEventList = requestObj2tsList.get(objName); if (tempRequestObjEventList == null) { tempRequestObjEventList = new ArrayList<Double>(); requestObj2tsList.put(objName, tempRequestObjEventList); } tempRequestObjEventList.add(ts0); } } } } Set<String> hostList = new HashSet<String>(); for (Map.Entry<String, List<Double>> iter : requestHost2tsList.entrySet()) { if (SelfCorr(iter.getValue())) { hostList.add(iter.getKey()); } } Set<String> objList = new HashSet<String>(); for (Map.Entry<String, List<Double>> iter : requestObj2tsList.entrySet()) { if (SelfCorr(iter.getValue())) { objList.add(iter.getKey()); } } Set<InetAddress> ipList = new HashSet<InetAddress>(); for (Map.Entry<InetAddress, List<Double>> iter : connIP2tsList.entrySet()) { if (SelfCorr(iter.getValue())) { ipList.add(iter.getKey()); } } for (Burst burst : burstCollection) { if (!burst.getBurstInfos().contains(BurstInfo.BURST_CLIENT_DELAY)) { continue; } Packet beginPacket = burst.getBeginPacket().getPacket(); if (beginPacket instanceof IPPacket) { IPPacket ip = (IPPacket) beginPacket; if (ipList.contains(ip.getDestinationIPAddress()) || ipList.contains(ip.getSourceIPAddress())) { periodicCount++; burst.setBurstInfo(BurstInfo.BURST_PERIODICAL); if (ipList.contains(ip.getDestinationIPAddress())) { hostPeriodicInfoSet.add(ip.getDestinationIPAddress().toString()); } else { hostPeriodicInfoSet.add(ip.getSourceIPAddress().toString()); } continue; } } PacketInfo firstUplinkPayloadPacket = null; for (PacketInfo p : burst.getPackets()) { if (p.getDir() == Direction.UPLINK && p.getPayloadLen() > 0) { firstUplinkPayloadPacket = p; break; } } for (TCPSession session : analysis.getTcpSessions()) { for (HttpRequestResponseInfo rr : session.getRequestResponseInfo()) { if (rr.getDirection() == HttpRequestResponseInfo.Direction.REQUEST && (hostList.contains(rr.getHostName()) || objList.contains(rr.getObjNameWithoutParams()))) { if (rr.getFirstDataPacket() == firstUplinkPayloadPacket) { periodicCount++; burst.setBurstInfo(BurstInfo.BURST_PERIODICAL); burst.setFirstUplinkDataPacket(firstUplinkPayloadPacket); if (hostList.contains(rr.getHostName())) { hostPeriodicInfoSet.add(rr.getHostName()); } else { hostPeriodicInfoSet.add(rr.getObjNameWithoutParams()); } continue; } } } } } diffPeriodicCount = hostPeriodicInfoSet.size(); }
/** Method to assign the burst states. */ private void analyzeBursts() { List<UserEvent> userEvents = analysis.getUserEvents(); List<CpuActivity> cpuEvents = analysis.getCpuActivityList(); int userEventsSize = userEvents.size(); int cpuEventsSize = cpuEvents.size(); int userEventPointer = 0; int cpuPointer = 0; // Analyze each burst Burst b = null; Burst lastBurst; for (Iterator<Burst> i = burstCollection.iterator(); i.hasNext(); ) { lastBurst = b; b = i.next(); // Step 1: Remove background packets List<PacketInfo> pktIdx = new ArrayList<PacketInfo>(b.getPackets().size()); int payloadLen = 0; Set<TcpInfo> tcpInfo = new HashSet<TcpInfo>(); for (PacketInfo p : b.getPackets()) { if (p.getAppName() != null) { payloadLen += p.getPayloadLen(); pktIdx.add(p); TcpInfo tcp = p.getTcpInfo(); if (tcp != null) { tcpInfo.add(tcp); } } } if (pktIdx.size() == 0) { assert (payloadLen == 0); b.addBurstInfo(BurstInfo.BURST_BKG); continue; } PacketInfo pkt0 = pktIdx.get(0); TcpInfo info0 = pkt0.getTcpInfo(); double time0 = pkt0.getTimeStamp(); // Step 2: a long burst? if (b.getEndTime() - b.getBeginTime() > profile.getLargeBurstDuration() && payloadLen > profile.getLargeBurstSize()) { b.addBurstInfo(BurstInfo.BURST_LONG); ++longBurstCount; continue; } // Step 3: Contains no payload? if (payloadLen == 0) { if (tcpInfo.contains(TcpInfo.TCP_CLOSE)) { b.addBurstInfo(BurstInfo.BURST_FIN); } if (tcpInfo.contains(TcpInfo.TCP_ESTABLISH)) { b.addBurstInfo(BurstInfo.BURST_SYN); } if (tcpInfo.contains(TcpInfo.TCP_RESET)) { b.addBurstInfo(BurstInfo.BURST_RST); } if (tcpInfo.contains(TcpInfo.TCP_KEEP_ALIVE) || tcpInfo.contains(TcpInfo.TCP_KEEP_ALIVE_ACK)) { b.addBurstInfo(BurstInfo.BURST_KEEPALIVE); } if (tcpInfo.contains(TcpInfo.TCP_ZERO_WINDOW)) { b.addBurstInfo(BurstInfo.BURST_ZEROWIN); } if (tcpInfo.contains(TcpInfo.TCP_WINDOW_UPDATE)) { b.addBurstInfo(BurstInfo.BURST_WINUPDATE); } if (b.getBurstInfos().size() == 0 && (info0 == TcpInfo.TCP_ACK_RECOVER || info0 == TcpInfo.TCP_ACK_DUP)) { b.addBurstInfo(BurstInfo.BURST_LOSS_RECOVER); } if (b.getBurstInfos().size() > 0) continue; } // Step 4: Server delay if (pkt0.getDir() == PacketInfo.Direction.DOWNLINK && (info0 == TcpInfo.TCP_DATA || info0 == TcpInfo.TCP_ACK)) { b.addBurstInfo(BurstInfo.BURST_SERVER_DELAY); continue; } // Step 5: Loss recover if (info0 == TcpInfo.TCP_ACK_DUP || info0 == TcpInfo.TCP_DATA_DUP) { b.addBurstInfo(BurstInfo.BURST_LOSS_DUP); continue; } if (info0 == TcpInfo.TCP_DATA_RECOVER || info0 == TcpInfo.TCP_ACK_RECOVER) { b.addBurstInfo(BurstInfo.BURST_LOSS_RECOVER); continue; } // Step 6: User triggered final double USER_EVENT_SMALL_TOLERATE = profile.getUserInputTh(); if (payloadLen > 0) { UserEvent ue = null; while ((userEventPointer < userEventsSize) && ((ue = userEvents.get(userEventPointer)).getReleaseTime() < (time0 - USER_EVENT_TOLERATE))) ++userEventPointer; BurstInfo bi = ue != null ? ((ue.getEventType() == UserEventType.SCREEN_LANDSCAPE || ue.getEventType() == UserEventType.SCREEN_PORTRAIT) ? BurstInfo.BURST_SCREEN_ROTATION_INPUT : BurstInfo.BURST_USER_INPUT) : null; int j = userEventPointer; double minGap = Double.MAX_VALUE; while (j < userEventsSize) { UserEvent uEvent = userEvents.get(j); if (withinTolerate(uEvent.getPressTime(), time0)) { double gap = time0 - uEvent.getPressTime(); if (gap < minGap) { minGap = gap; } } if (withinTolerate(uEvent.getReleaseTime(), time0)) { double gap = time0 - uEvent.getReleaseTime(); if (gap < minGap) { minGap = gap; } } if (uEvent.getPressTime() > time0) { break; } j++; } if (minGap < USER_EVENT_SMALL_TOLERATE) { b.addBurstInfo(bi); continue; } else if (minGap < USER_EVENT_TOLERATE && (lastBurst == null || lastBurst.getEndTime() < b.getBeginTime() - minGap)) { double cpuBegin = time0 - minGap; double cpuEnd = time0; // Check CPU usage while (cpuPointer < cpuEventsSize) { double t = cpuEvents.get(cpuPointer).getBeginTimeStamp(); if (t < b.getBeginTime() - USER_EVENT_TOLERATE) { ++cpuPointer; } else { break; } } int k = cpuPointer; double s = 0.0f; int ns = 0; while (k < cpuEventsSize) { CpuActivity cpuAct = cpuEvents.get(k); double t = cpuAct.getBeginTimeStamp(); if (t > cpuBegin && t < cpuEnd) { s += cpuAct.getUsage(); ns++; } if (t >= cpuEnd) { break; } k++; } if (ns > 0 && (s / ns) > AVG_CPU_USAGE_THRESHOLD) { b.addBurstInfo(bi); b.addBurstInfo(BurstInfo.BURST_CPU_BUSY); continue; } } } // Step 7: Client delay if (b.getBurstInfos().size() == 0 && payloadLen == 0) { b.addBurstInfo(BurstInfo.BURST_UNKNOWN); } else { b.addBurstInfo(BurstInfo.BURST_CLIENT_DELAY); } } }
/** Computes the total burst energy. */ private void computeBurstEnergyRadioResource() { List<RrcStateRange> rrcCollection = analysis.getRrcStateMachine().getRRcStateRanges(); int rrcCount = rrcCollection.size(); if (rrcCount == 0) { return; } int p = 0; double time2 = -1; double totalEnergy = 0.0f; Iterator<Burst> iter = burstCollection.iterator(); Burst currentBurst = iter.next(); double time1 = rrcCollection.get(0).getBeginTime(); while (true) { Burst nextBurst = iter.hasNext() ? iter.next() : null; time2 = nextBurst != null ? nextBurst.getBeginTime() : rrcCollection.get(rrcCount - 1).getEndTime(); double e = 0.0f; double activeTime = 0.0f; while (p < rrcCount) { RrcStateRange rrCntrl = rrcCollection.get(p); if (rrCntrl.getEndTime() < time1) { p++; } else { if (time2 > rrCntrl.getEndTime()) { e += profile.energy( time1, rrCntrl.getEndTime(), rrCntrl.getState(), analysis.getPackets()); if ((rrCntrl.getState() == RRCState.STATE_DCH || rrCntrl.getState() == RRCState.TAIL_DCH) || (rrCntrl.getState() == RRCState.LTE_CONTINUOUS || rrCntrl.getState() == RRCState.LTE_CR_TAIL) || (rrCntrl.getState() == RRCState.WIFI_ACTIVE || rrCntrl.getState() == RRCState.WIFI_TAIL)) { activeTime += rrCntrl.getEndTime() - time1; } p++; } break; } } while (p < rrcCount) { RrcStateRange rrCntrl = rrcCollection.get(p); if (rrCntrl.getEndTime() < time2) { e += profile.energy( Math.max(rrCntrl.getBeginTime(), time1), rrCntrl.getEndTime(), rrCntrl.getState(), analysis.getPackets()); if ((rrCntrl.getState() == RRCState.STATE_DCH || rrCntrl.getState() == RRCState.TAIL_DCH) || (rrCntrl.getState() == RRCState.LTE_CONTINUOUS || rrCntrl.getState() == RRCState.LTE_CR_TAIL) || (rrCntrl.getState() == RRCState.WIFI_ACTIVE || rrCntrl.getState() == RRCState.WIFI_TAIL)) { activeTime += rrCntrl.getEndTime() - Math.max(rrCntrl.getBeginTime(), time1); } p++; } else { e += profile.energy( Math.max(rrCntrl.getBeginTime(), time1), time2, rrCntrl.getState(), analysis.getPackets()); if ((rrCntrl.getState() == RRCState.STATE_DCH || rrCntrl.getState() == RRCState.TAIL_DCH) || (rrCntrl.getState() == RRCState.LTE_CONTINUOUS || rrCntrl.getState() == RRCState.LTE_CR_TAIL) || (rrCntrl.getState() == RRCState.WIFI_ACTIVE || rrCntrl.getState() == RRCState.WIFI_TAIL)) { activeTime += time2 - Math.max(rrCntrl.getBeginTime(), time1); } break; } } currentBurst.setEnergy(e); totalEnergy += e; currentBurst.setActiveTime(activeTime); time1 = time2; if (nextBurst != null) { currentBurst = nextBurst; } else { break; } } this.totalEnergy = totalEnergy; }