Explorar o código

adding aah framework into benchmark [ci fw Go/aah] (#2859)

* adding aah framework into benchmark [ci fw Go/aah]

* added readme for the test [ci skip]

* Create benchmark_config.json
Jeevanandam M %!s(int64=8) %!d(string=hai) anos
pai
achega
06414b5370

+ 1 - 0
.travis.yml

@@ -52,6 +52,7 @@ env:
     - "TESTDIR=Erlang/cowboy"
     - "TESTDIR=Erlang/elli"
     - "TESTDIR=Erlang/mochiweb"
+    - "TESTDIR=Go/aah"
     - "TESTDIR=Go/beego"
     - "TESTDIR=Go/echo"
     - "TESTDIR=Go/falcore"

+ 2 - 0
frameworks/Go/aah/.gitignore

@@ -0,0 +1,2 @@
+bin/
+pkg/

+ 22 - 0
frameworks/Go/aah/README.md

@@ -0,0 +1,22 @@
+# [aah framework](https://aahframework.org) Benchmarking Test
+
+This is the `Go` portion of a [benchmarking test suite](../) comparing a variety of web development platforms.
+
+> **aah framework** is a scalable, performant, rapid development Web framework for Go. aah focuses on very small footprint, maintainability, performance, configurability, security and extensibility as application use cases expands.
+
+**|**  [Getting started](https://docs.aahframework.org/getting-started.html) **|** [Features](https://aahframework.org/features.html) **|** [Documentation](https://docs.aahframework.org) **|**
+
+Requires ≥ go1.8
+
+## Source
+
+  * [Test source files](source_code)
+
+## Test URLs
+
+  * http://localhost:8080/json
+  * http://localhost:8080/db
+  * http://localhost:8080/queries?count=[1-500]
+  * http://localhost:8080/fortunes
+  * http://localhost:8080/updates?count=[1-500]
+  * http://localhost:8080/plaintext

+ 29 - 0
frameworks/Go/aah/benchmark_config.json

@@ -0,0 +1,29 @@
+{
+  "framework": "aah",
+  "tests": [{
+    "default": {
+      "setup_file": "setup",
+      "json_url": "/json",
+      "db_url": "/db",
+      "query_url": "/queries?count=",
+      "fortune_url": "/fortunes",
+      "update_url": "/updates?count=",
+      "plaintext_url": "/plaintext",
+      "port": 8080,
+      "approach": "Realistic",
+      "classification": "Fullstack",
+      "database": "MySQL",
+      "framework": "aah",
+      "language": "Go",
+      "flavor": "None",
+      "orm": "Raw",
+      "platform": "None",
+      "webserver": "None",
+      "os": "Linux",
+      "database_os": "Linux",
+      "display_name": "aah-framework",
+      "notes": "",
+      "versus": "go"
+    }
+  }]
+}

+ 31 - 0
frameworks/Go/aah/setup.sh

@@ -0,0 +1,31 @@
+#!/bin/bash
+
+fw_depends mysql go
+
+set -x
+
+mkdir bin
+
+# Install aah CLI tool and glide
+go get aahframework.org/tools.v0/aah
+curl https://glide.sh/get | sh
+
+# Clean src directory, glide is used to get dependencies libraries
+rm -rf src/aahframework.org
+rm -rf src/golang.org
+
+# print version
+aah version
+glide -v
+
+# Run glide to get dependencies
+cd src/benchmark
+glide install
+
+# Build and unpack
+aah build
+cd build
+unzip benchmark-0.0.1-linux-amd64.zip
+
+# Start server
+./benchmark/aah.sh start

+ 14 - 0
frameworks/Go/aah/source_code

@@ -0,0 +1,14 @@
+./aah/src/benchmark/.gitignore
+./aah/src/benchmark/aah.project
+./aah/src/benchmark/app/controllers/app.go
+./aah/src/benchmark/app/db/datasource.go
+./aah/src/benchmark/app/models/models.go
+./aah/src/benchmark/config/aah.conf
+./aah/src/benchmark/config/env/dev.conf
+./aah/src/benchmark/config/env/prod.conf
+./aah/src/benchmark/config/routes.conf
+./aah/src/benchmark/config/security.conf
+./aah/src/benchmark/glide.lock
+./aah/src/benchmark/glide.yaml
+./aah/src/benchmark/views/layouts/master.html
+./aah/src/benchmark/views/pages/app/fortunes.html

+ 30 - 0
frameworks/Go/aah/src/benchmark/.gitignore

@@ -0,0 +1,30 @@
+# aah framework application - .gitignore
+
+aah.go
+*.pid
+build/
+
+# Compiled Object files, Static and Dynamic libs (Shared Objects)
+*.o
+*.a
+*.so
+
+# Folders
+_obj
+_test
+
+# Architecture specific extensions/prefixes
+*.[568vq]
+[568vq].out
+
+*.cgo1.go
+*.cgo2.c
+_cgo_defun.c
+_cgo_gotypes.go
+_cgo_export.*
+
+_testmain.go
+
+*.exe
+*.test
+*.prof

+ 43 - 0
frameworks/Go/aah/src/benchmark/aah.project

@@ -0,0 +1,43 @@
+########################################
+# benchmark - aah framework project
+#
+# Note: Add it to version control
+########################################
+
+# Build section is used during aah application compile and build command.
+build {
+  # Application binary name
+  # Default value is `name` attribute value from `aah.conf`
+  #binary_name = "benchmark"
+
+  # Used as fallback if
+  #   - `git commit sha` or
+  #   - `AAH_APP_VERSION` environment value is not available.
+  version = "0.0.1"
+
+  # If application is missing any dependencies in `build import path`
+  # during a compile and build, aah CLI will try to get dependencies
+  # using 'go get <package>'.
+  # Default value is `false`.
+  #dep_get = true
+
+  # Log level is used for aah CLI tool logging.
+  # Default value is `info`.
+  #log_level = "info"
+
+  flags = ["-i"]
+
+  ldflags = ""
+
+  tags = ""
+
+  # AST excludes is used for `aah.Context` inspection and generating aah
+  # application main Go file. Valid exclude patterns
+  # refer: https://golang.org/pkg/path/filepath/#Match
+  ast_excludes = ["*_test.go", ".*", "*.bak", "*.tmp", "vendor"]
+
+  # Packing excludes is used to exclude file/directory during aah application
+  # build archive. Valid exclude patterns
+  # refer: https://golang.org/pkg/path/filepath/#Match
+  excludes = ["*.go", "*_test.go", ".*", "*.bak", "*.tmp", "vendor", "app", "build", "tests", "logs"]
+}

+ 94 - 0
frameworks/Go/aah/src/benchmark/app/controllers/app.go

@@ -0,0 +1,94 @@
+package controllers
+
+import (
+	"strconv"
+	"strings"
+	"sync"
+
+	"benchmark/app/models"
+
+	"aahframework.org/aah.v0"
+	"aahframework.org/ahttp.v0"
+)
+
+var (
+	helloWorldMsg = "Hello, World!"
+	messagePool   = sync.Pool{New: func() interface{} { return &models.Message{} }}
+)
+
+// AppController struct application controller
+type AppController struct {
+	*aah.Context
+}
+
+// Plaintext method is for `/plaintext` test.
+func (a *AppController) Plaintext() {
+	a.Reply().Text(helloWorldMsg)
+}
+
+// JSON method is for `/json` test.
+func (a *AppController) JSON() {
+	m := messagePool.Get().(*models.Message)
+	m.Message = helloWorldMsg
+	a.Reply().JSON(m)
+}
+
+// GetWorld returns one world record randomly for `/db` test.
+func (a *AppController) GetWorld() {
+	world := new(models.World)
+	if err := models.FetchRandomWorld(world); err != nil {
+		a.Reply().InternalServerError().Text(err.Error())
+		return
+	}
+	a.Reply().JSON(world)
+}
+
+// GetWorlds returns one world record randomly for `/queries` test.
+func (a *AppController) GetWorlds() {
+	a.handleResult(models.GetRandomWorlds(a.getCount()))
+}
+
+// UpdateWorlds updates record and returns those records for `/updates` test.
+func (a *AppController) UpdateWorlds() {
+	a.handleResult(models.UpdateRandomWorlds(a.getCount()))
+}
+
+// Fortunes method is for `/fortunes` test.
+func (a *AppController) Fortunes() {
+	fortunes, err := models.GetFortunes()
+	if err != nil {
+		a.Reply().InternalServerError().Text(err.Error())
+		return
+	}
+
+	a.Reply().HTML(aah.Data{
+		"Fortunes": fortunes,
+	})
+}
+
+// Finally interceptor
+func (a *AppController) Finally() {
+	// TFB requirements
+	// Removing charset for json and plaintext
+	if !strings.HasPrefix(a.Reply().ContType, ahttp.ContentTypeHTML.Mime) {
+		a.Reply().ContType = a.Reply().ContType[:strings.IndexByte(a.Reply().ContType, ';')]
+	}
+}
+
+func (a *AppController) getCount() int {
+	cnt, err := strconv.Atoi(a.Req.QueryValue("count"))
+	if err != nil || cnt < 1 {
+		cnt = 1
+	} else if cnt > 500 {
+		cnt = 500
+	}
+	return cnt
+}
+
+func (a *AppController) handleResult(worlds *[]models.World, err error) {
+	if err != nil {
+		a.Reply().InternalServerError().Text(err.Error())
+		return
+	}
+	a.Reply().JSON(worlds)
+}

+ 60 - 0
frameworks/Go/aah/src/benchmark/app/db/datasource.go

@@ -0,0 +1,60 @@
+package db
+
+import (
+	"database/sql"
+	"fmt"
+	"os"
+	"runtime"
+
+	"aahframework.org/aah.v0"
+	"aahframework.org/log.v0"
+
+	// mysql driver
+	_ "github.com/go-sql-driver/mysql"
+)
+
+var (
+	maxConnsCount = runtime.NumCPU() * 2
+	db            *sql.DB
+)
+
+// DB instance
+func DB() *sql.DB {
+	return db
+}
+
+// DatabaseInit initializes the Database.
+func DatabaseInit(e *aah.Event) {
+	cfg := aah.AppConfig()
+	dbHost := os.Getenv("DBHOST")
+	if dbHost == "" {
+		dbHost = "localhost"
+	}
+
+	dbURL := fmt.Sprintf(cfg.StringDefault("datasource.benchmark.url", ""), dbHost)
+
+	var err error
+	db, err = sql.Open(cfg.StringDefault("datasource.benchmark.driver", ""), dbURL)
+	if err != nil {
+		log.Fatal(err)
+	}
+
+	if err = db.Ping(); err != nil {
+		log.Fatal(err)
+	}
+
+	db.SetMaxIdleConns(maxConnsCount)
+	db.SetMaxOpenConns(maxConnsCount)
+}
+
+// DatabaseClose initializes the Database.
+func DatabaseClose(e *aah.Event) {
+	if db != nil {
+		_ = db.Close()
+	}
+}
+
+func init() {
+	aah.OnStart(DatabaseInit)
+	aah.OnShutdown(DatabaseClose)
+}

+ 140 - 0
frameworks/Go/aah/src/benchmark/app/models/models.go

@@ -0,0 +1,140 @@
+package models
+
+import (
+	"benchmark/app/db"
+	"database/sql"
+	"math/rand"
+	"sort"
+
+	"aahframework.org/aah.v0"
+	"aahframework.org/log.v0"
+)
+
+var (
+	// Prepare statements
+	worldSelectStmt   *sql.Stmt
+	worldUpdateStmt   *sql.Stmt
+	fortuneSelectStmt *sql.Stmt
+
+	worldRowCount = 10000
+)
+
+type (
+	// Message is used for JSON reply.
+	Message struct {
+		Message string `json:"message"`
+	}
+
+	// World is used for database operation.
+	World struct {
+		ID           uint16 `json:"id"`
+		RandomNumber uint16 `json:"randomNumber"`
+	}
+
+	// Fortune is used for database and reply.
+	Fortune struct {
+		ID      uint16 `json:"id"`
+		Message string `json:"message"`
+	}
+
+	// Fortunes slice
+	Fortunes []*Fortune
+
+	// For sorting
+	byMessage struct{ Fortunes }
+)
+
+//‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾
+// Global methods
+//___________________________________
+
+// FetchRandomWorld method returns one world record info.
+func FetchRandomWorld(w *World) error {
+	err := worldSelectStmt.QueryRow(randomWorldNum()).Scan(&w.ID, &w.RandomNumber)
+	return err
+}
+
+// GetRandomWorlds method returns world record from db randomly.
+func GetRandomWorlds(count int) (*[]World, error) {
+	worlds := make([]World, count)
+	var err error
+	for i := 0; i < count; i++ {
+		w := &worlds[i]
+		if err = FetchRandomWorld(w); err != nil {
+			return nil, err
+		}
+	}
+	return &worlds, nil
+}
+
+// UpdateRandomWorlds method updates random world records.
+func UpdateRandomWorlds(count int) (*[]World, error) {
+	worlds := make([]World, count)
+	var err error
+	for i := 0; i < count; i++ {
+		w := &worlds[i]
+		if err = FetchRandomWorld(w); err != nil {
+			return nil, err
+		}
+
+		w.RandomNumber = uint16(randomWorldNum())
+		if _, err = worldUpdateStmt.Exec(w.RandomNumber, w.ID); err != nil {
+			return nil, err
+		}
+	}
+	return &worlds, nil
+}
+
+// GetFortunes method returns fortunes records
+func GetFortunes() (Fortunes, error) {
+	rows, err := fortuneSelectStmt.Query()
+	if err != nil {
+		return nil, err
+	}
+
+	fortunes := make(Fortunes, 0, 16)
+	for rows.Next() {
+		var fortune Fortune
+		if err = rows.Scan(&fortune.ID, &fortune.Message); err != nil {
+			return nil, err
+		}
+		fortunes = append(fortunes, &fortune)
+	}
+	_ = rows.Close()
+
+	fortunes = append(fortunes, &Fortune{Message: "Additional fortune added at request time."})
+	sort.Sort(byMessage{fortunes})
+	return fortunes, nil
+}
+
+//‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾
+// Unexported methods
+//___________________________________
+
+func randomWorldNum() int {
+	return rand.Intn(worldRowCount) + 1
+}
+
+func prepareStatements(e *aah.Event) {
+	var err error
+	if worldSelectStmt, err = db.DB().Prepare("SELECT id, randomNumber FROM World WHERE id = ?"); err != nil {
+		log.Fatal(err)
+	}
+
+	if worldUpdateStmt, err = db.DB().Prepare("UPDATE World SET randomNumber = ? WHERE id = ?"); err != nil {
+		log.Fatal(err)
+	}
+
+	if fortuneSelectStmt, err = db.DB().Prepare("SELECT id, message FROM Fortune"); err != nil {
+		log.Fatal(err)
+	}
+}
+
+// Sorting interfaces
+func (s Fortunes) Len() int            { return len(s) }
+func (s Fortunes) Swap(i, j int)       { s[i], s[j] = s[j], s[i] }
+func (s byMessage) Less(i, j int) bool { return s.Fortunes[i].Message < s.Fortunes[j].Message }
+
+func init() {
+	aah.OnStart(prepareStatements, 2)
+}

+ 299 - 0
frameworks/Go/aah/src/benchmark/config/aah.conf

@@ -0,0 +1,299 @@
+###################################################
+# benchmark - aah framework application
+#
+# Complete configuration reference:
+#   https://docs.aahframework.org/app-config.html
+###################################################
+
+# Application name (non-whitespace)
+# Default value is `basename` of import path.
+name = "benchmark"
+
+# Friendly description of application
+desc = "aah framework web application"
+
+# -----------------------------------------------------------------
+# Server configuration - HTTP
+# Doc: https://docs.aahframework.org/app-config.html#section-server
+# -----------------------------------------------------------------
+server {
+  # For unix socket: unix:/tmp/aahframework.sock
+  # Default value is `empty` string.
+  #address = ""
+
+  # For port `80` and `443`, put empty string or a value
+  # Default value is 8080.
+  #port = ""
+
+  # Valid time units are "s = seconds", "m = minutes"
+  timeout {
+    # mapped to `http.Server.ReadTimeout`.
+    # Default value is `90s`.
+    #read = "90s"
+
+    # mapped to `http.Server.WriteTimeout`
+    # Default value is `90s`.
+    #write = "90s"
+
+    # aah sever graceful shutdown timeout
+    # Note: applicable only to go1.8 and above
+    # Default value is `60s`.
+    #grace_shutdown = "60s"
+  }
+
+  # Mapped to `http.Server.MaxHeaderBytes`.
+  # Default value is `1mb`.
+  #max_header_bytes = "1mb"
+
+  # HTTP server keep alive option.
+  # Default value is `true`.
+  #keep_alive = true
+
+  ssl {
+    # Default value is `false`.
+    #enable = false
+
+    # Default value is `empty` string.
+    #cert = ""
+
+    # Default value is `empty` string.
+    #key = ""
+
+    # Disabling HTTP/2 set it true.
+    # Default value is `false`.
+    #disable_http2 = true
+
+    lets_encrypt {
+      # To get SSL certificate from Let's Encrypt CA, enable it.
+      # Don't forget to enable `server.ssl.enable=true`.
+      # Default value is `false`.
+      #enable = false
+
+      # Host policy controls which domains the autocert will attempt
+      # to retrieve new certificates for. It does not affect cached certs.
+      # It is required, no default value.
+      #host_policy = ["example.org", "docs.example.org"]
+
+      # Renew before optionally specifies how early certificates should
+      # be renewed before they expire.
+      # Default value is `10` days.
+      #renew_before = 10
+
+      # Email optionally specifies a contact email address. This is used by CAs,
+      # such as Let's Encrypt, to notify about problems with issued certificates.
+      # If the Client's account key is already registered, Email is not used.
+      #email = "[email protected]"
+
+      # Force RSA makes the autocert generate certificates with 2048-bit RSA keys.
+      # If false, a default is used. Currently the default is
+      # EC-based keys using the P-256 curve.
+      #force_rsa = false
+
+      # Cache optionally stores and retrieves previously-obtained certificates
+      # autocert manager. By default certs will only be cached for the lifetime
+      # of the autocert manager.
+      #
+      # autocert manager passes the Cache certificates data encoded in PEM,
+      # with private/public parts combined in a single Cache.Put call,
+      # private key first.
+      # Default value is `empty` string
+      #cache_dir = "/Users/jeeva/autocert"
+    }
+  }
+}
+
+# ------------------------------------------------------------------
+# Request configuration
+# Doc: https://docs.aahframework.org/app-config.html#section-request
+# ------------------------------------------------------------------
+request {
+
+  # aah framework encourages to have unique `Request Id` for each incoming
+  # request, it helps in traceability. If request has already `X-Request-Id`
+  # HTTP header then it does not generate one.
+  id {
+    # Default value is `true`.
+    enable = false
+
+    # Default value is `X-Request-Id`, change it if you have different one.
+    #header = "X-Request-Id"
+  }
+
+  # Default value is `32mb`, choose your value based on your use case
+  #multipart_size = "32mb"
+}
+
+# ---------------------------------------------------------------
+# i18n configuration
+# Doc: https://docs.aahframework.org/app-config.html#section-i18n
+# ---------------------------------------------------------------
+i18n {
+  # It is used as fallback if framework is unable to determine the
+  # locale from HTTP Request.
+  # Default value is `en`.
+  #default = "en"
+}
+
+# -----------------------------------------------------------------
+# Format configuration
+# Doc: https://docs.aahframework.org/app-config.html#section-format
+# -----------------------------------------------------------------
+format {
+  # Default value is `2006-01-02`.
+  #date = "2006-01-02"
+
+  # Default value is `2006-01-02 15:04:05`.
+  #datetime = "2006-01-02 15:04:05"
+}
+
+# ------------------------------------------------------------------
+# Runtime configuration
+# Doc: https://docs.aahframework.org/app-config.html#section-runtime
+# ------------------------------------------------------------------
+runtime {
+  debug {
+    # Choose an appropriate buffer size for collecting all goroutines stack trace
+    # dump based on your case.
+    # Default value is `2mb`.
+    #stack_buffer_size = "2mb"
+
+    # Whether to collect all the Go routines details or not.
+    # Default value is `false`.
+    #all_goroutines = true
+  }
+
+  # Pooling configuration is to reduce GC overhead from framework.
+  # Tune these value based on your use case. Pool doesn't create object
+  # unless it's needed.
+  # Doc: https://docs.aahframework.org/pooling.html
+  pooling {
+    # Default value is `500`.
+    global = 5000
+
+    # Used for `bytes.Buffer`
+    # Default value is `200`.
+    buffer = 1500
+  }
+}
+
+# -----------------------------------------------------------------
+# Render configuration
+# Doc: https://docs.aahframework.org/app-config.html#section-render
+# -----------------------------------------------------------------
+render {
+  # aah framework chooses the `Content-Type` value automatically based on
+  # configuration if `aah.Reply()` builder value is not set. It selects in
+  # the order of:
+  #  - Based on URL file extension, supported `.html`, `.htm`, `.json`, `.js`, `.xml` and `.txt`
+  #  - Request Accept Header - Most Qualified one as per RFC7321
+  #  - Based `render.default` value supported types are `html`, `json`, `xml` and `text`
+  #  - Finally aah framework uses `http.DetectContentType` API
+  # Default value is `empty` string.
+  default = "html"
+
+  # Pretty print option is helpful in `dev` environment profile.
+  # It is only applicable to JSON and XML.
+  # Default value is `false`.
+  #pretty = true
+
+  # Gzip compression configuration for HTTP response.
+  gzip {
+    # By default Gzip compression is enabled in aah framework, however
+    # framework ensures HTTP client accepts Gzip response otherwise
+    # it won't use Gzip compression.
+    #
+    # Tips: If you have nginx or apache web server enabled with gzip in-front
+    # of aah server the set this value to `false`.
+    #
+    # Default value is `true`.
+    enable = false
+
+    # Used to control Gzip compression levels. Valid levels are
+    # 1 = BestSpeed to 9 = BestCompression.
+    # Default value is `4`.
+    #level = 4
+  }
+}
+
+# ------------------------------------------------------------------
+# Cache configuration
+# Doc: https://docs.aahframework.org/static-files.html#cache-control
+# ------------------------------------------------------------------
+cache {
+  static {
+    # Default `Cache-Control` for all static files,
+    # if specific mime type is not defined.
+    default_cache_control = "public, max-age=31536000"
+
+    # Define by mime types, if mime is not present then default is applied.
+    # Config is very flexible to define by mime type.
+    #
+    # Create a unique name and provide `mime` with comma separated value
+    # and `cache_control`.
+    # mime_types {
+    #   css_js {
+    #     mime = "text/css, application/javascript"
+    #     cache_control = "public, max-age=604800, proxy-revalidate"
+    #   }
+    #
+    #   images {
+    #     mime = "image/jpeg, image/png, image/gif, image/svg+xml, image/x-icon"
+    #     cache_control = "public, max-age=2628000, proxy-revalidate"
+    #   }
+    # }
+  }
+}
+
+# ---------------------------------------------------------------
+# View configuration
+# Doc: https://docs.aahframework.org/app-config.html#section-view
+# ---------------------------------------------------------------
+view {
+  # Choosing view engine for application. In the upcoming release framework
+  # will provide support to amber, pongo2, and jade. However you can implement
+  # on your own with simple `view.Enginer` interface.
+  # Default value is `go`. Currently only `go` is supported.
+  #engine = "go"
+
+  # Choose your own view file extension.
+  # Default value is `.html`.
+  #ext = ".html"
+
+  # Choose whether you need a case sensitive view file resolve or not.
+  # For e.g.: "/views/pages/app/login.tmpl" == "/views/pages/App/Login.tmpl"
+  # Default value is `false`.
+  #case_sensitive = false
+
+  # To use custom Go template delimiters for view files.
+  # Default value is `{{.}}`.
+  #delimiters = "{{.}}"
+
+  # Framework chooses the default app layout as `master.html` if you do not
+  # provide one. However you may have pages or template without layout too.
+  # So option to disable the default layout for HTML.
+  # Default value is `true`. Available since v0.6
+  #default_layout = false
+}
+
+# DataSource config
+datasource {
+    benchmark {
+      driver = "mysql"
+      url = "benchmarkdbuser:benchmarkdbpass@tcp(%s:3306)/hello_world"
+    }
+  }
+
+# --------------------------------------------------------------
+# Environment Profiles e.g.: dev, qa, prod
+# Doc: https://docs.aahframework.org/app-config.html#section-env
+# --------------------------------------------------------------
+env {
+  # Indicates active profile name for application configuration.
+  # Default value is `dev`.
+  #active = "dev"
+
+  # ----------------------------------
+  # Environment profile configurations
+  # ----------------------------------
+  include "./env/*.conf"
+}

+ 24 - 0
frameworks/Go/aah/src/benchmark/config/env/dev.conf

@@ -0,0 +1,24 @@
+# ---------------------------------
+# Development Configuration Section
+# ---------------------------------
+
+dev {
+
+  # --------------------------------------------------
+  # Log Configuration
+  # Doc: https://docs.aahframework.org/log-config.html
+  # --------------------------------------------------
+  log {
+    receiver = "console"
+    level = "info"
+  }
+
+  # -------------------------
+  # Render configuration
+  # -------------------------
+  render {
+    # pretty is only applicable to JSON & XML rendering
+    pretty = true
+  }
+
+}

+ 61 - 0
frameworks/Go/aah/src/benchmark/config/env/prod.conf

@@ -0,0 +1,61 @@
+# ---------------------------------
+# Production Configuration Section
+# ---------------------------------
+
+prod {
+
+  # ---------------------------
+  # Production Hostname mapping
+  # ---------------------------
+  routes {
+    domains {
+      localhost {
+        host = "TFB-server"
+      }
+    }
+  }
+
+  # --------------------------------------------------
+  # Log Configuration
+  # Doc: https://docs.aahframework.org/log-config.html
+  # --------------------------------------------------
+  log {
+    # Receiver is where is log values gets logged. Currently framework
+    # supports `console` and `file` as a receivers.
+    # Default value is `console`.
+    #receiver = "file"
+
+    # Level indicates the logging levels like `ERROR`, `WARN`, `INFO`, `DEBUG`
+    # and `TRACE`. Config value can be in lowercase or uppercase.
+    # Default value is `debug`.
+    level = "error"
+
+    # Pattern config defines the message flags and formatting while logging
+    # into receivers. Customize it as per your need, learn more about flags
+    # and format - https://docs.aahframework.org/log-config.html#pattern
+    # Default value is `%time:2006-01-02 15:04:05.000 %level:-5 %message`
+    #pattern = "%time:2006-01-02 15:04:05.000 %level:-5 %message"
+
+    # File config attribute is applicable only to `file` receiver type.
+    # Default value is `aah-log-file.log`.
+    #file = "benchmark.log"
+
+    # Rotate config section is applicable only to `file` receiver type.
+    # Default rotation is 'daily'.
+    rotate {
+      # Mode is used to determine rotate mode. Currently it supports `daily`,
+      # `lines` and `size`.
+      # Default value is `daily`.
+      #mode = "daily"
+
+      # This is applicable only to if `mode` is `size`.
+      # Default value is 100MB.
+      #size = 500
+
+      # This is applicable only to if `mode` is `lines`.
+      # Default value is unlimited.
+      #lines = 100000
+    }
+  }
+
+}

+ 71 - 0
frameworks/Go/aah/src/benchmark/config/routes.conf

@@ -0,0 +1,71 @@
+####################################################
+# benchmark - Application Routes Configuration
+#
+# Complete routes configuration reference:
+#   https://docs.aahframework.org/routes-config.html
+####################################################
+
+#------------------------------------------------------------------------
+# Domain and sub-domain configuration goes into section `domains { ... }`
+#------------------------------------------------------------------------
+domains {
+
+  # Pick your choice of an `unique keyname` to define your domain section
+  # in the routes configuration.
+  # For e.g.: Domain name/ip address with port no
+  localhost {
+    name = "benchmark routes"
+
+    # aah supports multi-domain routes configuration out-of-the-box.
+    # `host` used to determine domain routes for the incoming request.
+    # For e.g: example.org
+    host = "localhost"
+
+    #-----------------------------------------------------------------------------
+    # Application routes
+    # Doc: https://docs.aahframework.org/routes-config.html#section-routes
+    # Doc: https://docs.aahframework.org/routes-config.html#namespace-group-routes
+    #-----------------------------------------------------------------------------
+    routes {
+
+      json {
+        path = "/json"
+        controller = "AppController"
+        action = "JSON"
+      }
+
+      db {
+        path = "/db"
+        controller = "AppController"
+        action = "GetWorld"
+      }
+
+      dbs {
+        path = "/queries"
+        controller = "AppController"
+        action = "GetWorlds"
+      }
+
+      fortunes {
+        path = "/fortunes"
+        controller = "AppController"
+        action = "Fortunes"
+      }
+
+      updates {
+        path = "/updates"
+        controller = "AppController"
+        action = "UpdateWorlds"
+      }
+
+      plaintext {
+        path = "/plaintext"
+        controller = "AppController"
+        action = "Plaintext"
+      }
+
+    } # end - routes
+
+  } # end - localhost
+
+} # end - domains

+ 83 - 0
frameworks/Go/aah/src/benchmark/config/security.conf

@@ -0,0 +1,83 @@
+######################################################
+# benchmark - Application Security Configuration
+#
+# Complete routes configuration reference:
+#   https://docs.aahframework.org/security-config.html
+######################################################
+
+security {
+  # -----------------------------------------------------------------------
+  # Session configuration
+  # HTTP state management across multiple requests.
+  # Doc: https://docs.aahframework.org/security-config.html#section-session
+  # -----------------------------------------------------------------------
+  session {
+    # Session mode to choose whether HTTP session should be persisted or
+    # destroyed at the end of the request. Supported values are `stateless`
+    # and `stateful`.
+    # Default value is `stateless` for API and `stateful` for Web app.
+    #mode = "stateful"
+
+    # Session store is to choose where session value should be persisted.
+    store {
+      # Currently aah framework supports `cookie` and `file` as store type.
+      # Also framework provide extensible `session.Storer` interface to
+      # add custom session store.
+      # Default value is `cookie`.
+      type = "cookie"
+
+      
+    }
+
+    # Session ID length
+    # Default value is `32`.
+    #id_length = 32
+
+    # Time-to-live for session data. Valid time units are "m = minutes",
+    # "h = hours" and 0.
+    # Default value is `0`, cookie is deleted when the browser is closed.
+    #ttl = "0"
+
+    # Session cookie name prefix.
+    # Default value is `aah` For e.g.: `aah_session`
+    #prefix = "aah"
+
+    # Default value is `empty` string.
+    #domain = ""
+
+    # Default value is `/`.
+    #path = "/"
+
+    # HTTP session cookie HTTPOnly value. This option prevents XSS
+    # (Cross Site Scripting) attacks.
+    # Default value is `true`.
+    #http_only = true
+
+    # HTTP session cookie secure value.
+    # However if aah server is not configured with SSL then
+    # framework sets this value as false
+    # Default value is `true`.
+    #secure = true
+
+    # HTTP session cookie value signing using `HMAC`. For server farm this
+    # should be same in all instance. For HMAC sign & verify it recommend to use
+    # key size is `32` or `64` bytes.
+    # Default value is `64` bytes (generated when application gets created
+    # using `aah new` command).
+    sign_key = "74cb9e6a73a7d41c76b0d145e18bc41c74484fe71d16ee148ef5612aa8c3078b"
+
+    # HTTP session cookie value encryption and decryption using `AES`. For server
+    # farm this should be same in all instance. AES algorithm is used, valid
+    # lengths are `16`, `24`, or `32` bytes to select `AES-128`, `AES-192`, or `AES-256`.
+    # Default value is `32` bytes (generated when application gets created
+    # using `aah new` command).
+    enc_key = "b318415ff2b65b03332e822e1101cf53"
+
+    # Cleanup Interval is used to clean the expired session objects from store.
+    # This is only applicable for non-cookie store type.
+    # Cleanup performed in dedicated goroutine. Valid time units are
+    # `m -> minutes`, `h -> hours`.
+    # Default value is `30m`.
+    #cleanup_interval = "30m"
+  }
+}

+ 39 - 0
frameworks/Go/aah/src/benchmark/glide.lock

@@ -0,0 +1,39 @@
+hash: 8a2f4a09267a0af0254fb9e9328c1b6dbd69fa526243254f5d13f790effb76dd
+updated: 2017-06-08T04:39:51.485650163Z
+imports:
+- name: aahframework.org/aah.v0
+  version: e577358978ee343da0347e3d5e3ddf6a320be794
+- name: aahframework.org/ahttp.v0
+  version: e15ece4bedd71ec9c49e412e4bc6c7681a7a7e5d
+- name: aahframework.org/aruntime.v0
+  version: 3368d72836c245d93409bcf73e2eb5e74cf02767
+- name: aahframework.org/config.v0
+  version: c13836cc8b02b1667856aaa929167c680be3e9d6
+- name: aahframework.org/essentials.v0
+  version: a3d81313d1d8f7061f2a380f30367beb9fcd11db
+- name: aahframework.org/forge.v0
+  version: 9f3b186d1c58fb40060cc9783d990d3a9c5e0176
+  subpackages:
+  - token
+- name: aahframework.org/i18n.v0
+  version: 6089355055bb15109f7f3aefb8efd2a955115d6d
+- name: aahframework.org/log.v0
+  version: f32cca084e451e2f811eb2d82bc8cd5636741f66
+- name: aahframework.org/pool.v0
+  version: b334c816f1647832a73e84af41c828171b24324c
+- name: aahframework.org/router.v0
+  version: f490947101db8d646cc36d045548a32350f56243
+- name: aahframework.org/security.v0
+  version: e37fb86ca4b437b6af01212318123bb43f27aa5f
+  subpackages:
+  - session
+- name: aahframework.org/view.v0
+  version: 3f4c1cf783430edeefb8cbdc98f11128f6595318
+- name: github.com/go-sql-driver/mysql
+  version: e3f0fdcf52770a162d5a4540ddb8d9957ff456d1
+- name: golang.org/x/crypto
+  version: e7ba82683099cae71475961448ab8f903ea77c26
+  subpackages:
+  - acme
+  - acme/autocert
+testImports: []

+ 5 - 0
frameworks/Go/aah/src/benchmark/glide.yaml

@@ -0,0 +1,5 @@
+package: benchmark
+import:
+- package: aahframework.org/aah.v0
+  version: ^v0.6
+- package: github.com/go-sql-driver/mysql

+ 7 - 0
frameworks/Go/aah/src/benchmark/views/layouts/master.html

@@ -0,0 +1,7 @@
+<!DOCTYPE html>
+<html>
+<head>{{ template "title" . }}</head>
+<body>
+{{ template "body" . }}
+</body>
+</html>

+ 10 - 0
frameworks/Go/aah/src/benchmark/views/pages/app/fortunes.html

@@ -0,0 +1,10 @@
+{{ define "title" -}}<title>Fortunes</title>{{- end }}
+
+{{ define "body" -}}
+<table>
+<tr><th>id</th><th>message</th></tr>
+{{- range .Fortunes }}
+<tr><td>{{ .ID }}</td><td>{{ .Message }}</td></tr>
+{{- end }}
+</table>
+{{- end }}