Skip to content

Commit

Permalink
Merge pull request #2 from igorwulff/feature/style-processing-improve…
Browse files Browse the repository at this point in the history
…ments

Improved Benchmarking and added a total counter.
  • Loading branch information
igorwulff authored Dec 10, 2024
2 parents dba4061 + f33c42c commit 71b3daa
Show file tree
Hide file tree
Showing 5 changed files with 94 additions and 77 deletions.
14 changes: 14 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,20 @@ This repository provides a framework and helper tools to streamline the process

## Example

The tool can be given 3 arguments:
```sh
-day string
Day of the challenge. 0 to run all days. (default "0")
-part string
Part of the challenge. 0 to run all parts (default "0")
-year string
Year of the challenge (default "2024")
```

Where days and parts are optional:
* If no days are provided, all days will be run.
* If a day is provided but no parts, all parts of that day will be run.

To run the tool, use the following command:

```sh
Expand Down
20 changes: 20 additions & 0 deletions internal/benchmark.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
package internal

import "time"

type BenchmarkResult struct {
TotalTimeInMs int64
Start int64
}

func (b *BenchmarkResult) StartTimer() {
b.Start = time.Now().UnixMilli()
}

func (b *BenchmarkResult) StopTimer() {
b.TotalTimeInMs = time.Now().UnixMilli() - b.Start
}

func (b BenchmarkResult) GetTotalTimeInMs() int64 {
return b.TotalTimeInMs
}
14 changes: 1 addition & 13 deletions internal/input.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ type Args struct {
func ProcessArgs() Args {
year := flag.String("year", fmt.Sprint(time.Now().Year()), "Year of the challenge")
day := flag.String("day", "0", "Day of the challenge. 0 to run all days.")
part := flag.String("part", "1", "Part of the challenge")
part := flag.String("part", "0", "Part of the challenge. 0 to run all parts")
flag.Parse()

args := Args{
Expand All @@ -27,22 +27,10 @@ func ProcessArgs() Args {
Year: *year,
}

path, err := args.getPath()
if err != nil {
fmt.Println(err)
os.Exit(1)
}

args.path = path

return args
}

func (args Args) getPath() (string, error) {
if args.Day == "0" {
return "", nil
}

path := filepath.Join("./", args.Year, "day"+args.Day, "part"+args.Part)
if _, err := os.Stat(filepath.Dir(path)); os.IsNotExist(err) {
return "", fmt.Errorf("the directory %s does not exist", filepath.Dir(path))
Expand Down
43 changes: 26 additions & 17 deletions internal/processor.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,15 +10,16 @@ import (
)

type PluginProcessor struct {
Args Args
Args Args
Benchmark *BenchmarkResult
}

func (p PluginProcessor) Build() error {
cmd := exec.Command("go", "build", "-buildmode=plugin", "-o", p.Args.path+".so", p.Args.path+".go")
cmd.Stdout = os.Stdout
cmd.Stderr = os.Stderr

fmt.Printf("\nCreating plugin: %s\n", cmd.String())
fmt.Printf("\nBuilding: %s", cmd.String())
if err := cmd.Run(); err != nil {
return fmt.Errorf("error running command: %v", err)
}
Expand All @@ -41,7 +42,7 @@ func (p PluginProcessor) CallFunc(input *[]byte) (string, error) {
// Assert that the symbol is a function with the expected signature
processFunc, ok := symProcess.(func(string) string)
if !ok {
return "", fmt.Errorf("unexpected function signature")
return "", fmt.Errorf("expected func(string) string, got %T", symProcess)
}

// Call the function with an input variable
Expand Down Expand Up @@ -80,11 +81,19 @@ func (p PluginProcessor) GetInput() (*[]byte, error) {
return &data, nil
}

func GetAllPluginProcessors(args Args) ([]PluginProcessor, error) {
var baseDir = filepath.Join("./", args.Year)
var processors []PluginProcessor
type Path int

err := filepath.Walk(baseDir, func(path string, info os.FileInfo, err error) error {
const (
year Path = iota
day
part
)

func GetProcessors(args Args) ([]PluginProcessor, error) {
dir := filepath.Join("./", args.Year)
processors := make([]PluginProcessor, 0)

err := filepath.Walk(dir, func(path string, info os.FileInfo, err error) error {
if err != nil {
return err
}
Expand All @@ -98,38 +107,38 @@ func GetAllPluginProcessors(args Args) ([]PluginProcessor, error) {
return nil
}

if !strings.HasPrefix(parts[1], "day") {
if !strings.HasPrefix(parts[day], "day") || (args.Day != "0" && parts[day] != "day"+args.Day) {
return nil
}

if !strings.HasPrefix(parts[2], "part") || strings.Contains(parts[2], "test") || !strings.HasSuffix(parts[2], ".go") {
if !strings.HasPrefix(parts[part], "part") || strings.Contains(parts[part], "test") || !strings.HasSuffix(parts[part], ".go") {
return nil
}

year := parts[0]
day := parts[1][3:]
part := parts[2][4 : len(parts[2])-3]
if args.Part != "0" && parts[part] != "part"+args.Part+".go" {
return nil
}

args := Args{
Year: year,
Day: day,
Part: part,
Year: parts[year],
Day: parts[day][3:],
Part: parts[part][4 : len(parts[part])-3],
}
args.path, err = args.getPath()
if err != nil {
return err
}

processors = append(processors, PluginProcessor{
Args: args,
Args: args,
Benchmark: &BenchmarkResult{},
})

return nil
})

if err != nil {
fmt.Println("Error scanning directories:", err)

return nil, err
}

Expand Down
80 changes: 33 additions & 47 deletions runner.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,75 +4,61 @@ import (
"fmt"
"os"
"text/tabwriter"
"time"

internal "github.com/igorwulff/aoc/internal"
)

type BenchmarkResult struct {
TotalTimeInMs int64
}

func Run() ([]BenchmarkResult, error) {
func Run() {
args := internal.ProcessArgs()
var plugins []internal.PluginProcessor
// Benchmarking mode
if args.Day == "0" {
allPlugins, err := internal.GetAllPluginProcessors(args)
if err != nil {
fmt.Println(err)
return nil, err
}
plugins = append(plugins, allPlugins...)
} else {
plugins = append(plugins, internal.PluginProcessor{Args: args})
plugins, err := internal.GetProcessors(args)
if err != nil {
fmt.Println(err)
return
}

results := make([]BenchmarkResult, len(plugins))
for i, plugin := range plugins {
input, err := plugin.GetInput()
for _, p := range plugins {
input, err := p.GetInput()
if err != nil {
fmt.Printf("Could not find input.txt for Day %s Part %s\n", plugin.Args.Day, plugin.Args.Part)
return nil, err
fmt.Printf("Could not find input.txt for Day %s Part %s\n", p.Args.Day, p.Args.Part)
return
}

fmt.Printf("Building day %s part %s... ", plugin.Args.Day, plugin.Args.Part)
if err := plugin.Build(); err != nil {
fmt.Print("ERROR!\n")
fmt.Println(err)
return nil, err
fmt.Printf("Running day %s, part %s", p.Args.Day, p.Args.Part)

if err := p.Build(); err != nil {
fmt.Print("ERROR!\n", err)
return
}
fmt.Print("OK!\n")

fmt.Print("Executing tests... ")
if err := plugin.RunTests(); err != nil {
fmt.Print("ERROR!\n")
fmt.Println(err)
return nil, err
if err := p.RunTests(); err != nil {
fmt.Print("ERROR!\n", err)
return
}

fmt.Print("Executing main function... ")
timeBeforeExec := time.Now().UnixMilli()
output, err := plugin.CallFunc(input)
fmt.Println("Trying to solve puzzle...")

p.Benchmark.StartTimer()
output, err := p.CallFunc(input)
if err != nil {
fmt.Print("ERROR!\n")
fmt.Println(err)
return nil, err
fmt.Print("ERROR!\n", err)
return
}
timeAfterExec := time.Now().UnixMilli()
results[i] = BenchmarkResult{TotalTimeInMs: timeAfterExec - timeBeforeExec}
p.Benchmark.StopTimer()

fmt.Printf("Solution: %s\n", output)
fmt.Printf("Solution: %s\n\n", output)
}

fmt.Println("Execution finished! Total time:")
fmt.Println("Execution finished!")
w := tabwriter.NewWriter(os.Stdout, 0, 4, 4, ' ', 0)
fmt.Fprintln(w, "Day\tPart\tTime (ms)")
for i, plugin := range plugins {
fmt.Fprintln(w, "\nDay\tPart\tTime (ms)")

var sum int64 = 0
for _, p := range plugins {
sum += p.Benchmark.GetTotalTimeInMs()
// @TODO: would be nice to join day & parts in a single row, but for now it's already nice they're alphabetically sorted
fmt.Fprintf(w, "%s\t%s\t%d\n", plugin.Args.Day, plugin.Args.Part, results[i].TotalTimeInMs)
fmt.Fprintf(w, "%s\t%s\t%d\n", p.Args.Day, p.Args.Part, p.Benchmark.GetTotalTimeInMs())
}
w.Flush()

return results, nil
fmt.Printf("\nTotal time: %d ms\n", sum)
}

0 comments on commit 71b3daa

Please sign in to comment.