// Generates a report with the amount of time for each operation in the domain DAO. For // more realistic values it does the same operation for the same amount of data X number // of times to get the average time of the operation. After some results, with indexes we // get 80% better performance, another good improvements was to create and remove many // objects at once using go routines func domainDAOPerformanceReport(reportFile string, domainDAO dao.DomainDAO) { // Report header report := " # | Total | Insert | Find | Remove\n" + "------------------------------------------------------------------------------------\n" // Report variables averageTurns := 5 scale := []int{10, 50, 100, 500, 1000, 5000, 10000, 50000, 100000, 500000, 1000000, 5000000} for _, numberOfItems := range scale { var totalDuration, insertDuration, queryDuration, removeDuration time.Duration for i := 0; i < averageTurns; i++ { utils.Println(fmt.Sprintf("Generating report - scale %d - turn %d", numberOfItems, i+1)) totalDurationTmp, insertDurationTmp, queryDurationTmp, removeDurationTmp := calculateDomainDAODurations(domainDAO, numberOfItems) totalDuration += totalDurationTmp insertDuration += insertDurationTmp queryDuration += queryDurationTmp removeDuration += removeDurationTmp } report += fmt.Sprintf("% -8d | % 16s | % 16s | % 16s | % 16s\n", numberOfItems, time.Duration(int64(totalDuration)/int64(averageTurns)).String(), time.Duration(int64(insertDuration)/int64(averageTurns)).String(), time.Duration(int64(queryDuration)/int64(averageTurns)).String(), time.Duration(int64(removeDuration)/int64(averageTurns)).String(), ) } utils.WriteReport(reportFile, report) }
// Generates a report with the amount of time of a scan func scanReport(domainDAO dao.DomainDAO, scanDAO dao.ScanDAO, scanConfig ScanTestConfigFile) { report := " # | Total | DPS | Memory (MB)\n" + "-----------------------------------------------------\n" // Report variables scale := []int{10, 50, 100, 500, 1000, 5000, 10000, 50000, 100000, 500000, 1000000, 5000000} dnskey, privateKey, err := utils.GenerateKey() if err != nil { utils.Fatalln("Error generating DNSKEY", err) } reportHandler := ReportHandler{ DNSKEY: dnskey, PrivateKey: privateKey, } server.Handler = reportHandler dns.DefaultServeMux = nil for _, numberOfItems := range scale { utils.Println(fmt.Sprintf("Generating report - scale %d", numberOfItems)) for i := 0; i < numberOfItems; i++ { if i%1000 == 0 { utils.PrintProgress("building scenario", (i*100)/numberOfItems) } fqdn := fmt.Sprintf("domain%d.br.", i) generateAndSaveDomain(fqdn, domainDAO, dnskey) } utils.PrintProgress("building scenario", 100) totalDuration, domainsPerSecond := calculateScanDurations(numberOfItems, scanDAO) var memStats runtime.MemStats runtime.ReadMemStats(&memStats) report += fmt.Sprintf("% -8d | %16s | %4d | %14.2f\n", numberOfItems, time.Duration(int64(totalDuration)).String(), domainsPerSecond, float64(memStats.Alloc)/float64(MB), ) if err := domainDAO.RemoveAll(); err != nil { // When the result set is too big to remove, we got a timeout error from the // connection, but it's ok //utils.Fatalln("Error removing domains generated for report", err) } } utils.WriteReport(scanConfig.Report.File, report) }
func restReport(restConfig RESTTestConfigFile) { report := " # | Operation | Total | DPS | Memory (MB)\n" + "---------------------------------------------------------------\n" // Report variables scale := []int{10, 50, 100, 500, 1000, 5000, 10000, 50000, 100000, 500000, 1000000, 5000000} content := []byte(`{ "Nameservers": [ { "host": "ns1.example.com.br.", "ipv4": "127.0.0.1" }, { "host": "ns2.example.com.br.", "ipv6": "::1" } ], "Owners": [ { "email": "*****@*****.**", "language": "pt-br" } ] }`) url := "" if len(config.ShelterConfig.RESTServer.Listeners) > 0 { url = fmt.Sprintf("http://%s:%d", config.ShelterConfig.RESTServer.Listeners[0].IP, config.ShelterConfig.RESTServer.Listeners[0].Port) } if len(url) == 0 { utils.Fatalln("There's no interface to connect to", nil) } for _, numberOfItems := range scale { utils.Println(fmt.Sprintf("Generating report - scale %d", numberOfItems)) // Generate domains report += restActionReport(numberOfItems, content, func(i int) (*http.Request, error) { return http.NewRequest("PUT", fmt.Sprintf("%s/domain/example%d.com.br.", url, i), bytes.NewReader(content)) }, http.StatusCreated, "CREATE") // Retrieve domains report += restActionReport(numberOfItems, content, func(i int) (*http.Request, error) { return http.NewRequest("GET", fmt.Sprintf("%s/domain/example%d.com.br.", url, i), nil) }, http.StatusOK, "RETRIEVE") // Delete domains report += restActionReport(numberOfItems, content, func(i int) (*http.Request, error) { return http.NewRequest("DELETE", fmt.Sprintf("%s/domain/example%d.com.br.", url, i), nil) }, http.StatusNoContent, "DELETE") } utils.WriteReport(restConfig.Report.File, report) }
// Generates a report with the result of a scan in the root zone file, it should be last // last thing from the test, because it changes the DNS test port to the original one for // real tests func inputScanReport(config ScanQuerierTestConfigFile) { // Move back to default port, because we are going to query the world for real to check // querier performance scan.DNSPort = 53 // As we are using the same domains repeatedly we should be careful about how many // requests we send to only one host to avoid abuses. This value should be beteween 5 // and 10 scan.MaxQPSPerHost = 5 report := " # | Total | QPS | Memory (MB)\n" + "---------------------------------------------------\n" domains, err := readInputFile(config.Report.InputFile) if err != nil { utils.Fatalln("Error while loading input data for report", err) } nameserverStatusCounter := 0 nameserversStatus := make(map[model.NameserverStatus]int) dsStatusCounter := 0 dsSetStatus := make(map[model.DSStatus]int) totalDuration, queriesPerSecond, nameserversStatus, dsSetStatus := calculateScanQuerierDurations(config, domains) var memStats runtime.MemStats runtime.ReadMemStats(&memStats) report += fmt.Sprintf("% -8d | %16s | %4d | %14.2f\n", len(domains), time.Duration(int64(totalDuration)).String(), queriesPerSecond, float64(memStats.Alloc)/float64(MB), ) report += "\nNameserver Status\n" + "-----------------\n" for _, counter := range nameserversStatus { nameserverStatusCounter += counter } for status, counter := range nameserversStatus { report += fmt.Sprintf("%16s: % 3.2f%%\n", model.NameserverStatusToString(status), (float64(counter*100) / float64(nameserverStatusCounter)), ) } report += "\nDS Status\n" + "---------\n" for _, counter := range dsSetStatus { dsStatusCounter += counter } for status, counter := range dsSetStatus { report += fmt.Sprintf("%16s: % 3.2f%%\n", model.DSStatusToString(status), (float64(counter*100) / float64(dsStatusCounter)), ) } utils.WriteReport(config.Report.OutputFile, report) }
// Generates a report with the amount of time of a scan func scanQuerierReport(config ScanQuerierTestConfigFile) { report := " # | Total | QPS | Memory (MB)\n" + "-----------------------------------------------------\n" // Report variables scale := []int{10, 50, 100, 500, 1000, 5000, 10000, 50000, 100000, 500000, 1000000, 5000000} fqdn := "domain.com.br." dnskey, rrsig, err := utils.GenerateKSKAndSignZone(fqdn) if err != nil { utils.Fatalln("Error creating DNSSEC keys and signatures", err) } ds := dnskey.ToDS(uint8(model.DSDigestTypeSHA1)) dns.HandleFunc(fqdn, func(w dns.ResponseWriter, dnsRequestMessage *dns.Msg) { defer w.Close() if dnsRequestMessage.Question[0].Qtype == dns.TypeSOA { dnsResponseMessage := &dns.Msg{ MsgHdr: dns.MsgHdr{ Authoritative: true, }, Question: dnsRequestMessage.Question, Answer: []dns.RR{ &dns.SOA{ Hdr: dns.RR_Header{ Name: fqdn, Rrtype: dns.TypeSOA, Class: dns.ClassINET, Ttl: 86400, }, Ns: "ns1." + fqdn, Mbox: "rafael.justo.net.br.", Serial: 2013112600, Refresh: 86400, Retry: 86400, Expire: 86400, Minttl: 900, }, }, } dnsResponseMessage.SetReply(dnsRequestMessage) w.WriteMsg(dnsResponseMessage) } else if dnsRequestMessage.Question[0].Qtype == dns.TypeDNSKEY { dnsResponseMessage := &dns.Msg{ MsgHdr: dns.MsgHdr{ Authoritative: true, }, Question: dnsRequestMessage.Question, Answer: []dns.RR{ dnskey, rrsig, }, } dnsResponseMessage.SetReply(dnsRequestMessage) w.WriteMsg(dnsResponseMessage) } }) for _, numberOfItems := range scale { var domains []*model.Domain for i := 0; i < numberOfItems; i++ { // We create an object with different nameservers because we don't want to put the // nameserver in the query rate limit check domains = append(domains, &model.Domain{ FQDN: fqdn, Nameservers: []model.Nameserver{ { Host: fmt.Sprintf("ns%d.%s", i, fqdn), IPv4: net.ParseIP("127.0.0.1"), }, }, DSSet: []model.DS{ { Keytag: dnskey.KeyTag(), Algorithm: utils.ConvertKeyAlgorithm(dnskey.Algorithm), DigestType: model.DSDigestTypeSHA1, Digest: ds.Digest, }, }, }) } utils.Println(fmt.Sprintf("Generating report - scale %d", numberOfItems)) totalDuration, queriesPerSecond, _, _ := calculateScanQuerierDurations(config, domains) var memStats runtime.MemStats runtime.ReadMemStats(&memStats) report += fmt.Sprintf("% -8d | %16s | %4d | %14.2f\n", numberOfItems, time.Duration(int64(totalDuration)).String(), queriesPerSecond, float64(memStats.Alloc)/float64(MB), ) } utils.WriteReport(config.Report.ReportFile, report) }