"flag"
"fmt"
"log"
+ "os"
+ "runtime/pprof"
+ "strconv"
)
// =============================================================================
// =============================================================================
func main() {
+ // Flags to enable various performance profiling options.
+ cpuProfile := flag.String("cpuprofile", "", "Filename for saving CPU profile output.")
+ memProfilePrefix := flag.String("memprofileprefix", "", "Filename PREFIX for saving memory profile output.")
+ suppressOutput := flag.Bool("silent", false, "Suppress printing of numberline at end of simulation. Useful when profiling.")
+
// Obtain termination conditions from user.
totalGenerations := flag.Int("generations", 2, "Number of generations of surreal numbers to breed.")
flag.Parse()
}
remainingGenerations := *totalGenerations - 1
+ // Setup any CPU performance profiling requested by the user. This will run
+ // throughout program execution.
+ if *cpuProfile != "" {
+ cpuProFile, err := os.Create(*cpuProfile)
+ if err != nil {
+ log.Fatal("ERROR: Unable to open CPU profiling output file:", err)
+ }
+ pprof.StartCPUProfile(cpuProFile)
+ defer pprof.StopCPUProfile()
+ }
+
// Build a universe to contain all the surreal numbers we breed.
// Seed it by hand with the number zero as generation-0.
var universe surrealUniverse
// add them all to the universe.
fmt.Printf("Breeding Generation:")
for generation := 1; generation <= remainingGenerations; generation++ {
+ // Give the user some idea of overall progress during long jobs.
if generation != 1 {
fmt.Printf(",")
}
fmt.Printf(" %d", generation)
+
// First generate all possible reduced form symbols per Axiom 1.
potentialNumbers := permuteExistingNumbers(generation, universe)
// Now prune out any symbols which are NOT valid numbers per Axiom 2.
// Attempt to add the new numbers to the universe. Any duplicates will
// be weeded out in the attempt.
addNumbersToUniverse(validNumbers, &universe)
+
+ // Setup any memory profiling requested by the user. This will snapshot
+ // the heap at the end of every generation.
+ if *memProfilePrefix != "" {
+ memProFile, err := os.Create(*memProfilePrefix + "-gen" + strconv.Itoa(generation) + ".mprof")
+ if err != nil {
+ log.Fatal("ERROR: Unable to write heap profile to disk:", err)
+ }
+ pprof.WriteHeapProfile(memProFile)
+ memProFile.Close()
+ }
}
fmt.Printf(".\n")
+
// Print the number line with generation on the horizontal axis and
// magnitude on the vertical axis.
- for i := 0; i < universe.cardinality(); i++ {
- printlnNumber(universe.numbers[i])
+ if !(*suppressOutput) {
+ for i := 0; i < universe.cardinality(); i++ {
+ printlnNumber(universe.numbers[i])
+ }
}
fmt.Println("After", *totalGenerations, "generations, the universe contains", len(universe.numbers), "numbers.")
fmt.Println("If output looks poor, ensure tabstop is eight spaces and that output doesn't wrap.")