33using System . Diagnostics . CodeAnalysis ;
44using System . Linq ;
55using System . Text . RegularExpressions ;
6+ using BenchmarkDotNet . Extensions ;
67using BenchmarkDotNet . Helpers ;
78using BenchmarkDotNet . Portability . Cpu ;
89using Perfolizer . Horology ;
910
10- namespace BenchmarkDotNet . Environments
11+ namespace BenchmarkDotNet . Environments ;
12+
13+ public static class ProcessorBrandStringHelper
1114{
12- public static class ProcessorBrandStringHelper
15+ /// <summary>
16+ /// Transform a processor brand string to a nice form for summary.
17+ /// </summary>
18+ /// <param name="cpuInfo">The CPU information</param>
19+ /// <param name="includeMaxFrequency">Whether to include determined max frequency information</param>
20+ /// <returns>Prettified version</returns>
21+ public static string Prettify ( CpuInfo ? cpuInfo , bool includeMaxFrequency = false )
1322 {
14- /// <summary>
15- /// Transform a processor brand string to a nice form for summary.
16- /// </summary>
17- /// <param name="cpuInfo">The CPU information</param>
18- /// <param name="includeMaxFrequency">Whether to include determined max frequency information</param>
19- /// <returns>Prettified version</returns>
20- public static string Prettify ( CpuInfo cpuInfo , bool includeMaxFrequency = false )
21- {
22- if ( cpuInfo == null || string . IsNullOrEmpty ( cpuInfo . ProcessorName ) )
23- {
24- return "Unknown processor" ;
25- }
23+ string ? processorName = cpuInfo ? . ProcessorName ;
24+ if ( processorName == null || processorName . IsBlank ( ) )
25+ return "Unknown processor" ;
2626
27- // Remove parts which don't provide any useful information for user
28- var processorName = cpuInfo . ProcessorName . Replace ( "@" , "" ) . Replace ( "(R)" , "" ) . Replace ( "(TM)" , "" ) ;
27+ // Remove parts which don't provide any useful information for user
28+ processorName = processorName . Replace ( "@" , "" ) . Replace ( "(R)" , "" ) . Replace ( "(TM)" , "" ) ;
2929
30- // If we have found physical core(s), we can safely assume we can drop extra info from brand
31- if ( cpuInfo . PhysicalCoreCount . HasValue && cpuInfo . PhysicalCoreCount . Value > 0 )
32- processorName = Regex . Replace ( processorName , @"(\w+?-Core Processor)" , "" ) . Trim ( ) ;
30+ // If we have found physical core(s), we can safely assume we can drop extra info from brand
31+ if ( cpuInfo . PhysicalCoreCount is > 0 )
32+ processorName = Regex . Replace ( processorName , @"(\w+?-Core Processor)" , "" ) . Trim ( ) ;
3333
34- string frequencyString = GetBrandStyledActualFrequency ( cpuInfo . NominalFrequency ) ;
35- if ( includeMaxFrequency && frequencyString != null && ! processorName . Contains ( frequencyString ) )
36- {
37- // show Max only if there's already a frequency name to differentiate the two
38- string maxFrequency = processorName . Contains ( "Hz" ) ? $ "(Max: { frequencyString } )" : frequencyString ;
39- processorName = $ "{ processorName } { maxFrequency } ";
40- }
34+ string frequencyString = GetBrandStyledNominalFrequency ( cpuInfo . NominalFrequency ) ;
35+ if ( includeMaxFrequency && frequencyString != null && ! processorName . Contains ( frequencyString ) )
36+ {
37+ // show Max only if there's already a frequency name to differentiate the two
38+ string maxFrequency = processorName . Contains ( "Hz" ) ? $ "(Max: { frequencyString } )" : frequencyString ;
39+ processorName = $ "{ processorName } { maxFrequency } ";
40+ }
4141
42- // Remove double spaces
43- processorName = Regex . Replace ( processorName . Trim ( ) , @"\s+" , " " ) ;
42+ // Remove double spaces
43+ processorName = Regex . Replace ( processorName . Trim ( ) , @"\s+" , " " ) ;
4444
45- // Add microarchitecture name if known
46- string microarchitecture = ParseMicroarchitecture ( processorName ) ;
47- if ( microarchitecture != null )
48- processorName = $ "{ processorName } ({ microarchitecture } )";
45+ // Add microarchitecture name if known
46+ string microarchitecture = ParseMicroarchitecture ( processorName ) ;
47+ if ( microarchitecture != null )
48+ processorName = $ "{ processorName } ({ microarchitecture } )";
4949
50- return processorName ;
51- }
50+ return processorName ;
51+ }
5252
53- /// <summary>
54- /// Presents actual processor's frequency into brand string format
55- /// </summary>
56- /// <param name="frequency"></param>
57- private static string GetBrandStyledActualFrequency ( Frequency ? frequency )
58- {
59- if ( frequency == null )
60- return null ;
61- return $ "{ frequency . Value . ToGHz ( ) . ToString ( "N2" , DefaultCultureInfo . Instance ) } GHz";
62- }
53+ /// <summary>
54+ /// Presents actual processor's frequency into brand string format
55+ /// </summary>
56+ /// <param name="frequency"></param>
57+ private static string ? GetBrandStyledNominalFrequency ( Frequency ? frequency )
58+ {
59+ if ( frequency == null )
60+ return null ;
61+ return $ "{ frequency . Value . ToGHz ( ) . ToString ( "N2" , DefaultCultureInfo . Instance ) } GHz";
62+ }
6363
64- /// <summary>
65- /// Parse a processor name and tries to return a microarchitecture name.
66- /// Works only for well-known microarchitectures.
67- /// </summary>
68- private static string ? ParseMicroarchitecture ( string processorName )
64+ /// <summary>
65+ /// Parse a processor name and tries to return a microarchitecture name.
66+ /// Works only for well-known microarchitectures.
67+ /// </summary>
68+ private static string ? ParseMicroarchitecture ( string processorName )
69+ {
70+ if ( processorName . StartsWith ( "Intel Core" ) )
6971 {
70- if ( processorName . StartsWith ( "Intel Core" ) )
72+ string model = processorName . Substring ( "Intel Core" . Length ) . Trim ( ) ;
73+
74+ // Core i3/5/7/9
75+ if (
76+ model . Length > 4 &&
77+ model [ 0 ] == 'i' &&
78+ ( model [ 1 ] == '3' || model [ 1 ] == '5' || model [ 1 ] == '7' || model [ 1 ] == '9' ) &&
79+ ( model [ 2 ] == '-' || model [ 2 ] == ' ' ) )
7180 {
72- string model = processorName . Substring ( "Intel Core" . Length ) . Trim ( ) ;
73-
74- // Core i3/5/7/9
75- if (
76- model . Length > 4 &&
77- model [ 0 ] == 'i' &&
78- ( model [ 1 ] == '3' || model [ 1 ] == '5' || model [ 1 ] == '7' || model [ 1 ] == '9' ) &&
79- ( model [ 2 ] == '-' || model [ 2 ] == ' ' ) )
80- {
81- string modelNumber = model . Substring ( 3 ) ;
82- if ( modelNumber . StartsWith ( "CPU" ) )
83- modelNumber = modelNumber . Substring ( 3 ) . Trim ( ) ;
84- if ( modelNumber . Contains ( "CPU" ) )
85- modelNumber = modelNumber . Substring ( 0 , modelNumber . IndexOf ( "CPU" , StringComparison . Ordinal ) ) . Trim ( ) ;
86- return ParseIntelCoreMicroarchitecture ( modelNumber ) ;
87- }
81+ string modelNumber = model . Substring ( 3 ) ;
82+ if ( modelNumber . StartsWith ( "CPU" ) )
83+ modelNumber = modelNumber . Substring ( 3 ) . Trim ( ) ;
84+ if ( modelNumber . Contains ( "CPU" ) )
85+ modelNumber = modelNumber . Substring ( 0 , modelNumber . IndexOf ( "CPU" , StringComparison . Ordinal ) ) . Trim ( ) ;
86+ return ParseIntelCoreMicroarchitecture ( modelNumber ) ;
8887 }
89-
90- return null ;
9188 }
9289
93- private static readonly Lazy < Dictionary < string , string > > KnownMicroarchitectures = new Lazy < Dictionary < string , string > > ( ( ) =>
90+ return null ;
91+ }
92+
93+ private static readonly Lazy < Dictionary < string , string > > KnownMicroarchitectures = new Lazy < Dictionary < string , string > > ( ( ) =>
94+ {
95+ var data = ResourceHelper . LoadResource ( "BenchmarkDotNet.Environments.microarchitectures.txt" ) . Split ( '\r ' , '\n ' ) ;
96+ var dictionary = new Dictionary < string , string > ( ) ;
97+ string ? currentMicroarchitecture = null ;
98+ foreach ( string line in data )
9499 {
95- var data = ResourceHelper . LoadResource ( "BenchmarkDotNet.Environments.microarchitectures.txt" ) . Split ( '\r ' , '\n ' ) ;
96- var dictionary = new Dictionary < string , string > ( ) ;
97- string ? currentMicroarchitecture = null ;
98- foreach ( string line in data )
100+ if ( line . StartsWith ( "//" ) || string . IsNullOrWhiteSpace ( line ) )
101+ continue ;
102+ if ( line . StartsWith ( "#" ) )
99103 {
100- if ( line . StartsWith ( "//" ) || string . IsNullOrWhiteSpace ( line ) )
101- continue ;
102- if ( line . StartsWith ( "#" ) )
103- {
104- currentMicroarchitecture = line . Substring ( 1 ) . Trim ( ) ;
105- continue ;
106- }
107-
108- string modelNumber = line . Trim ( ) ;
109- if ( dictionary . ContainsKey ( modelNumber ) )
110- throw new Exception ( $ "{ modelNumber } is defined twice in microarchitectures.txt") ;
111- if ( currentMicroarchitecture == null )
112- throw new Exception ( $ "{ modelNumber } doesn't have defined microarchitecture in microarchitectures.txt") ;
113- dictionary [ modelNumber ] = currentMicroarchitecture ;
104+ currentMicroarchitecture = line . Substring ( 1 ) . Trim ( ) ;
105+ continue ;
114106 }
115107
116- return dictionary ;
117- } ) ;
108+ string modelNumber = line . Trim ( ) ;
109+ if ( dictionary . ContainsKey ( modelNumber ) )
110+ throw new Exception ( $ "{ modelNumber } is defined twice in microarchitectures.txt") ;
111+ if ( currentMicroarchitecture == null )
112+ throw new Exception ( $ "{ modelNumber } doesn't have defined microarchitecture in microarchitectures.txt") ;
113+ dictionary [ modelNumber ] = currentMicroarchitecture ;
114+ }
118115
119- // see http://www.intel.com/content/www/us/en/processors/processor-numbers.html
120- [ SuppressMessage ( "ReSharper" , "StringLiteralTypo" ) ]
121- internal static string ? ParseIntelCoreMicroarchitecture ( string modelNumber )
122- {
123- if ( KnownMicroarchitectures . Value . TryGetValue ( modelNumber , out string ? microarchitecture ) )
124- return microarchitecture ;
116+ return dictionary ;
117+ } ) ;
118+
119+ // see http://www.intel.com/content/www/us/en/processors/processor-numbers.html
120+ [ SuppressMessage ( "ReSharper" , "StringLiteralTypo" ) ]
121+ internal static string ? ParseIntelCoreMicroarchitecture ( string modelNumber )
122+ {
123+ if ( KnownMicroarchitectures . Value . TryGetValue ( modelNumber , out string ? microarchitecture ) )
124+ return microarchitecture ;
125125
126- if ( modelNumber . Length >= 3 && modelNumber . Substring ( 0 , 3 ) . All ( char . IsDigit ) &&
127- ( modelNumber . Length == 3 || ! char . IsDigit ( modelNumber [ 3 ] ) ) )
128- return "Nehalem" ;
129- if ( modelNumber . Length >= 4 && modelNumber . Substring ( 0 , 4 ) . All ( char . IsDigit ) )
126+ if ( modelNumber . Length >= 3 && modelNumber . Substring ( 0 , 3 ) . All ( char . IsDigit ) &&
127+ ( modelNumber . Length == 3 || ! char . IsDigit ( modelNumber [ 3 ] ) ) )
128+ return "Nehalem" ;
129+ if ( modelNumber . Length >= 4 && modelNumber . Substring ( 0 , 4 ) . All ( char . IsDigit ) )
130+ {
131+ char generation = modelNumber [ 0 ] ;
132+ switch ( generation )
130133 {
131- char generation = modelNumber [ 0 ] ;
132- switch ( generation )
133- {
134- case '2' :
135- return "Sandy Bridge" ;
136- case '3' :
137- return "Ivy Bridge" ;
138- case '4' :
139- return "Haswell" ;
140- case '5' :
141- return "Broadwell" ;
142- case '6' :
143- return "Skylake" ;
144- case '7' :
145- return "Kaby Lake" ;
146- case '8' :
147- return "Coffee Lake" ;
148- default :
149- return null ;
150- }
134+ case '2' :
135+ return "Sandy Bridge" ;
136+ case '3' :
137+ return "Ivy Bridge" ;
138+ case '4' :
139+ return "Haswell" ;
140+ case '5' :
141+ return "Broadwell" ;
142+ case '6' :
143+ return "Skylake" ;
144+ case '7' :
145+ return "Kaby Lake" ;
146+ case '8' :
147+ return "Coffee Lake" ;
148+ default :
149+ return null ;
151150 }
152- return null ;
153151 }
152+ return null ;
154153 }
155154}
0 commit comments