@@ -797,23 +797,23 @@ public static IEnumerable<TSource> SequenceAt<TSource>(this TSource[] source, in
797797 yield return source [ i ++ ] ;
798798 }
799799
800- public static IEnumerable < T > SkipLast < T > ( this IEnumerable < T > source , int count )
801- {
802- var saveList = new Queue < T > ( ) ;
803- var saved = 0 ;
804- foreach ( T item in source )
805- {
806- if ( saved < count )
807- {
808- saveList . Enqueue ( item ) ;
809- ++ saved ;
810- continue ;
811- }
812-
813- saveList . Enqueue ( item ) ;
814- yield return saveList . Dequeue ( ) ;
815- }
816- }
800+ // public static IEnumerable<T> SkipLast<T>(this IEnumerable<T> source, int count)
801+ // {
802+ // var saveList = new Queue<T>();
803+ // var saved = 0;
804+ // foreach (T item in source)
805+ // {
806+ // if (saved < count)
807+ // {
808+ // saveList.Enqueue(item);
809+ // ++saved;
810+ // continue;
811+ // }
812+
813+ // saveList.Enqueue(item);
814+ // yield return saveList.Dequeue();
815+ // }
816+ // }
817817
818818 public static bool ? ToBoolean ( this XAttribute a )
819819 {
@@ -1169,6 +1169,128 @@ IEnumerator<TSource> IEnumerable<TSource>.GetEnumerator()
11691169 }
11701170 }
11711171
1172+ // this is fundamentally the same as PtBucketTimer, except that it is instance based,
1173+ // not a static class.
1174+ public class BucketTimer
1175+ {
1176+ public BucketTimer ( )
1177+ {
1178+ Buckets = new Dictionary < string , BucketInfo > ( ) ;
1179+ }
1180+
1181+ private class BucketInfo
1182+ {
1183+ public int Count ;
1184+ public TimeSpan Time ;
1185+ }
1186+
1187+ private string LastBucket = null ;
1188+ private DateTime LastTime ;
1189+ private Dictionary < string , BucketInfo > Buckets ;
1190+
1191+ public void Bucket ( string bucket )
1192+ {
1193+ DateTime now = DateTime . Now ;
1194+ if ( LastBucket != null )
1195+ AddToBuckets ( now ) ;
1196+ LastBucket = bucket ;
1197+ LastTime = now ;
1198+ }
1199+
1200+ public void End ( )
1201+ {
1202+ DateTime now = DateTime . Now ;
1203+ if ( LastBucket != null )
1204+ AddToBuckets ( now ) ;
1205+ LastBucket = null ;
1206+ }
1207+
1208+ private void AddToBuckets ( DateTime now )
1209+ {
1210+ TimeSpan d = now - LastTime ;
1211+ var bucketParts = LastBucket . Split ( '/' ) ;
1212+ var bucketList = bucketParts . Select ( ( t , i ) => bucketParts
1213+ . Take ( i + 1 )
1214+ . Select ( z => z + "/" )
1215+ . StringConcatenate ( )
1216+ . Trim ( '/' ) )
1217+ . ToList ( ) ;
1218+
1219+ foreach ( var b in bucketList )
1220+ {
1221+ if ( Buckets . ContainsKey ( b ) )
1222+ {
1223+ Buckets [ b ] . Count = Buckets [ b ] . Count + 1 ;
1224+ Buckets [ b ] . Time += d ;
1225+ }
1226+ else
1227+ {
1228+ Buckets . Add ( b , new BucketInfo ( )
1229+ {
1230+ Count = 1 ,
1231+ Time = d ,
1232+ } ) ;
1233+ }
1234+ }
1235+ LastTime = now ;
1236+ }
1237+
1238+ public string DumpBucketsByKey ( )
1239+ {
1240+ StringBuilder sb = new StringBuilder ( ) ;
1241+ foreach ( var bucket in Buckets . OrderBy ( b => b . Key ) )
1242+ {
1243+ string ts = bucket . Value . Time . ToString ( ) ;
1244+ if ( ts . Contains ( '.' ) )
1245+ ts = ts . Substring ( 0 , ts . Length - 5 ) ;
1246+ string s = bucket . Key . PadRight ( 60 , '-' ) + " " + string . Format ( "{0:00000000}" , bucket . Value . Count ) + " " + ts ;
1247+ sb . Append ( s + Environment . NewLine ) ;
1248+ }
1249+ TimeSpan total = Buckets
1250+ . Aggregate ( TimeSpan . Zero , ( t , b ) => t + b . Value . Time ) ;
1251+ var tz = total . ToString ( ) ;
1252+ sb . Append ( string . Format ( "Total: {0}" , tz . Substring ( 0 , tz . Length - 5 ) ) ) ;
1253+ return sb . ToString ( ) ;
1254+ }
1255+
1256+ public string DumpBucketsToCsvByKey ( )
1257+ {
1258+ StringBuilder sb = new StringBuilder ( ) ;
1259+ foreach ( var bucket in Buckets . OrderBy ( b => b . Key ) )
1260+ {
1261+ string ts = bucket . Value . Time . ToString ( ) ;
1262+ if ( ts . Contains ( '.' ) )
1263+ ts = ts . Substring ( 0 , ts . Length - 5 ) ;
1264+ string s = bucket . Key + "," + bucket . Value . Count . ToString ( ) + "," + ts ;
1265+ sb . Append ( s + Environment . NewLine ) ;
1266+ }
1267+ return sb . ToString ( ) ;
1268+ }
1269+
1270+ public string DumpBucketsByTime ( )
1271+ {
1272+ StringBuilder sb = new StringBuilder ( ) ;
1273+ foreach ( var bucket in Buckets . OrderBy ( b => b . Value . Time ) )
1274+ {
1275+ string ts = bucket . Value . Time . ToString ( ) ;
1276+ if ( ts . Contains ( '.' ) )
1277+ ts = ts . Substring ( 0 , ts . Length - 5 ) ;
1278+ string s = bucket . Key . PadRight ( 60 , '-' ) + " " + string . Format ( "{0:00000000}" , bucket . Value . Count ) + " " + ts ;
1279+ sb . Append ( s + Environment . NewLine ) ;
1280+ }
1281+ TimeSpan total = Buckets
1282+ . Aggregate ( TimeSpan . Zero , ( t , b ) => t + b . Value . Time ) ;
1283+ var tz = total . ToString ( ) ;
1284+ sb . Append ( string . Format ( "Total: {0}" , tz . Substring ( 0 , tz . Length - 5 ) ) ) ;
1285+ return sb . ToString ( ) ;
1286+ }
1287+
1288+ public void Init ( )
1289+ {
1290+ Buckets = new Dictionary < string , BucketInfo > ( ) ;
1291+ }
1292+ }
1293+
11721294 public static class PtBucketTimer
11731295 {
11741296 private class BucketInfo
0 commit comments