public PartialNetworkStream(MainWindow InMainWindow, List <PartialNetworkStream> InStreams, int InStartFrame, int InEndFrame, int InNameIndexUnreal, FilterValues InFilterValues, float InDeltaTime) { NameIndexUnreal = InNameIndexUnreal; FirstFrameDeltaTime = InDeltaTime; InMainWindow.ShowProgress(true); InMainWindow.UpdateProgress(0); // Merge tokens from passed in streams. for (int i = InStartFrame; i < InEndFrame; i++) { PartialNetworkStream Stream = InStreams[i]; if (i % 10 == 0) { float Percent = (float)(i - InStartFrame) / (float)(InEndFrame - InStartFrame); InMainWindow.UpdateProgress(( int )(Percent * 100)); } // Merge tokens from passed in stream based on filter criteria. foreach (var Token in Stream.Tokens) { if (Token.MatchesFilters(InFilterValues)) { Tokens.Add(Token); UpdateSummary(Token, InFilterValues); } } } InMainWindow.ShowProgress(false); EndTime += InDeltaTime; }
public void AddStream(PartialNetworkStream InStream) { // Merge tokens from passed in stream based on filter criteria. foreach (var Token in InStream.Tokens) { Tokens.Add(Token); UpdateSummary(Token, new FilterValues()); } }
/** * Constructor, duplicating the passed in stream while applying the passed in filters. * * @param InStream Stream to duplicate * @param ActorFilter Actor filter to match against * @param PropertyFilter Property filter to match against * @param RPCFilter RPC filter to match against */ public PartialNetworkStream(PartialNetworkStream InStream, string InActorFilter, string InPropertyFilter, string InRPCFilter) { NameIndexUnreal = InStream.NameIndexUnreal; FirstFrameDeltaTime = InStream.FirstFrameDeltaTime; // Merge tokens from passed in stream based on filter criteria. foreach (var Token in InStream.Tokens) { if (Token.MatchesFilters(InActorFilter, InPropertyFilter, InRPCFilter)) { Tokens.Add(Token); } } CreateSummary(NameIndexUnreal, FirstFrameDeltaTime, InActorFilter, InPropertyFilter, InRPCFilter); }
/** * Constructor, duplicating the passed in stream while applying the passed in filters. * * @param InStream Stream to duplicate * @param ActorFilter Actor filter to match against * @param PropertyFilter Property filter to match against * @param RPCFilter RPC filter to match against */ public PartialNetworkStream(PartialNetworkStream InStream, FilterValues InFilterValues) { NameIndexUnreal = InStream.NameIndexUnreal; FirstFrameDeltaTime = InStream.FirstFrameDeltaTime; // Merge tokens from passed in stream based on filter criteria. foreach (var Token in InStream.Tokens) { if (Token.MatchesFilters(InFilterValues)) { Tokens.Add(Token); } } CreateSummary(NameIndexUnreal, FirstFrameDeltaTime, InFilterValues); }
private void SelectRangeWorker(int SelectionStart, int SelectionEnd) { // Create a partial network stream with the new selection to get the summary. PartialNetworkStream Selection = new PartialNetworkStream( this, CurrentNetworkStream.Frames, SelectionStart, SelectionEnd, CurrentNetworkStream.NameIndexUnreal, CurrentFilterValues, 1 / 30.0f ); SetCurrentStreamSelection(CurrentNetworkStream, Selection, false); SelectRangeThread = null; }
public void SetCurrentStreamSelection(NetworkStream NetworkStream, PartialNetworkStream Selection, bool bSingleSelect) { if (Dispatcher.CheckAccess() == false) { Dispatcher.Invoke(new Action(() => SetCurrentStreamSelection(NetworkStream, Selection, bSingleSelect))); return; } ActorPerfPropsDetailsListView.Items.Clear(); Selection.ToActorSummaryView(NetworkStream, ActorSummaryView); Selection.ToActorPerformanceView(NetworkStream, ActorPerfPropsListView, ActorPerfPropsDetailsListView, CurrentFilterValues); // Below is way too slow for range select right now, so we just do this for single frame selection if (bSingleSelect) { Selection.ToDetailedTreeView(TokenDetailsView.Items, CurrentFilterValues); } CurrentStreamSelection = Selection; }
/** * Selection dragging on the X axis will update the summary to be current selection. */ private void NetworkChart_SelectionRangeChanged(object sender, CursorEventArgs e) { if ((CurrentNetworkStream == null) || (CurrentNetworkStream.Frames.Count == 0)) { return; } if (e.Axis.AxisName == AxisName.X) { int SelectionStart = Math.Max( 0, (int)NetworkChart.ChartAreas["DefaultChartArea"].AxisX.ScaleView.ViewMinimum); int SelectionEnd = Math.Min( CurrentNetworkStream.Frames.Count, (int)NetworkChart.ChartAreas["DefaultChartArea"].AxisX.ScaleView.ViewMaximum); // Create a partial network stream with the new selection to get the summary. PartialNetworkStream Selection = new PartialNetworkStream( CurrentNetworkStream.Frames.GetRange(SelectionStart, SelectionEnd - SelectionStart), CurrentNetworkStream.NameIndexUnreal, 1 / 30.0f); SummaryTextBox.Lines = Selection.Filter(CurrentActorFilter, CurrentPropertyFilter, CurrentRPCFilter).ToStringArray(); } }
public static void ParseStreamIntoChart(NetworkStream NetworkStream, Chart NetworkChart, string ActorFilter, string PropertyFilter, string RPCFilter) { var StartTime = DateTime.UtcNow; NetworkChart.BeginInit(); // Reset existing data. foreach (var Series in NetworkChart.Series) { Series.Points.Clear(); } NetworkChart.ResetAutoValues(); NetworkChart.Invalidate(); NetworkChart.ChartAreas[0].AxisX.ScrollBar.IsPositionedInside = false; NetworkChart.ChartAreas[0].AxisX.ScrollBar.ButtonStyle = ScrollBarButtonStyles.All; NetworkChart.ChartAreas[0].AxisX.ScrollBar.Size = 15; NetworkChart.ChartAreas[0].AxisX.ScrollBar.ButtonColor = Color.LightGray; NetworkChart.ChartAreas[0].AxisY.ScrollBar.IsPositionedInside = false; NetworkChart.ChartAreas[0].AxisY.ScrollBar.ButtonStyle = ScrollBarButtonStyles.All; NetworkChart.ChartAreas[0].AxisY.ScrollBar.Size = 15; NetworkChart.ChartAreas[0].AxisY.ScrollBar.ButtonColor = Color.LightGray; int FrameCounter = 0; foreach (PartialNetworkStream RawFrame in NetworkStream.Frames) { PartialNetworkStream Frame = RawFrame.Filter(ActorFilter, PropertyFilter, RPCFilter); if (Frame.EndTime == Frame.StartTime) { throw new InvalidOperationException(); } float OneOverDeltaTime = 1 / (Frame.EndTime - Frame.StartTime); NetworkChart.Series["ActorCount"].Points.AddXY(FrameCounter, Frame.ActorCount); NetworkChart.Series["ActorCountSec"].Points.AddXY(FrameCounter, Frame.ActorCount * OneOverDeltaTime); NetworkChart.Series["PropertyCount"].Points.AddXY(FrameCounter, Frame.PropertyCount); NetworkChart.Series["PropertyCountSec"].Points.AddXY(FrameCounter, Frame.PropertyCount * OneOverDeltaTime); NetworkChart.Series["PropertySize"].Points.AddXY(FrameCounter, Frame.ReplicatedSizeBits / 8); NetworkChart.Series["PropertySizeSec"].Points.AddXY(FrameCounter, Frame.ReplicatedSizeBits / 8 * OneOverDeltaTime); NetworkChart.Series["RPCCount"].Points.AddXY(FrameCounter, Frame.RPCCount); NetworkChart.Series["RPCCountSec"].Points.AddXY(FrameCounter, Frame.RPCCount * OneOverDeltaTime); NetworkChart.Series["RPCSize"].Points.AddXY(FrameCounter, Frame.RPCSizeBits / 8); NetworkChart.Series["RPCSizeSec"].Points.AddXY(FrameCounter, Frame.RPCSizeBits / 8 * OneOverDeltaTime); NetworkChart.Series["ExportBunchCount"].Points.AddXY(FrameCounter, Frame.ExportBunchCount); NetworkChart.Series["ExportBunchSize"].Points.AddXY(FrameCounter, Frame.ExportBunchSizeBits / 8); NetworkChart.Series["MustBeMappedGuidsCount"].Points.AddXY(FrameCounter, Frame.MustBeMappedGuidCount / 8); NetworkChart.Series["MustBeMappedGuidsSize"].Points.AddXY(FrameCounter, Frame.MustBeMappedGuidSizeBits / 8); NetworkChart.Series["SendAckCount"].Points.AddXY(FrameCounter, Frame.SendAckCount); NetworkChart.Series["SendAckCountSec"].Points.AddXY(FrameCounter, Frame.SendAckCount * OneOverDeltaTime); NetworkChart.Series["SendAckSize"].Points.AddXY(FrameCounter, Frame.SendAckSizeBits / 8); NetworkChart.Series["SendAckSizeSec"].Points.AddXY(FrameCounter, Frame.SendAckSizeBits / 8 * OneOverDeltaTime); NetworkChart.Series["ContentBlockHeaderSize"].Points.AddXY(FrameCounter, Frame.ContentBlockHeaderSizeBits / 8); NetworkChart.Series["ContentBlockFooterSize"].Points.AddXY(FrameCounter, Frame.ContentBlockFooterSizeBits / 8); NetworkChart.Series["PropertyHandleSize"].Points.AddXY(FrameCounter, Frame.PropertyHandleSizeBits / 8); NetworkChart.Series["SendBunchCount"].Points.AddXY(FrameCounter, Frame.SendBunchCount); NetworkChart.Series["SendBunchCountSec"].Points.AddXY(FrameCounter, Frame.SendBunchCount * OneOverDeltaTime); NetworkChart.Series["SendBunchSize"].Points.AddXY(FrameCounter, Frame.SendBunchSizeBits / 8); NetworkChart.Series["SendBunchSizeSec"].Points.AddXY(FrameCounter, Frame.SendBunchSizeBits / 8 * OneOverDeltaTime); NetworkChart.Series["SendBunchHeaderSize"].Points.AddXY(FrameCounter, Frame.SendBunchHeaderSizeBits / 8); NetworkChart.Series["GameSocketSendSize"].Points.AddXY(FrameCounter, Frame.UnrealSocketSize); NetworkChart.Series["GameSocketSendSizeSec"].Points.AddXY(FrameCounter, Frame.UnrealSocketSize * OneOverDeltaTime); NetworkChart.Series["GameSocketSendCount"].Points.AddXY(FrameCounter, Frame.UnrealSocketCount); NetworkChart.Series["GameSocketSendCountSec"].Points.AddXY(FrameCounter, Frame.UnrealSocketCount * OneOverDeltaTime); NetworkChart.Series["MiscSocketSendSize"].Points.AddXY(FrameCounter, Frame.OtherSocketSize); NetworkChart.Series["MiscSocketSendSizeSec"].Points.AddXY(FrameCounter, Frame.OtherSocketSize * OneOverDeltaTime); NetworkChart.Series["MiscSocketSendCount"].Points.AddXY(FrameCounter, Frame.OtherSocketCount); NetworkChart.Series["MiscSocketSendCountSec"].Points.AddXY(FrameCounter, Frame.OtherSocketCount * OneOverDeltaTime); int OutgoingBandwidth = Frame.UnrealSocketSize + Frame.OtherSocketSize + NetworkStream.PacketOverhead * (Frame.UnrealSocketCount + Frame.OtherSocketCount); NetworkChart.Series["OutgoingBandwidthSize"].Points.AddXY(FrameCounter, OutgoingBandwidth); NetworkChart.Series["OutgoingBandwidthSizeSec"].Points.AddXY(FrameCounter, OutgoingBandwidth * OneOverDeltaTime); NetworkChart.Series["ActorReplicateTimeInMS"].Points.AddXY(FrameCounter, Frame.ActorReplicateTimeInMS); if (Frame.NumEvents > 0) { NetworkChart.Series["Events"].Points.AddXY(FrameCounter, 0); } FrameCounter++; } NetworkChart.DataManipulator.FinancialFormula(FinancialFormula.MovingAverage, "30", "GameSocketSendSizeSec", "GameSocketSendSizeAvgSec"); NetworkChart.DataManipulator.FinancialFormula(FinancialFormula.MovingAverage, "30", "OutgoingBandwidthSizeSec", "OutgoingBandwidthSizeAvgSec"); NetworkChart.ChartAreas["DefaultChartArea"].RecalculateAxesScale(); NetworkChart.EndInit(); Console.WriteLine("Adding data to chart took {0} seconds", (DateTime.UtcNow - StartTime).TotalSeconds); }
public static void ParseStreamIntoChart(MainWindow InMainWindow, NetworkStream NetworkStream, Chart NetworkChart, FilterValues InFilterValues) { var StartTime = DateTime.UtcNow; InMainWindow.ShowProgress(true); // Save old scroll position double OldPosition = NetworkChart.ChartAreas["DefaultChartArea"].AxisX.ScaleView.Position; NetworkChart.BeginInit(); // Reset existing data. for (int i = 0; i < NetworkChart.Series.Count; i++) { float Percent = ( float )i / ( float )NetworkChart.Series.Count; InMainWindow.UpdateProgress(( int )(Percent * 100)); NetworkChart.Series[i].Points.Clear(); } InMainWindow.ShowProgress(true); NetworkChart.ResetAutoValues(); NetworkChart.Invalidate(); NetworkChart.ChartAreas[0].AxisX.ScrollBar.IsPositionedInside = false; NetworkChart.ChartAreas[0].AxisX.ScrollBar.ButtonStyle = ScrollBarButtonStyles.All; NetworkChart.ChartAreas[0].AxisX.ScrollBar.Size = 15; NetworkChart.ChartAreas[0].AxisX.ScrollBar.ButtonColor = Color.LightGray; NetworkChart.ChartAreas[0].AxisY.ScrollBar.IsPositionedInside = false; NetworkChart.ChartAreas[0].AxisY.ScrollBar.ButtonStyle = ScrollBarButtonStyles.All; NetworkChart.ChartAreas[0].AxisY.ScrollBar.Size = 15; NetworkChart.ChartAreas[0].AxisY.ScrollBar.ButtonColor = Color.LightGray; int FrameCounter = 0; foreach (PartialNetworkStream RawFrame in NetworkStream.Frames) { if (FrameCounter % 1000 == 0) { float Percent = ( float )FrameCounter / ( float )NetworkStream.Frames.Count; InMainWindow.UpdateProgress(( int )(Percent * 100)); } PartialNetworkStream Frame = RawFrame.Filter(InFilterValues); if (Frame.EndTime == Frame.StartTime) { throw new InvalidOperationException(); } float OneOverDeltaTime = 1 / (Frame.EndTime - Frame.StartTime); int OutgoingBandwidth = Frame.UnrealSocketSize + Frame.OtherSocketSize + NetworkStream.PacketOverhead * (Frame.UnrealSocketCount + Frame.OtherSocketCount); InMainWindow.AddChartPoint(SeriesType.OutgoingBandwidthSize, FrameCounter, OutgoingBandwidth); InMainWindow.AddChartPoint(SeriesType.OutgoingBandwidthSizeSec, FrameCounter, OutgoingBandwidth * OneOverDeltaTime); InMainWindow.AddChartPoint(SeriesType.ActorCount, FrameCounter, Frame.ActorCount); InMainWindow.AddChartPoint(SeriesType.PropertySize, FrameCounter, Frame.ReplicatedSizeBits / 8); InMainWindow.AddChartPoint(SeriesType.PropertySizeSec, FrameCounter, Frame.ReplicatedSizeBits / 8 * OneOverDeltaTime); InMainWindow.AddChartPoint(SeriesType.RPCSize, FrameCounter, Frame.RPCSizeBits / 8); InMainWindow.AddChartPoint(SeriesType.RPCSizeSec, FrameCounter, Frame.RPCSizeBits / 8 * OneOverDeltaTime); #if true InMainWindow.AddChartPoint(SeriesType.ActorCountSec, FrameCounter, Frame.ActorCount * OneOverDeltaTime); InMainWindow.AddChartPoint(SeriesType.PropertyCount, FrameCounter, Frame.PropertyCount); InMainWindow.AddChartPoint(SeriesType.PropertyCountSec, FrameCounter, Frame.PropertyCount * OneOverDeltaTime); InMainWindow.AddChartPoint(SeriesType.RPCCount, FrameCounter, Frame.RPCCount); InMainWindow.AddChartPoint(SeriesType.RPCCountSec, FrameCounter, Frame.RPCCount * OneOverDeltaTime); InMainWindow.AddChartPoint(SeriesType.ExportBunchCount, FrameCounter, Frame.ExportBunchCount); InMainWindow.AddChartPoint(SeriesType.ExportBunchSize, FrameCounter, Frame.ExportBunchSizeBits / 8); InMainWindow.AddChartPoint(SeriesType.MustBeMappedGuidsCount, FrameCounter, Frame.MustBeMappedGuidCount / 8); InMainWindow.AddChartPoint(SeriesType.MustBeMappedGuidsSize, FrameCounter, Frame.MustBeMappedGuidSizeBits / 8); InMainWindow.AddChartPoint(SeriesType.SendAckCount, FrameCounter, Frame.SendAckCount); InMainWindow.AddChartPoint(SeriesType.SendAckCountSec, FrameCounter, Frame.SendAckCount * OneOverDeltaTime); InMainWindow.AddChartPoint(SeriesType.SendAckSize, FrameCounter, Frame.SendAckSizeBits / 8); InMainWindow.AddChartPoint(SeriesType.SendAckSizeSec, FrameCounter, Frame.SendAckSizeBits / 8 * OneOverDeltaTime); InMainWindow.AddChartPoint(SeriesType.ContentBlockHeaderSize, FrameCounter, Frame.ContentBlockHeaderSizeBits / 8); InMainWindow.AddChartPoint(SeriesType.ContentBlockFooterSize, FrameCounter, Frame.ContentBlockFooterSizeBits / 8); InMainWindow.AddChartPoint(SeriesType.PropertyHandleSize, FrameCounter, Frame.PropertyHandleSizeBits / 8); InMainWindow.AddChartPoint(SeriesType.SendBunchCount, FrameCounter, Frame.SendBunchCount); InMainWindow.AddChartPoint(SeriesType.SendBunchCountSec, FrameCounter, Frame.SendBunchCount * OneOverDeltaTime); InMainWindow.AddChartPoint(SeriesType.SendBunchSize, FrameCounter, Frame.SendBunchSizeBits / 8); InMainWindow.AddChartPoint(SeriesType.SendBunchSizeSec, FrameCounter, Frame.SendBunchSizeBits / 8 * OneOverDeltaTime); InMainWindow.AddChartPoint(SeriesType.SendBunchHeaderSize, FrameCounter, Frame.SendBunchHeaderSizeBits / 8); InMainWindow.AddChartPoint(SeriesType.GameSocketSendSize, FrameCounter, Frame.UnrealSocketSize); InMainWindow.AddChartPoint(SeriesType.GameSocketSendSizeSec, FrameCounter, Frame.UnrealSocketSize * OneOverDeltaTime); InMainWindow.AddChartPoint(SeriesType.GameSocketSendCount, FrameCounter, Frame.UnrealSocketCount); InMainWindow.AddChartPoint(SeriesType.GameSocketSendCountSec, FrameCounter, Frame.UnrealSocketCount * OneOverDeltaTime); InMainWindow.AddChartPoint(SeriesType.ActorReplicateTimeInMS, FrameCounter, Frame.ActorReplicateTimeInMS); #endif #if false InMainWindow.AddChartPoint(SeriesType.MiscSocketSendSize, FrameCounter, Frame.OtherSocketSize); InMainWindow.AddChartPoint(SeriesType.MiscSocketSendSizeSec, FrameCounter, Frame.OtherSocketSize * OneOverDeltaTime); InMainWindow.AddChartPoint(SeriesType.MiscSocketSendCount, FrameCounter, Frame.OtherSocketCount); InMainWindow.AddChartPoint(SeriesType.MiscSocketSendCountSec, FrameCounter, Frame.OtherSocketCount * OneOverDeltaTime); #endif if (Frame.NumEvents > 0) { InMainWindow.AddChartPoint(SeriesType.Events, FrameCounter, 0); } FrameCounter++; } //NetworkChart.DataManipulator.FinancialFormula( FinancialFormula.MovingAverage, "30", SeriesType.GameSocketSendSizeSec, SeriesType.GameSocketSendSizeAvgSec ); NetworkChart.DataManipulator.FinancialFormula(FinancialFormula.MovingAverage, "30", SeriesType.OutgoingBandwidthSizeSec.ToString(), SeriesType.OutgoingBandwidthSizeAvgSec.ToString()); NetworkChart.ChartAreas["DefaultChartArea"].RecalculateAxesScale(); NetworkChart.ChartAreas["DefaultChartArea"].AxisX.ScaleView.Position = OldPosition; NetworkChart.EndInit(); InMainWindow.ShowProgress(false); Console.WriteLine("Adding data to chart took {0} seconds", (DateTime.UtcNow - StartTime).TotalSeconds); }
/** * Parses passed in data stream into a network stream container class * * @param ParserStream Raw data stream, needs to support seeking * @return NetworkStream data was parsed into */ public static NetworkStream Parse(Stream ParserStream) { var StartTime = DateTime.UtcNow; // Network stream the file is parsed into. NetworkStream NetworkStream = new NetworkStream(); // Serialize the header. This will also return an endian-appropriate binary reader to // be used for reading the data. BinaryReader BinaryStream = null; var Header = StreamHeader.ReadHeader(ParserStream, out BinaryStream); // Keep track of token stream offset as name table is at end of file. long TokenStreamOffset = ParserStream.Position; // Seek to name table and serialize it. ParserStream.Seek(Header.NameTableOffset, SeekOrigin.Begin); for (int NameIndex = 0; NameIndex < Header.NameTableEntries; NameIndex++) { UInt32 Length = BinaryStream.ReadUInt32(); NetworkStream.NameArray.Add(new string(BinaryStream.ReadChars((int)Length))); // Find "Unreal" name index used for misc socket parsing optimizations. if (NetworkStream.NameArray[NameIndex] == "Unreal") { NetworkStream.NameIndexUnreal = NameIndex; } } // Seek to beginning of token stream. ParserStream.Seek(TokenStreamOffset, SeekOrigin.Begin); // Scratch variables used for building stream. Required as we emit information in reverse // order needed for parsing. var CurrentFrameTokens = new List <TokenBase>(); TokenReplicateActor LastActorToken = null; List <TokenReplicateProperty> LastProperties = new List <TokenReplicateProperty>(); List <TokenWritePropertyHeader> LastPropertyHeaders = new List <TokenWritePropertyHeader>(); TokenFrameMarker LastFrameMarker = null; // Parse stream till we reach the end, marked by special token. bool bHasReachedEndOfStream = false; while (bHasReachedEndOfStream == false) { TokenBase Token = TokenBase.ReadNextToken(BinaryStream, NetworkStream); // Convert current tokens to frame if we reach a frame boundary or the end of the stream. if (((Token.TokenType == ETokenTypes.FrameMarker) || (Token.TokenType == ETokenTypes.EndOfStreamMarker)) // Nothing to do if we don't have any tokens, e.g. first frame. && (CurrentFrameTokens.Count > 0)) { // Figure out delta time of previous frame. Needed as partial network stream lacks relative // information for last frame. We assume 30Hz for last frame and for the first frame in case // we receive network traffic before the first frame marker. float DeltaTime = 1 / 30.0f; if (Token.TokenType == ETokenTypes.FrameMarker && LastFrameMarker != null) { DeltaTime = ((TokenFrameMarker)Token).RelativeTime - LastFrameMarker.RelativeTime; } // Create per frame partial stream and add it to the full stream. var FrameStream = new PartialNetworkStream(CurrentFrameTokens, NetworkStream.NameIndexUnreal, DeltaTime); NetworkStream.Frames.Add(FrameStream); CurrentFrameTokens.Clear(); Debug.Assert(LastProperties.Count == 0); // We shouldn't have any properties now Debug.Assert(LastPropertyHeaders.Count == 0); // We shouldn't have any property headers now either // Finish up actor summary of last pending actor before switching frames. HandleActorSummary(NetworkStream, LastActorToken); LastActorToken = null; } // Keep track of last frame marker. if (Token.TokenType == ETokenTypes.FrameMarker) { LastFrameMarker = (TokenFrameMarker)Token; } // Bail out if we hit the end. We already flushed tokens above. if (Token.TokenType == ETokenTypes.EndOfStreamMarker) { Debug.Assert(LastProperties.Count == 0); // We shouldn't have any properties now Debug.Assert(LastPropertyHeaders.Count == 0); // We shouldn't have any property headers now either bHasReachedEndOfStream = true; // Finish up actor summary of last pending actor at end of stream HandleActorSummary(NetworkStream, LastActorToken); } // Keep track of per frame tokens. else { // Keep track of last actor context for property replication. if (Token.TokenType == ETokenTypes.ReplicateActor) { // Encountered a new actor so we can finish up existing one for summary. FinishActorProperties(Token as TokenReplicateActor, LastProperties, LastPropertyHeaders); Debug.Assert(LastProperties.Count == 0); // We shouldn't have any properties now Debug.Assert(LastPropertyHeaders.Count == 0); // We shouldn't have any property headers now either HandleActorSummary(NetworkStream, LastActorToken); LastActorToken = Token as TokenReplicateActor; } // Keep track of RPC summary else if (Token.TokenType == ETokenTypes.SendRPC) { var TokenSendRPC = Token as TokenSendRPC; NetworkStream.UpdateSummary(ref NetworkStream.RPCNameToSummary, TokenSendRPC.FunctionNameIndex, TokenSendRPC.GetNumTotalBits(), 0.0f); } // Add properties to the actor token instead of network stream and keep track of summary. if (Token.TokenType == ETokenTypes.ReplicateProperty) { var TokenReplicateProperty = Token as TokenReplicateProperty; NetworkStream.UpdateSummary(ref NetworkStream.PropertyNameToSummary, TokenReplicateProperty.PropertyNameIndex, TokenReplicateProperty.NumBits, 0); //LastActorToken.Properties.Add(TokenReplicateProperty); LastProperties.Add(TokenReplicateProperty); } else if (Token.TokenType == ETokenTypes.WritePropertyHeader) { var TokenWritePropertyHeader = Token as TokenWritePropertyHeader; LastPropertyHeaders.Add(TokenWritePropertyHeader); } else { CurrentFrameTokens.Add(Token); } } } // Stats for profiling. double ParseTime = (DateTime.UtcNow - StartTime).TotalSeconds; Console.WriteLine("Parsing {0} MBytes in stream took {1} seconds", ParserStream.Length / 1024 / 1024, ParseTime); // Empty stream will have 0 frames and proper name table. Shouldn't happen as we only // write out stream in engine if there are any events. return(NetworkStream); }
/** * Parses passed in data stream into a network stream container class * * @param ParserStream Raw data stream, needs to support seeking * @return NetworkStream data was parsed into */ public static NetworkStream Parse(MainWindow InMainWindow, Stream ParserStream) { var StartTime = DateTime.UtcNow; // Network stream the file is parsed into. NetworkStream = new NetworkStream(); // Serialize the header. This will also return an endian-appropriate binary reader to // be used for reading the data. BinaryReader BinaryStream = null; var Header = StreamHeader.ReadHeader(ParserStream, out BinaryStream); // Scratch variables used for building stream. Required as we emit information in reverse // order needed for parsing. var CurrentFrameTokens = new List <TokenBase>(); TokenReplicateActor LastActorToken = null; List <TokenReplicateProperty> LastProperties = new List <TokenReplicateProperty>(); List <TokenWritePropertyHeader> LastPropertyHeaders = new List <TokenWritePropertyHeader>(); TokenFrameMarker LastFrameMarker = null; InMainWindow.ShowProgress(true); int Count = 0; var AllFrames = new PartialNetworkStream(NetworkStream.NameIndexUnreal, 1.0f / 30.0f); int EarlyOutMinutes = InMainWindow.GetMaxProfileMinutes(); // Parse stream till we reach the end, marked by special token. bool bHasReachedEndOfStream = false; List <TokenBase> TokenList = new List <TokenBase>(); float FrameStartTime = -1.0f; float FrameEndTime = -1.0f; while (bHasReachedEndOfStream == false) { if (Count++ % 1000 == 0) { float Percent = ( float )ParserStream.Position / ( float )ParserStream.Length; InMainWindow.UpdateProgress(( int )(Percent * 100)); } if (ParserStream.Position == ParserStream.Length) { // We reached stream early (must not have been finalized properly, but we can still read it) break; } TokenBase Token = null; try { Token = TokenBase.ReadNextToken(BinaryStream, NetworkStream); } catch (System.IO.EndOfStreamException) { // We reached stream early (must not have been finalized properly, but we can still read it) break; } if (Token.TokenType == ETokenTypes.NameReference) { NetworkStream.NameArray.Add((Token as TokenNameReference).Name); // Find "Unreal" name index used for misc socket parsing optimizations. if (NetworkStream.NameArray[NetworkStream.NameArray.Count - 1] == "Unreal") { NetworkStream.NameIndexUnreal = NetworkStream.NameArray.Count - 1; } continue; } if (Token.TokenType == ETokenTypes.ConnectionReference) { NetworkStream.AddressArray.Add((Token as TokenConnectionReference).Address); continue; } if (Token.TokenType == ETokenTypes.ConnectionChange) { // We need to setup CurrentConnectionIndex, since it's used in ReadNextToken NetworkStream.CurrentConnectionIndex = (Token as TokenConnectionChanged).AddressIndex; continue; } TokenList.Add(Token); // Track frame start/end times manually so we can bail out when we hit the amount of time we want to load if (Token.TokenType == ETokenTypes.FrameMarker) { var TokenFrameMarker = ( TokenFrameMarker )Token; if (FrameStartTime < 0) { FrameStartTime = TokenFrameMarker.RelativeTime; FrameEndTime = TokenFrameMarker.RelativeTime; } else { FrameEndTime = TokenFrameMarker.RelativeTime; } } if (EarlyOutMinutes > 0 && ((FrameEndTime - FrameStartTime) > 60 * EarlyOutMinutes)) { break; } } for (int i = 0; i < TokenList.Count; i++) { if (i % 1000 == 0) { float Percent = ( float )(i + 1) / ( float )(TokenList.Count); InMainWindow.UpdateProgress(( int )(Percent * 100)); } TokenBase Token = TokenList[i]; // Convert current tokens to frame if we reach a frame boundary or the end of the stream. if (((Token.TokenType == ETokenTypes.FrameMarker) || (Token.TokenType == ETokenTypes.EndOfStreamMarker)) // Nothing to do if we don't have any tokens, e.g. first frame. && (CurrentFrameTokens.Count > 0)) { // Figure out delta time of previous frame. Needed as partial network stream lacks relative // information for last frame. We assume 30Hz for last frame and for the first frame in case // we receive network traffic before the first frame marker. float DeltaTime = 1 / 30.0f; if (Token.TokenType == ETokenTypes.FrameMarker && LastFrameMarker != null) { DeltaTime = ((TokenFrameMarker)Token).RelativeTime - LastFrameMarker.RelativeTime; } // Create per frame partial stream and add it to the full stream. var FrameStream = new PartialNetworkStream(CurrentFrameTokens, NetworkStream.NameIndexUnreal, DeltaTime); AllFrames.AddStream(FrameStream); NetworkStream.Frames.Add(FrameStream); CurrentFrameTokens.Clear(); Debug.Assert(LastProperties.Count == 0); // We shouldn't have any properties now Debug.Assert(LastPropertyHeaders.Count == 0); // We shouldn't have any property headers now either // Finish up actor summary of last pending actor before switching frames. HandleActorSummary(NetworkStream, LastActorToken); LastActorToken = null; } // Keep track of last frame marker. if (Token.TokenType == ETokenTypes.FrameMarker) { LastFrameMarker = (TokenFrameMarker)Token; } // Bail out if we hit the end. We already flushed tokens above. if (Token.TokenType == ETokenTypes.EndOfStreamMarker) { Debug.Assert(LastProperties.Count == 0); // We shouldn't have any properties now Debug.Assert(LastPropertyHeaders.Count == 0); // We shouldn't have any property headers now either bHasReachedEndOfStream = true; // Finish up actor summary of last pending actor at end of stream HandleActorSummary(NetworkStream, LastActorToken); } // Keep track of per frame tokens. else { // Keep track of last actor context for property replication. if (Token.TokenType == ETokenTypes.ReplicateActor) { // Encountered a new actor so we can finish up existing one for summary. FinishActorProperties(Token as TokenReplicateActor, LastProperties, LastPropertyHeaders); Debug.Assert(LastProperties.Count == 0); // We shouldn't have any properties now Debug.Assert(LastPropertyHeaders.Count == 0); // We shouldn't have any property headers now either HandleActorSummary(NetworkStream, LastActorToken); LastActorToken = Token as TokenReplicateActor; } // Keep track of RPC summary else if (Token.TokenType == ETokenTypes.SendRPC) { var TokenSendRPC = Token as TokenSendRPC; NetworkStream.UpdateSummary(ref NetworkStream.RPCNameToSummary, TokenSendRPC.FunctionNameIndex, TokenSendRPC.GetNumTotalBits(), 0.0f); } // Add properties to the actor token instead of network stream and keep track of summary. if (Token.TokenType == ETokenTypes.ReplicateProperty) { var TokenReplicateProperty = Token as TokenReplicateProperty; NetworkStream.UpdateSummary(ref NetworkStream.PropertyNameToSummary, TokenReplicateProperty.PropertyNameIndex, TokenReplicateProperty.NumBits, 0); //LastActorToken.Properties.Add(TokenReplicateProperty); LastProperties.Add(TokenReplicateProperty); } else if (Token.TokenType == ETokenTypes.WritePropertyHeader) { var TokenWritePropertyHeader = Token as TokenWritePropertyHeader; LastPropertyHeaders.Add(TokenWritePropertyHeader); } else { CurrentFrameTokens.Add(Token); } } } InMainWindow.SetCurrentStreamSelection(NetworkStream, AllFrames, false); InMainWindow.ShowProgress(false); // Stats for profiling. double ParseTime = (DateTime.UtcNow - StartTime).TotalSeconds; Console.WriteLine("Parsing {0} MBytes in stream took {1} seconds", ParserStream.Length / 1024 / 1024, ParseTime); // Empty stream will have 0 frames and proper name table. Shouldn't happen as we only // write out stream in engine if there are any events. return(NetworkStream); }
public static void ParseStreamIntoChart(MainWindow InMainWindow, NetworkStream InStream, WpfPlot NetworkChart, FilterValues InFilterValues) { var StartTime = DateTime.UtcNow; InMainWindow.ShowProgress(true); NetworkChart.Plot.Clear(); for (int i = 0; i < InMainWindow.DefaultSeriesTypes.Count; i++) { float Percent = (float)i / (float)InMainWindow.DefaultSeriesTypes.Count; InMainWindow.UpdateProgress((int)(Percent * 100)); InMainWindow.DefaultSeriesTypes[i].Reset(); } int FrameCounter = 0; foreach (PartialNetworkStream RawFrame in InStream.Frames) { if (FrameCounter % 1000 == 0) { float Percent = (float)FrameCounter / (float)InStream.Frames.Count; InMainWindow.UpdateProgress((int)(Percent * 100)); } PartialNetworkStream Frame = RawFrame.Filter(InFilterValues); if (Frame.EndTime == Frame.StartTime) { throw new InvalidOperationException("End time and Start time cannot be same."); } float OneOverDeltaTime = 1 / (Frame.EndTime - Frame.StartTime); int OutgoingBandwidth = Frame.UnrealSocketSize + Frame.OtherSocketSize + NetworkStream.PacketOverhead * (Frame.UnrealSocketCount + Frame.OtherSocketCount); InMainWindow.AddChartPoint(SeriesType.OutgoingBandwidthSize, FrameCounter, OutgoingBandwidth); InMainWindow.AddChartPoint(SeriesType.OutgoingBandwidthSizeSec, FrameCounter, OutgoingBandwidth * OneOverDeltaTime); InMainWindow.AddChartPoint(SeriesType.ActorCount, FrameCounter, Frame.ActorCount); InMainWindow.AddChartPoint(SeriesType.PropertySize, FrameCounter, Frame.ReplicatedSizeBits / 8); InMainWindow.AddChartPoint(SeriesType.PropertySizeSec, FrameCounter, Frame.ReplicatedSizeBits / 8 * OneOverDeltaTime); InMainWindow.AddChartPoint(SeriesType.RPCSize, FrameCounter, Frame.RPCSizeBits / 8); InMainWindow.AddChartPoint(SeriesType.RPCSizeSec, FrameCounter, Frame.RPCSizeBits / 8 * OneOverDeltaTime); #if true InMainWindow.AddChartPoint(SeriesType.ActorCountSec, FrameCounter, Frame.ActorCount * OneOverDeltaTime); InMainWindow.AddChartPoint(SeriesType.PropertyCount, FrameCounter, Frame.PropertyCount); InMainWindow.AddChartPoint(SeriesType.PropertyCountSec, FrameCounter, Frame.PropertyCount * OneOverDeltaTime); InMainWindow.AddChartPoint(SeriesType.RPCCount, FrameCounter, Frame.RPCCount); InMainWindow.AddChartPoint(SeriesType.RPCCountSec, FrameCounter, Frame.RPCCount * OneOverDeltaTime); InMainWindow.AddChartPoint(SeriesType.ExportBunchCount, FrameCounter, Frame.ExportBunchCount); InMainWindow.AddChartPoint(SeriesType.ExportBunchSize, FrameCounter, Frame.ExportBunchSizeBits / 8); InMainWindow.AddChartPoint(SeriesType.MustBeMappedGuidsCount, FrameCounter, Frame.MustBeMappedGuidCount / 8); InMainWindow.AddChartPoint(SeriesType.MustBeMappedGuidsSize, FrameCounter, Frame.MustBeMappedGuidSizeBits / 8); InMainWindow.AddChartPoint(SeriesType.SendAckCount, FrameCounter, Frame.SendAckCount); InMainWindow.AddChartPoint(SeriesType.SendAckCountSec, FrameCounter, Frame.SendAckCount * OneOverDeltaTime); InMainWindow.AddChartPoint(SeriesType.SendAckSize, FrameCounter, Frame.SendAckSizeBits / 8); InMainWindow.AddChartPoint(SeriesType.SendAckSizeSec, FrameCounter, Frame.SendAckSizeBits / 8 * OneOverDeltaTime); InMainWindow.AddChartPoint(SeriesType.ContentBlockHeaderSize, FrameCounter, Frame.ContentBlockHeaderSizeBits / 8); InMainWindow.AddChartPoint(SeriesType.ContentBlockFooterSize, FrameCounter, Frame.ContentBlockFooterSizeBits / 8); InMainWindow.AddChartPoint(SeriesType.PropertyHandleSize, FrameCounter, Frame.PropertyHandleSizeBits / 8); InMainWindow.AddChartPoint(SeriesType.SendBunchCount, FrameCounter, Frame.SendBunchCount); InMainWindow.AddChartPoint(SeriesType.SendBunchCountSec, FrameCounter, Frame.SendBunchCount * OneOverDeltaTime); InMainWindow.AddChartPoint(SeriesType.SendBunchSize, FrameCounter, Frame.SendBunchSizeBits / 8); InMainWindow.AddChartPoint(SeriesType.SendBunchSizeSec, FrameCounter, Frame.SendBunchSizeBits / 8 * OneOverDeltaTime); InMainWindow.AddChartPoint(SeriesType.SendBunchHeaderSize, FrameCounter, Frame.SendBunchHeaderSizeBits / 8); InMainWindow.AddChartPoint(SeriesType.GameSocketSendSize, FrameCounter, Frame.UnrealSocketSize); InMainWindow.AddChartPoint(SeriesType.GameSocketSendSizeSec, FrameCounter, Frame.UnrealSocketSize * OneOverDeltaTime); InMainWindow.AddChartPoint(SeriesType.GameSocketSendCount, FrameCounter, Frame.UnrealSocketCount); InMainWindow.AddChartPoint(SeriesType.GameSocketSendCountSec, FrameCounter, Frame.UnrealSocketCount * OneOverDeltaTime); InMainWindow.AddChartPoint(SeriesType.ActorReplicateTimeInMS, FrameCounter, Frame.ActorReplicateTimeInMS); #endif #if false InMainWindow.AddChartPoint(SeriesType.MiscSocketSendSize, FrameCounter, Frame.OtherSocketSize); InMainWindow.AddChartPoint(SeriesType.MiscSocketSendSizeSec, FrameCounter, Frame.OtherSocketSize * OneOverDeltaTime); InMainWindow.AddChartPoint(SeriesType.MiscSocketSendCount, FrameCounter, Frame.OtherSocketCount); InMainWindow.AddChartPoint(SeriesType.MiscSocketSendCountSec, FrameCounter, Frame.OtherSocketCount * OneOverDeltaTime); #endif if (Frame.NumEvents > 0) { InMainWindow.AddChartPoint(SeriesType.Events, FrameCounter, 0); } FrameCounter++; } InMainWindow.ShowProgress(false); Console.WriteLine("Adding data to chart took {0} seconds", (DateTime.UtcNow - StartTime).TotalSeconds); InMainWindow.Dispatcher.Invoke(new Action(() => InMainWindow.UpdateNetworkChart())); }