Skip to content

Commit

Permalink
Merge pull request #1733 from riganti/handleerrors-jsonsizeanalyzer
Browse files Browse the repository at this point in the history
Handle exceptions in JsonSizeAnalyzer
  • Loading branch information
tomasherceg authored Nov 11, 2023
2 parents fcc2eb8 + 2978932 commit 767804b
Show file tree
Hide file tree
Showing 2 changed files with 39 additions and 26 deletions.
6 changes: 5 additions & 1 deletion src/Framework/Framework/Diagnostics/JsonSizeAnalyzer.cs
Original file line number Diff line number Diff line change
Expand Up @@ -48,8 +48,12 @@ AtomicSizeProfile analyzeToken(JToken token)
return new(((bool)token) ? 4 : 5);
case JTokenType.Null:
return new(4);
case JTokenType.Guid:
return new(36 + 2);
case JTokenType.Date:
return new(23 + 2);
default:
Debug.Assert(false);
Debug.Assert(false, $"Unexpected token type {token.Type}");
return new(token.ToString().Length);
}
}
Expand Down
59 changes: 34 additions & 25 deletions src/Framework/Framework/Diagnostics/PerformanceWarningTracer.cs
Original file line number Diff line number Diff line change
Expand Up @@ -15,13 +15,15 @@ namespace DotVVM.Framework.Diagnostics
public class PerformanceWarningTracer : IRequestTracer
{
private readonly RuntimeWarningCollector logger;
private readonly ILogger? tracerLogger;
private readonly DotvvmPerfWarningsConfiguration config;
private readonly JsonSizeAnalyzer jsonSizeAnalyzer;
private readonly Stopwatch stopwatch = Stopwatch.StartNew();
private readonly List<(string eventName, TimeSpan timestamp)> events = new();
public PerformanceWarningTracer(DotvvmConfiguration config, RuntimeWarningCollector logger, JsonSizeAnalyzer jsonSizeAnalyzer)
public PerformanceWarningTracer(DotvvmConfiguration config, RuntimeWarningCollector logger, JsonSizeAnalyzer jsonSizeAnalyzer, ILogger<PerformanceWarningTracer>? tracerLogger = null)
{
this.logger = logger;
this.tracerLogger = tracerLogger;
this.config = config.Diagnostics.PerfWarnings;
this.jsonSizeAnalyzer = jsonSizeAnalyzer;
}
Expand Down Expand Up @@ -57,34 +59,41 @@ void WarnLargeViewModel(long viewModelSize, IDotvvmRequestContext context)
if (context.ViewModelJson is null)
return;

var vmAnalysis = jsonSizeAnalyzer.Analyze(context.ViewModelJson);
try
{
var vmAnalysis = jsonSizeAnalyzer.Analyze(context.ViewModelJson);

var topClasses =
vmAnalysis.Classes
.OrderByDescending(c => c.Value.Size.ExclusiveSize)
.Take(3)
// only classes which have at least 5% impact
.Where(c => c.Value.Size.ExclusiveSize > vmAnalysis.TotalSize / 20)
.ToArray();
var topProperties =
vmAnalysis.Classes
.SelectMany(c => c.Value.Properties.Select(p => (Key: c.Key + "." + p.Key, p.Value)))
.OrderByDescending(c => c.Value.ExclusiveSize)
.Take(3)
// only properties which have at least 5% impact
.Where(c => c.Value.ExclusiveSize > vmAnalysis.TotalSize / 20)
.ToArray();
var topClasses =
vmAnalysis.Classes
.OrderByDescending(c => c.Value.Size.ExclusiveSize)
.Take(3)
// only classes which have at least 5% impact
.Where(c => c.Value.Size.ExclusiveSize > vmAnalysis.TotalSize / 20)
.ToArray();
var topProperties =
vmAnalysis.Classes
.SelectMany(c => c.Value.Properties.Select(p => (Key: c.Key + "." + p.Key, p.Value)))
.OrderByDescending(c => c.Value.ExclusiveSize)
.Take(3)
// only properties which have at least 5% impact
.Where(c => c.Value.ExclusiveSize > vmAnalysis.TotalSize / 20)
.ToArray();

var byteToPercent = 100.0 / vmAnalysis.TotalSize;
var byteToPercent = 100.0 / vmAnalysis.TotalSize;

var msg = $"The serialized view model has {viewModelSize / 1024.0 / 1024.0:0.0}MB, which may make your application quite slow. " +
string.Join(", ",
topProperties.Select(c => $"Property {c.Key} takes {c.Value.ExclusiveSize * byteToPercent:0}%").Concat(
topClasses.Select(c => $"Class {c.Key} takes {c.Value.Size.ExclusiveSize * byteToPercent:0}%")));
var msg = $"The serialized view model has {viewModelSize / 1024.0 / 1024.0:0.0}MB, which may make your application quite slow. " +
string.Join(", ",
topProperties.Select(c => $"Property {c.Key} takes {c.Value.ExclusiveSize * byteToPercent:0}%").Concat(
topClasses.Select(c => $"Class {c.Key} takes {c.Value.Size.ExclusiveSize * byteToPercent:0}%")));

logger.Warn(new DotvvmRuntimeWarning(
msg
));
logger.Warn(new DotvvmRuntimeWarning(
msg
));
}
catch (Exception ex)
{
tracerLogger?.LogWarning(ex, $"Failed to analyze view model size. The serialized view model has {viewModelSize / 1024.0 / 1024.0:0.0}MB, which may make your application quite slow");
}
}
public Task EndRequest(IDotvvmRequestContext context)
{
Expand Down

0 comments on commit 767804b

Please sign in to comment.