| 
 | 
	
 
 
public static class MemoryDiagnosticsHelper 
{ 
public static bool isStart = false; 
static Popup popup; 
static TextBlock currentMemoryKB; 
static TextBlock currentMemoryMB; 
static TextBlock currentLumitMemoryMB; 
static DispatcherTimer timer; 
static bool forceGc; 
const long MAX_MEMORY = 90 * 1024 * 1024; // 90MB, per marketplace 
static int lastSafetyBand = -1; // to avoid needless changes of colour 
const long MAX_CHECKPOINTS = 10; // adjust as needed 
static Queue recentCheckpoints; 
static bool alreadyFailedPeak = false; // to avoid endless Asserts 
///  
/// Starts the memory diagnostic timer and shows the counter 
///  
/// The timespan between counter updates 
/// Whether or not to force a GC before collecting memory stats 
[Conditional("DEBUG")] 
public static void Start(TimeSpan timespan, bool forceGc) 
{ 
isStart = true; 
if (timer != null) throw new InvalidOperationException("Diagnostics already running"); 
MemoryDiagnosticsHelper.forceGc = forceGc; 
recentCheckpoints = new Queue(); 
StartTimer(timespan); 
ShowPopup(); 
} 
///  
/// Stops the timer and hides the counter 
///  
[Conditional("DEBUG")] 
public static void Stop() 
{ 
isStart = false; 
HidePopup(); 
StopTimer(); 
recentCheckpoints = null; 
} 
///  
/// Add a checkpoint to the system to help diagnose failures. Ignored in retail mode 
///  
/// Text to describe the most recent thing that happened 
[Conditional("DEBUG")] 
public static void Checkpoint(string text) 
{ 
if (recentCheckpoints == null) return; 
if (recentCheckpoints.Count >= MAX_CHECKPOINTS - 1) recentCheckpoints.Dequeue(); 
recentCheckpoints.Enqueue(new MemoryCheckpoint(text, GetCurrentMemoryUsage())); 
} 
///  
/// Recent checkpoints stored by the app; will always be empty in retail mode 
///  
public static IEnumerable RecentCheckpoints 
{ 
get 
{ 
if (recentCheckpoints == null) yield break; 
foreach (MemoryCheckpoint checkpoint in recentCheckpoints) yield return checkpoint; 
} 
} 
///  
/// Gets the current memory usage, in bytes. Returns zero in non-debug mode 
///  
/// Current usage 
public static long GetCurrentMemoryUsage() 
{ 
// don't use DeviceExtendedProperties for release builds (requires a capability) 
return (long)DeviceExtendedProperties.GetValue("ApplicationCurrentMemoryUsage"); 
} 
///  
/// Gets the current memory usage, in bytes. Returns zero in non-debug mode 
///  
/// Current usage 
public static long GetCurrentPeakMemoryUsage() 
{ 
// don't use DeviceExtendedProperties for release builds (requires a capability) 
return (long)DeviceExtendedProperties.GetValue("ApplicationPeakMemoryUsage"); 
} 
///  
/// Gets the peak memory usage, in bytes. Returns zero in non-debug mode 
///  
/// Peak memory usage 
public static long GetPeakMemoryUsage() 
{ 
// don't use DeviceExtendedProperties for release builds (requires a capability) 
return (long)DeviceExtendedProperties.GetValue("ApplicationPeakMemoryUsage"); 
} 
///  
/// Gets the peak memory usage, in bytes. Returns zero in non-debug mode 
///  
/// Peak memory usage 
public static long GetLumitMemoryUsage() 
{ 
// don't use DeviceExtendedProperties for release builds (requires a capability) 
return (long)DeviceExtendedProperties.GetValue("ApplicationWorkingSetLimit"); 
} 
private static void ShowPopup() 
{ 
popup = new Popup(); 
double fontSize = (double)Application.Current.Resources["PhoneFontSizeSmall"] - 2; 
Brush foreground = (Brush)Application.Current.Resources["PhoneForegroundBrush"]; 
StackPanel sp = new StackPanel { Orientation = Orientation.Horizontal, Background = (Brush)Application.Current.Resources["PhoneSemitransparentBrush"] }; 
//currentMemoryKB = new TextBlock { Text = "---", FontSize = fontSize, Foreground = new SolidColorBrush(Colors.Red)}; 
//peakMemoryBlock = new TextBlock { Text = "", FontSize = fontSize, Foreground = new SolidColorBrush(Colors.White), Margin = new Thickness(5, 0, 0, 0) }; 
//sp.Children.Add(new TextBlock { Text = " kb", FontSize = fontSize, Foreground = foreground }); 
//sp.Children.Add(currentMemoryKB); 
currentMemoryMB = new TextBlock { Text = "---", FontSize = fontSize, Foreground = new SolidColorBrush(Colors.White) }; 
currentMemoryKB = new TextBlock { Text = "---", Margin = new Thickness(10, 0, 0, 0), FontSize = fontSize, Foreground = new SolidColorBrush(Colors.Red) }; 
currentLumitMemoryMB = new TextBlock { Text = "---", Margin = new Thickness(10, 0, 0, 0), FontSize = fontSize, Foreground = new SolidColorBrush(Colors.Green) }; 
sp.Children.Add(currentMemoryMB); 
sp.Children.Add(currentMemoryKB); 
sp.Children.Add(currentLumitMemoryMB); 
sp.RenderTransform = new CompositeTransform { Rotation = 0, TranslateX = 150, TranslateY = 0, CenterX = 0, CenterY = 0 }; 
popup.Child = sp; 
popup.IsOpen = true; 
} 
private static void StartTimer(TimeSpan timespan) 
{ 
timer = new DispatcherTimer(); 
timer.Interval = timespan; 
timer.Tick += new EventHandler(timer_Tick); 
timer.Start(); 
} 
static void timer_Tick(object sender, EventArgs e) 
{ 
if (forceGc) GC.Collect(); 
UpdateCurrentMemoryUsage(); 
UpdatePeakMemoryUsage(); 
} 
private static void UpdatePeakMemoryUsage() 
{ 
if (alreadyFailedPeak) return; 
long peak = GetPeakMemoryUsage(); 
//if (peak >= MAX_MEMORY) 
//{ 
//    alreadyFailedPeak = true; 
//    Checkpoint("*MEMORY USAGE FAIL*");  
//    if (Debugger.IsAttached) Debug.Assert(false, "Peak memory condition violated"); 
//} 
} 
private static void UpdateCurrentMemoryUsage() 
{ 
try 
{ 
long mem = GetCurrentMemoryUsage(); 
long feng = GetCurrentPeakMemoryUsage(); 
long lumit = GetLumitMemoryUsage(); 
currentMemoryKB.Text = string.Format("{0:f}", feng / 1024.0 / 1024.0) + "MB"; 
currentMemoryMB.Text = string.Format("{0:f}", mem / 1024.0 / 1024.0) + "MB"; 
currentLumitMemoryMB.Text = string.Format("{0:f}", lumit / 1024.0 / 1024.0) + "MB"; 
} 
catch { } 
//int safetyBand = GetSafetyBand(mem); 
//if (safetyBand != lastSafetyBand) 
//{ 
//    currentMemoryKB.Foreground = GetBrushForSafetyBand(safetyBand); 
//    lastSafetyBand = safetyBand; 
//} 
} 
private static Brush GetBrushForSafetyBand(int safetyBand) 
{ 
return new SolidColorBrush(Colors.Red); 
//switch (safetyBand) 
//{ 
//    case 0: 
//        return new SolidColorBrush(Colors.Green); 
//    case 1: 
//        return new SolidColorBrush(Colors.Orange); 
//    default: 
//        return new SolidColorBrush(Colors.Red); 
//} 
} 
private static int GetSafetyBand(long mem) 
{ 
double percent = (double)mem / (double)MAX_MEMORY; 
if (percent |   
 
 
 
 | 
  
 |