33using BenchmarkDotNet . Environments ;
44using BenchmarkDotNet . Loggers ;
55using BenchmarkDotNet . Reports ;
6+ using Perfolizer . Horology ;
67using JsonSerializer = SimpleJson . SimpleJson ;
78
89namespace BenchmarkDotNet . Exporters . Json
@@ -21,53 +22,71 @@ protected JsonExporterBase(bool indentJson = false, bool excludeMeasurements = f
2122 }
2223
2324 public override void ExportToLog ( Summary summary , ILogger logger )
25+ {
26+ JsonSerializer . CurrentJsonSerializerStrategy . Indent = IndentJson ;
27+ logger . WriteLine ( JsonSerializer . SerializeObject ( GetDataToSerialize ( summary ) ) ) ;
28+ }
29+
30+ protected virtual IReadOnlyDictionary < string , object > GetDataToSerialize ( Summary summary )
31+ {
32+ // If we just ask SimpleJson to serialize the entire "summary" object it throws several errors.
33+ // So we are more specific in what we serialize (plus some fields/properties aren't relevant)
34+ return new Dictionary < string , object >
35+ {
36+ { "Title" , summary . Title } ,
37+ { "HostEnvironmentInfo" , GetDataToSerialize ( summary . HostEnvironmentInfo ) } ,
38+ { "Benchmarks" , summary . Reports . Select ( GetDataToSerialize ) }
39+ } ;
40+ }
41+
42+ protected virtual IReadOnlyDictionary < string , object > GetDataToSerialize ( HostEnvironmentInfo environmentInfo )
2443 {
2544 // We construct HostEnvironmentInfo manually, so that we can have the HardwareTimerKind enum as text, rather than an integer
2645 // SimpleJson serializer doesn't seem to have an enum String/Value option (to-be-fair, it is meant to be "Simple")
27- var environmentInfo = new
46+ return new Dictionary < string , object >
2847 {
29- HostEnvironmentInfo . BenchmarkDotNetCaption ,
30- summary . HostEnvironmentInfo . BenchmarkDotNetVersion ,
31- OsVersion = summary . HostEnvironmentInfo . OsVersion . Value ,
32- ProcessorName = ProcessorBrandStringHelper . Prettify ( summary . HostEnvironmentInfo . CpuInfo . Value ) ,
33- summary . HostEnvironmentInfo . CpuInfo . Value ? . PhysicalProcessorCount ,
34- summary . HostEnvironmentInfo . CpuInfo . Value ? . PhysicalCoreCount ,
35- summary . HostEnvironmentInfo . CpuInfo . Value ? . LogicalCoreCount ,
36- summary . HostEnvironmentInfo . RuntimeVersion ,
37- summary . HostEnvironmentInfo . Architecture ,
38- summary . HostEnvironmentInfo . HasAttachedDebugger ,
39- summary . HostEnvironmentInfo . HasRyuJit ,
40- summary . HostEnvironmentInfo . Configuration ,
41- DotNetCliVersion = summary . HostEnvironmentInfo . DotNetSdkVersion . Value ,
42- summary . HostEnvironmentInfo . ChronometerFrequency ,
43- HardwareTimerKind = summary . HostEnvironmentInfo . HardwareTimerKind . ToString ( )
48+ { nameof ( HostEnvironmentInfo . BenchmarkDotNetCaption ) , HostEnvironmentInfo . BenchmarkDotNetCaption } ,
49+ { nameof ( environmentInfo . BenchmarkDotNetVersion ) , environmentInfo . BenchmarkDotNetVersion } ,
50+ { " OsVersion" , environmentInfo . OsVersion . Value } ,
51+ { " ProcessorName" , ProcessorBrandStringHelper . Prettify ( environmentInfo . CpuInfo . Value ) } ,
52+ { "PhysicalProcessorCount" , environmentInfo . CpuInfo . Value ? . PhysicalProcessorCount } ,
53+ { "PhysicalCoreCount" , environmentInfo . CpuInfo . Value ? . PhysicalCoreCount } ,
54+ { "LogicalCoreCount" , environmentInfo . CpuInfo . Value ? . LogicalCoreCount } ,
55+ { nameof ( environmentInfo . RuntimeVersion ) , environmentInfo . RuntimeVersion } ,
56+ { nameof ( environmentInfo . Architecture ) , environmentInfo . Architecture } ,
57+ { nameof ( environmentInfo . HasAttachedDebugger ) , environmentInfo . HasAttachedDebugger } ,
58+ { nameof ( environmentInfo . HasRyuJit ) , environmentInfo . HasRyuJit } ,
59+ { nameof ( environmentInfo . Configuration ) , environmentInfo . Configuration } ,
60+ { " DotNetCliVersion" , environmentInfo . DotNetSdkVersion . Value } ,
61+ { nameof ( environmentInfo . ChronometerFrequency ) , environmentInfo . ChronometerFrequency } ,
62+ { nameof ( HardwareTimerKind ) , environmentInfo . HardwareTimerKind . ToString ( ) } ,
4463 } ;
64+ }
4565
46- // If we just ask SimpleJson to serialize the entire "summary" object it throws several errors.
47- // So we are more specific in what we serialize (plus some fields/properties aren't relevant)
48-
49- var benchmarks = summary . Reports . Select ( report =>
66+ protected virtual IReadOnlyDictionary < string , object > GetDataToSerialize ( BenchmarkReport report )
67+ {
68+ var benchmark = new Dictionary < string , object >
5069 {
51- var data = new Dictionary < string , object >
70+ // We don't need Benchmark.ShortInfo, that info is available via Benchmark.Parameters below
71+ { "DisplayInfo" , report . BenchmarkCase . DisplayInfo } ,
72+ { "Namespace" , report . BenchmarkCase . Descriptor . Type . Namespace } ,
73+ { "Type" , FullNameProvider . GetTypeName ( report . BenchmarkCase . Descriptor . Type ) } ,
74+ { "Method" , report . BenchmarkCase . Descriptor . WorkloadMethod . Name } ,
75+ { "MethodTitle" , report . BenchmarkCase . Descriptor . WorkloadMethodDisplayInfo } ,
76+ { "Parameters" , report . BenchmarkCase . Parameters . PrintInfo } ,
5277 {
53- // We don't need Benchmark.ShortInfo, that info is available via Benchmark.Parameters below
54- { "DisplayInfo" , report . BenchmarkCase . DisplayInfo } ,
55- { "Namespace" , report . BenchmarkCase . Descriptor . Type . Namespace } ,
56- { "Type" , FullNameProvider . GetTypeName ( report . BenchmarkCase . Descriptor . Type ) } ,
57- { "Method" , report . BenchmarkCase . Descriptor . WorkloadMethod . Name } ,
58- { "MethodTitle" , report . BenchmarkCase . Descriptor . WorkloadMethodDisplayInfo } ,
59- { "Parameters" , report . BenchmarkCase . Parameters . PrintInfo } ,
60- { "FullName" , FullNameProvider . GetBenchmarkName ( report . BenchmarkCase ) } , // do NOT remove this property, it is used for xunit-performance migration
61- // Hardware Intrinsics can be disabled using env vars, that is why they might be different per benchmark and are not exported as part of HostEnvironmentInfo
62- { "HardwareIntrinsics" , report . GetHardwareIntrinsicsInfo ( ) ?? "" } ,
63- // { "Properties", r.Benchmark.Job.ToSet().ToDictionary(p => p.Name, p => p.Value) }, // TODO
64- { "Statistics" , report . ResultStatistics }
65- } ;
78+ "FullName" , FullNameProvider . GetBenchmarkName ( report . BenchmarkCase )
79+ } , // do NOT remove this property, it is used for xunit-performance migration
80+ // Hardware Intrinsics can be disabled using env vars, that is why they might be different per benchmark and are not exported as part of HostEnvironmentInfo
81+ { "HardwareIntrinsics" , report . GetHardwareIntrinsicsInfo ( ) ?? "" } ,
82+ // { "Properties", r.Benchmark.Job.ToSet().ToDictionary(p => p.Name, p => p.Value) }, // TODO
83+ { "Statistics" , report . ResultStatistics }
84+ } ;
6685
6786 // We show MemoryDiagnoser's results only if it is being used
6887 if ( report . BenchmarkCase . Config . HasMemoryDiagnoser ( ) )
6988 {
70- data . Add ( "Memory" , new
89+ benchmark . Add ( "Memory" , new
7190 {
7291 report . GcStats . Gen0Collections ,
7392 report . GcStats . Gen1Collections ,
@@ -80,7 +99,7 @@ public override void ExportToLog(Summary summary, ILogger logger)
8099 if ( ExcludeMeasurements == false )
81100 {
82101 // We construct Measurements manually, so that we can have the IterationMode enum as text, rather than an integer
83- data . Add ( "Measurements" ,
102+ benchmark . Add ( "Measurements" ,
84103 report . AllMeasurements . Select ( m => new
85104 {
86105 IterationMode = m . IterationMode . ToString ( ) ,
@@ -93,20 +112,11 @@ public override void ExportToLog(Summary summary, ILogger logger)
93112
94113 if ( report . Metrics . Any ( ) )
95114 {
96- data . Add ( "Metrics" , report . Metrics . Values ) ;
115+ benchmark . Add ( "Metrics" , report . Metrics . Values ) ;
97116 }
98117 }
99118
100- return data ;
101- } ) ;
102-
103- JsonSerializer . CurrentJsonSerializerStrategy . Indent = IndentJson ;
104- logger . WriteLine ( JsonSerializer . SerializeObject ( new Dictionary < string , object >
105- {
106- { "Title" , summary . Title } ,
107- { "HostEnvironmentInfo" , environmentInfo } ,
108- { "Benchmarks" , benchmarks }
109- } ) ) ;
119+ return benchmark ;
110120 }
111121 }
112122}
0 commit comments