<commit_before>﻿using CommandLine;
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;

namespace LiveStacks
{
    class Program
    {
        private static StackResolver _resolver;
        private static LiveSession _session;
        private static Options _options;
        private static Timer _timer;
        private static int _invocationsLeft;

        private static void Main(string[] args)
        {
            _options = new Options();
            if (!Parser.Default.ParseArguments(args, _options))
                Environment.Exit(1);

            _invocationsLeft = _options.Count == -1 ? int.MaxValue : _options.Count;

            _session = new LiveSession(_options.StackEvent, _options.PidsToFilter);
            Console.CancelKeyPress += (_, __) =>
            {
                Console.WriteLine("Ctrl+C pressed, stopping...");
                _session.Stop();
            };

            _resolver = new StackResolver();
            object timerSyncObject = new object();
            TimeSpan interval = TimeSpan.FromSeconds(_options.IntervalSeconds);
            _timer = new Timer(_ =>
            {
                // Prevent multiple invocations of the timer from running concurrently.
                lock (timerSyncObject)
                {
                    OnTimer();
                    if (--_invocationsLeft == 0)
                    {
                        _session.Stop();
                    }
                }
            }, null, interval, interval);
            // TODO If the interval is 0, the user wants to print every single stack

            _session.Start();
        }

        private static void OnTimer()
        {
            if (!_options.FoldedStacks)
            {
                Console.WriteLine(DateTime.Now.ToLongTimeString());
            }
            Stopwatch sw = Stopwatch.StartNew();
            var stacks = _session.Stacks.TopStacks(_options.TopStacks);
            _session.Stacks.Clear();
            foreach (var stack in stacks)
            {
                if (_options.FoldedStacks)
                    PrintFoldedStack(stack);
                else
                    PrintNormalStack(stack);
            }
            if (!_options.FoldedStacks)
            {
                Console.WriteLine($"  Time aggregating/resolving: {sw.ElapsedMilliseconds}ms");
            }
        }

        private static void PrintNormalStack(AggregatedStack stack)
        {
            int pid = stack.ProcessID;
            Console.WriteLine($"  {stack.Count,10} [{_resolver.ProcessName(pid)} {pid}]");
            foreach (var symbol in _resolver.Resolve(pid, stack.Addresses))
            {
                Console.WriteLine("    " + symbol.ToString());
            }
        }

        private static void PrintFoldedStack(AggregatedStack stack)
        {
            int pid = stack.ProcessID;
            Console.Write($"{_resolver.ProcessName(pid)} ({pid});");
            foreach (var symbol in _resolver.Resolve(pid, stack.Addresses))
            {
                Console.Write(symbol.ToString() + ";");
            }
            Console.WriteLine(stack.Count);
        }
    }
}
<commit_msg>Reverse stack frames before printing in folded format<commit_after>﻿using CommandLine;
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;

namespace LiveStacks
{
    class Program
    {
        private static StackResolver _resolver;
        private static LiveSession _session;
        private static Options _options;
        private static Timer _timer;
        private static int _invocationsLeft;

        private static void Main(string[] args)
        {
            _options = new Options();
            if (!Parser.Default.ParseArguments(args, _options))
                Environment.Exit(1);

            _invocationsLeft = _options.Count == -1 ? int.MaxValue : _options.Count;

            _session = new LiveSession(_options.StackEvent, _options.PidsToFilter);
            Console.CancelKeyPress += (_, __) =>
            {
                Console.WriteLine("Ctrl+C pressed, stopping...");
                _session.Stop();
            };

            _resolver = new StackResolver();
            object timerSyncObject = new object();
            TimeSpan interval = TimeSpan.FromSeconds(_options.IntervalSeconds);
            _timer = new Timer(_ =>
            {
                // Prevent multiple invocations of the timer from running concurrently.
                lock (timerSyncObject)
                {
                    OnTimer();
                    if (--_invocationsLeft == 0)
                    {
                        _session.Stop();
                    }
                }
            }, null, interval, interval);
            // TODO If the interval is 0, the user wants to print every single stack

            _session.Start();
        }

        private static void OnTimer()
        {
            if (!_options.FoldedStacks)
            {
                Console.WriteLine(DateTime.Now.ToLongTimeString());
            }
            Stopwatch sw = Stopwatch.StartNew();
            var stacks = _session.Stacks.TopStacks(_options.TopStacks);
            _session.Stacks.Clear();
            foreach (var stack in stacks)
            {
                if (_options.FoldedStacks)
                    PrintFoldedStack(stack);
                else
                    PrintNormalStack(stack);
            }
            if (!_options.FoldedStacks)
            {
                Console.WriteLine($"  Time aggregating/resolving: {sw.ElapsedMilliseconds}ms");
            }
        }

        private static void PrintNormalStack(AggregatedStack stack)
        {
            int pid = stack.ProcessID;
            Console.WriteLine($"  {stack.Count,10} [{_resolver.ProcessName(pid)} {pid}]");
            foreach (var symbol in _resolver.Resolve(pid, stack.Addresses))
            {
                Console.WriteLine("    " + symbol.ToString());
            }
        }

        private static void PrintFoldedStack(AggregatedStack stack)
        {
            int pid = stack.ProcessID;
            Console.Write($"{_resolver.ProcessName(pid)} ({pid});");
            foreach (var symbol in _resolver.Resolve(pid, stack.Addresses).Reverse())
            {
                Console.Write(symbol.ToString() + ";");
            }
            Console.WriteLine(stack.Count);
        }
    }
}

{'fraction_non_alphanumeric': 0.09389174478379196, 'fraction_numerical': 0.0018143332325370426, 'mean_word_length': 1.5890410958904109, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 7, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '5070970', 'n_tokens_mistral': 1664, 'n_tokens_neox': 1583, 'n_words': 369}