Переглянути джерело

Merge pull request #1629 from zane-techempower/add-moonshine-2

Add Crystal-Moonshine and improve Crystal installation
Mike Smith 10 роки тому
батько
коміт
bbedc39a06

+ 1 - 0
.travis.yml

@@ -36,6 +36,7 @@ env:
     - "TESTDIR=Clojure/pedestal"
     - "TESTDIR=Clojure/aleph"
     - "TESTDIR=Crystal/crystal-raw"
+    - "TESTDIR=Crystal/moonshine"
     - "TESTDIR=Dart/dart"
     - "TESTDIR=Dart/dart-redstone"
     - "TESTDIR=Dart/dart-start"

+ 2 - 1
frameworks/Crystal/crystal-raw/benchmark_config.json

@@ -17,7 +17,8 @@
       "os": "Linux",
       "database_os": "Linux",
       "display_name": "Crystal",
-      "notes": ""
+      "notes": "",
+      "versus": "ruby"
     }
   }]
 }

+ 1 - 1
frameworks/Crystal/crystal-raw/install.sh

@@ -1,3 +1,3 @@
 #!/bin/bash
 
-fw_depends crystal
+fw_depends crystal-0.7.1

+ 2 - 0
frameworks/Crystal/crystal-raw/setup.sh

@@ -1,4 +1,6 @@
 #!/bin/bash
+source ${IROOT}/crystal-0.7.1.installed
 
 crystal build --release server.cr -o server.out
+
 ./server.out

+ 4 - 0
frameworks/Crystal/moonshine/.gitignore

@@ -0,0 +1,4 @@
+.deps
+.deps.lock
+libs/
+.crystal

+ 4 - 0
frameworks/Crystal/moonshine/Projectfile

@@ -0,0 +1,4 @@
+deps do
+  github "dhruvrajvanshi/Moonshine", name: "moonshine"
+  github "stefanwille/crystal-redis"
+end

+ 5 - 0
frameworks/Crystal/moonshine/README.md

