eduherminio / AoCHelper

Helper .NET library for solving Advent of Code puzzles

Home Page:https://adventofcode.com

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Part 1 Timer seemingly starting early

Aaeeschylus opened this issue Β· comments

For some reason, the Part 1 for everything is taking much longer than part 2 of the same question. For example:

image

I am not sure why this is the case. For Day 1, part 1 is doing significantly less than part 2. For Day 2, both parts are the exact same. Could this be related to how I have written my parts or is this something related to when AoCHelper starts the timer? This may also be a case of me not entirely understanding how the Helper is supposed to work.

Please note, I am using the Template that is linked in the main Readme.

Here is an example of how my Day 2 is set up:

    public class Day_02 : BaseDay
    {
        private readonly string _input;

        public Day_02()
        {
            _input = File.ReadAllText(InputFilePath);
        }

        public override ValueTask<string> Solve_1() => Part1();

        public override ValueTask<string> Solve_2() => Part2();

        private ValueTask<string> Part1()
        {
            throw new System.NotImplementedException();
        }

        private ValueTask<string> Part2()
        {
            throw new System.NotImplementedException();
        }
    }

Hi @Aaeeschylus!
First of all, thx for using AoCHelper πŸ˜ƒ

Without seen your code for Day 1 it's tricky to identify the issue.
It does sound a lot like what I describe here, with the effort of parsing/transforming the input is being done in part 1. One needs to be careful with IEnumerable<T> lazy evaluation as well.

Using the following SolverConfiguration in your Program.cs may help us debug the issue:

new SolverConfiguration { ShowConstructorElapsedTime = true, ShowTotalElapsedTimePerDay = true }

In my case I can see clearly that the input loading is made in the constructor and, elapsed time make sense from there:

Using new SolverConfiguration { ClearConsole = false }

β”Œβ”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚ Day   β”‚ Part   β”‚ Solution β”‚ Elapsed time β”‚
β”œβ”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€
β”‚ Day 1 β”‚ Part 1 β”‚ 1527     β”‚ 0,39 ms      β”‚
β”‚ Day 1 β”‚ Part 2 β”‚ 1575     β”‚ 1 ms         β”‚
β”‚       β”‚        β”‚          β”‚              β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

Using new SolverConfiguration { ShowConstructorElapsedTime = true, ShowTotalElapsedTimePerDay = true, ClearConsole = false }
β”Œβ”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚ Day   β”‚ Part     β”‚ Solution    β”‚ Elapsed time β”‚
β”œβ”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€
β”‚ Day 1 β”‚ Day_01() β”‚ ----------- β”‚ 24 ms        β”‚
β”‚ Day 1 β”‚ Part 1   β”‚ 1527        β”‚ 0,49 ms      β”‚
β”‚ Day 1 β”‚ Part 2   β”‚ 1575        β”‚ 1 ms         β”‚
β”‚ Day 1 β”‚ Total    β”‚ ----------- β”‚ 26 ms        β”‚
β”‚       β”‚          β”‚             β”‚              β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

Let me know if that helps

Hi @eduherminio!
Thanks for the really quick response and explaining the extra configuration. I hadn't really looked into that yet and I am glad I know it exists now!

Sadly, all of my input parsing/transforming is already done in the constructor and not in Part 1.

I was having a chat to some colleagues about it (as together we are using AOC this year to improve our knowledge of languages we are not too confident with) and it seems like the issue I am running into is just how .NET/C# works. It appears that the issue is related to JIT Compiling. When something is run for the first time it will take longer, however all subsequent runs of the same thing are quicker as it has already been compiled completely. Look at my results below:
image

In my case, day 1 uses some functions from a shared class library I have made for commonly used functions. I tried running all of the functions before even starting the solver and as you can see from the image, that fixed the issue there. Day 2 still has this issue as a throw had not been run yet.

I tested this further by putting a throw not implemented inside a try catch that ignores it just before I run the solver and it fixes it for day 2 as well:
image
Long story short, based on the above, I don't think there is anything wrong with the AOCHelper and it is just how .NET/C# work as a whole with JIT compiling.

I see, I'm aware of the JIT 'issue' (that's one of the reasons why specialized perf measuring tools like BenchmarkDotNet take its time to warm up before the actual tests) but I was expecting it to have less impact in your elapse time.

Now that you mention it, I remember some specific implementations in AoC2019, when AoCHelper was born, where, unless invoking the key method in the constructor, the results were similar to yours.

I'm actually tracking implementing something more advanced to measure performance in #46, which would imply discarding the first executions, but to be fair I didn't make any progress for now because that would always end up somewhere between what we currently have and a 'proper' benchmark using a specialized library.

People 'serious' about measuring the performance of their solutions will never use AoCHelper to do it and, according to the my original idea and the feedback I'm getting, one of the reasons why people use it is to get some kind of basic measure without actually bothering to wait minutes in order to get super-accurate ones.

But that's of course my opinion (and can change), if there's further interest in getting more accurate measures, give some πŸ‘πŸΌ to #46 and I'll consider investing some time there.

Meanwhile, I've changed the template to use SolverConfiguration instances so that more people realize they can customize some stuff, and also added a section in the readme explaining the different options.

Thx for reporting this @Aaeeschylus!

Yeah that is entirely understandable and no worries! I think it has such a huge impact at the moment as day 1 was very quick and simple. I expect it to be less noticeable once we get to day 12 or later. I mostly looked into this just to learn some more about how it works in the background. I appreciate the help though!