@@ -0,0 +1,5 @@
+# Crystal-Moonshine
+
+This is the [Moonshine](https://github.com/dhruvrajvanshi/Moonshine) test of the Framework Benchmarks. Crystal is a new language that closely resembles Ruby with a goal of removing typed variables and parameters (instead inferencing), whilst maintaining top speed through bindings into C.
+
+Moonshine is a minimal web framework for the Crystal language.

+ 28 - 0
frameworks/Crystal/moonshine/benchmark_config.json

@@ -0,0 +1,28 @@
+{
+  "framework": "moonshine",
+  "tests": [{
+    "default": {
+      "setup_file": "setup",
+      "json_url": "/json",
+      "db_url": "/redis/db",
+      "query_url": "/redis/queries?queries=",
+      "fortune_url": "/redis/fortunes",
+      "update_url": "/redis/updates?queries=",
+      "plaintext_url": "/plaintext",
+      "port": 8080,
+      "approach": "Realistic",
+      "classification": "Fullstack",
+      "database": "Redis",
+      "framework": "moonshine",
+      "language": "Crystal",
+      "orm": "micro",
+      "platform": "Crystal",
+      "webserver": "None",
+      "os": "Linux",
+      "database_os": "Linux",
+      "display_name": "Moonshine",
+      "notes": "",
+      "versus": "ruby"
+    }
+  }]
+}

+ 4 - 0
frameworks/Crystal/moonshine/install.sh

@@ -0,0 +1,4 @@
+#!/bin/bash
+
+fw_depends crystal-0.7.1
+

+ 154 - 0
frameworks/Crystal/moonshine/server.cr

@@ -0,0 +1,154 @@
+require "moonshine"
+require "redis"
+require "html/builder"
+
+include Moonshine
+include Moonshine::Utils::Shortcuts
+include Moonshine::Base
+
+# Compose Objects (like Hash) to have a to_json method
+require "json/to_json"
+
+REDIS = Redis.new
+app = App.new
+
+class CONTENT
+  UTF8 = "; charset=UTF-8"
+  JSON = "application/json" + UTF8
+  PLAIN = "text/plain"
+  HTML = "text/html" + UTF8
+end
+
+ID_MAXIMUM = 10_000
+
+app.response_middleware do |req, res|
+    res.headers["Server"] = "Moonshine"
+    res.headers["Date"] = Time.now.to_s
+    res
+end
+
+private def randomWorld
+  id = rand(1..ID_MAXIMUM)
+  num = REDIS.get("world:" + id.to_s)
+  { :id => id, :randomNumber => num }
+end
+
+private def setWorld(world)
+  id = "world:" + world[:id].to_s
+  REDIS.set(id, world[:randomNumber])
+  world
+end
+
+private def sanitizedQueryCount(request)
+  begin
+    queries = request.get["queries"].to_i
+  rescue
+    queries = 1
+  end
+  queries = 1 if queries < 1
+  queries = 500 if queries > 500
+  queries
+end
+
+#
+# Basic Tests
+#
+
+# Test 1: JSON Serialization
+app.get "/json", do |request|
+  res = ok({ :message => "Hello, World!" }.to_json)
+  res.headers["Content-type"] = CONTENT::JSON
+  res
+end
+
+# Test 6: Plaintext
+app.get "/plaintext", do |request|
+  res = ok("Hello, World!")
+  res.headers["Content-type"] = CONTENT::PLAIN
+  res
+end
+
+#
+# Redis DatabaseTests
+#
+
+# Redis Test 2: Single database query
+app.get "/redis/db", do |request|
+  res = ok(randomWorld.to_json)
+  res.headers["Content-type"] = CONTENT::JSON
+  res
+end
+
+# Redis Test 3: Multiple database query
+app.get "/redis/queries", do |request|
+  results = (1..sanitizedQueryCount(request)).map do
+    randomWorld
+  end
+
+  res = ok(results.to_json)
+  res.headers["Content-type"] = CONTENT::JSON
+  res
+end
+
+# Redis Test 4: Fortunes
+app.get "/redis/fortunes", do |request|
+  data = [] of  Hash(Symbol, (String | Int32))
+
+  REDIS.lrange("fortunes", 0, -1).each_with_index do |e, i|
+    data.push({ :id => i + 1, :message => e.to_s })
+  end
+  
+  additional_fortune = {
+    :id => 0
+    :message => "Additional fortune added at request time."
+  }
+  data.push(additional_fortune)
+
+  data.sort! { |a, b|
+    a[:message].to_s <=> b[:message].to_s
+  }
+
+  # New builder for each request!
+  html = HTML::Builder.new.build do
+    html {
+      head {
+        title { text "Fortunes" }
+      }
+      body {
+        table {
+          tr {
+            thead { text "id" }
+            thead { text "message" }
+          }
+          data.each { |e|
+            tr {
+              td { text e[:id].to_s }
+              td { text e[:message].to_s }
+            }
+          }
+        }
+      }
+    }
+  end
+
+  # Doctype not available in builder
+  # builder only supports `thead`, tests need to see `th`
+  res = ok("<!doctype html>" + html.gsub("thead", "th"))
+  res.headers["Content-type"] = CONTENT::HTML
+  res
+end
+
+# Redis Test 5: Database Updates
+app.get "/redis/updates", do |request|
+  updated = (1..sanitizedQueryCount(request)).map do
+    world = randomWorld
+    world[:randomNumber] = rand(1..ID_MAXIMUM)
+    setWorld(world)
+  end
+
+  res = ok(updated.to_json)
+  res.headers["Content-type"] = CONTENT::JSON
+  res
+end
+
+app.run(8080)

+ 5 - 0
frameworks/Crystal/moonshine/setup.sh

@@ -0,0 +1,5 @@
+source ${IROOT}/crystal-0.7.1.installed
+
+crystal deps install
+
+crystal server.cr &

+ 14 - 0
toolset/setup/linux/languages/crystal-0.7.1.sh

@@ -0,0 +1,14 @@
+#!/bin/bash
+REDCODE=$(fw_exists ${IROOT}/crystal-0.7.1.installed)
+[ ! "$RETCODE" == 0 ] || { return 0; }
+
+SAVE_AS=crystal-0.7.1-1-linux-x86_64.tar.gz
+URL=https://github.com/manastech/crystal/releases/download/0.7.1/crystal-0.7.1-1-linux-x86_64.tar.gz
+
+# Default filename is too long, causing problems
+# Use -O to specify
+fw_get -O $SAVE_AS $URL
+
+fw_untar crystal-0.7.1-1-linux-x86_64.tar.gz
+
+echo "export PATH=$IROOT/crystal-0.7.1-1/bin/:$PATH" >> ${IROOT}/crystal-0.7.1.installed

+ 0 - 14
toolset/setup/linux/languages/crystal.sh

@@ -1,14 +0,0 @@
-#!/bin/bash
-set -ex
-
-RETCODE=$(fw_exists ${IROOT}/crystal.installed)
-[ ! "$RETCODE" == 0 ] || { return 0; }
-
-sudo apt-key adv --keyserver keys.gnupg.net --recv-keys 09617FD37CC06B54
-echo "deb http://dist.crystal-lang.org/apt crystal main" | sudo tee /etc/apt/sources.list.d/crystal.list
-
-sudo apt-get update
-
-sudo apt-get install -y crystal
-
-touch ${IROOT}/crystal.installed