Browse Source

Implement parallelism for Crystal (#2758)

* Update to crystal 0.22.0

* Implement parallelism for Crystal

Crystal currently has no parallelism in the stdlib, however you can enable
SO_REUSEPORT and use the kernel to balance connections between processes.

* fixup! Update to crystal 0.22.0

* fixup! Update to crystal 0.22.0

* fixup! Update to crystal 0.22.0
Chris Hobbs 8 years ago
parent
commit
6d6c568617

+ 2 - 2
frameworks/Crystal/crystal/server.cr

@@ -9,7 +9,7 @@ server = HTTP::Server.new("0.0.0.0", 8080) do |context|
   when "/json"
   when "/json"
     response.status_code = 200
     response.status_code = 200
     response.headers["Content-Type"] = "application/json"
     response.headers["Content-Type"] = "application/json"
-    response.print({message: "Hello, World!"}.to_json)
+    {message: "Hello, World!"}.to_json(response)
   when "/plaintext"
   when "/plaintext"
     response.status_code = 200
     response.status_code = 200
     response.headers["Content-Type"] = "text/plain"
     response.headers["Content-Type"] = "text/plain"
@@ -19,4 +19,4 @@ server = HTTP::Server.new("0.0.0.0", 8080) do |context|
   end
   end
 end
 end
 
 
-server.listen
+server.listen(reuse_port: true)

+ 5 - 1
frameworks/Crystal/crystal/setup.sh

@@ -4,4 +4,8 @@ fw_depends crystal
 
 
 crystal build --release server.cr -o server.out
 crystal build --release server.cr -o server.out
 
 
-./server.out
+for i in {1..$(nproc --all)}; do
+  ./server.out &
+done
+
+wait

+ 9 - 15
frameworks/Crystal/kemal/server-postgres.cr

@@ -1,13 +1,10 @@
 require "kemal"
 require "kemal"
 require "pg"
 require "pg"
-require "pool/connection"
 
 
 # Compose Objects (like Hash) to have a to_json method
 # Compose Objects (like Hash) to have a to_json method
 require "json/to_json"
 require "json/to_json"
 
 
-DB = ConnectionPool.new(capacity: 25, timeout: 0.01) do
-  PG.connect("postgres://benchmarkdbuser:benchmarkdbpass@#{ENV["DBHOST"]? || "127.0.0.1"}/hello_world")
-end
+APPDB = DB.open("postgres://benchmarkdbuser:benchmarkdbpass@#{ENV["DBHOST"]? || "127.0.0.1"}/hello_world")
 
 
 class CONTENT
 class CONTENT
   UTF8  = "; charset=UTF-8"
   UTF8  = "; charset=UTF-8"
@@ -20,25 +17,22 @@ ID_MAXIMUM = 10_000
 
 
 private def random_world
 private def random_world
   id = rand(1..ID_MAXIMUM)
   id = rand(1..ID_MAXIMUM)
-  conn = DB.checkout
-  result = conn.exec({Int32, Int32}, "SELECT id, randomNumber FROM world WHERE id = $1", [id]).rows.first
-  DB.checkin(conn)
-  {id: result[0], randomNumber: result[1]}
+  random_number = APPDB.query_one("SELECT randomNumber FROM world WHERE id = $1", id, as: Int32)
+  {id: id, randomNumber: random_number}
 end
 end
 
 
 private def set_world(world)
 private def set_world(world)
-  conn = DB.checkout
-  result = conn.exec("UPDATE world set randomNumber = $1 where id = $2", [world[:randomNumber], world[:id]])
-  DB.checkin(conn)
+  APPDB.exec("UPDATE world SET randomNumber = $1 WHERE id = $2", world[:randomNumber], world[:id])
   world
   world
 end
 end
 
 
 private def fortunes
 private def fortunes
-  data = [] of NamedTuple(id: Int32, message: String)
+  data = Array(NamedTuple(id: Int32, message: String)).new
 
 
-  DB.connection.exec({Int32, String}, "select id, message from Fortune").rows.each do |row|
-    data.push({id: row[0], message: row[1]})
+  APPDB.query_each("SELECT id, message FROM Fortune") do |rs|
+    data.push({id: rs.read(Int32), message: rs.read(String)})
   end
   end
+
   data
   data
 end
 end
 
 
@@ -115,4 +109,4 @@ get "/updates" do |env|
 end
 end
 
 
 logging false
 logging false
-Kemal.run
+Kemal.run { |cfg| cfg.server.bind(reuse_port: true) }

+ 1 - 1
frameworks/Crystal/kemal/server-redis.cr

@@ -109,4 +109,4 @@ get "/updates" do |env|
 end
 end
 
 
 logging false
 logging false
-Kemal.run
+Kemal.run { |cfg| cfg.server.bind(reuse_port: true) }

+ 5 - 1
frameworks/Crystal/kemal/setup-postgres.sh

@@ -6,4 +6,8 @@ shards install
 
 
 crystal build --release server-postgres.cr
 crystal build --release server-postgres.cr
 
 
-./server-postgres &
+for i in {1..$(nproc --all)}; do
+  ./server-postgres &
+done
+
+wait

+ 5 - 1
frameworks/Crystal/kemal/setup-redis.sh

@@ -9,4 +9,8 @@ shards install
 
 
 crystal build --release server-redis.cr
 crystal build --release server-redis.cr
 
 
-./server-redis &
+for i in {1..$(nproc --all)}; do
+  ./server-redis &
+done
+
+wait

+ 7 - 11
frameworks/Crystal/kemal/shard.lock

@@ -1,12 +1,12 @@
 version: 1.0
 version: 1.0
 shards:
 shards:
-  html_builder:
-    github: crystal-lang/html_builder
-    version: 0.2.1
+  db:
+    github: crystal-lang/crystal-db
+    version: 0.4.2
 
 
   kemal:
   kemal:
     github: sdogruyol/kemal
     github: sdogruyol/kemal
-    version: 0.16.0
+    version: 0.19.0
 
 
   kilt:
   kilt:
     github: jeromegn/kilt
     github: jeromegn/kilt
@@ -14,17 +14,13 @@ shards:
 
 
   pg:
   pg:
     github: will/crystal-pg
     github: will/crystal-pg
-    version: 0.9.0
-
-  pool:
-    github: ysbaddaden/pool
-    version: 0.2.3
+    version: 0.13.3
 
 
   radix:
   radix:
     github: luislavena/radix
     github: luislavena/radix
-    version: 0.3.1
+    version: 0.3.8
 
 
   redis:
   redis:
     github: stefanwille/crystal-redis
     github: stefanwille/crystal-redis
-    version: 1.6.6
+    version: 1.8.0
 
 

+ 3 - 6
frameworks/Crystal/kemal/shard.yml

@@ -4,15 +4,12 @@ version: "0.0.1"
 dependencies:
 dependencies:
   pg:
   pg:
     github: "will/crystal-pg"
     github: "will/crystal-pg"
-    version: "0.9.0"
-  pool:
-    github: "ysbaddaden/pool"
-    version: "0.2.3"
+    version: "0.13.3"
   kemal:
   kemal:
     github: "sdogruyol/kemal"
     github: "sdogruyol/kemal"
-    version: "0.16.0"
+    version: "0.19.0"
   redis:
   redis:
     github: "stefanwille/crystal-redis"
     github: "stefanwille/crystal-redis"
-    version: "~> 1.6.6"
+    version: "1.8.0"
 
 
 license: "MIT"
 license: "MIT"

+ 2 - 2
toolset/setup/linux/languages/crystal.sh

@@ -4,7 +4,7 @@ fw_installed crystal && return 0
 
 
 # install crystal
 # install crystal
 
 
-VERSION="0.18.7"
+VERSION="0.22.0"
 
 
 SAVE_AS=crystal-$VERSION-1-linux-x86_64.tar.gz
 SAVE_AS=crystal-$VERSION-1-linux-x86_64.tar.gz
 URL=https://github.com/crystal-lang/crystal/releases/download/$VERSION/crystal-$VERSION-1-linux-x86_64.tar.gz
 URL=https://github.com/crystal-lang/crystal/releases/download/$VERSION/crystal-$VERSION-1-linux-x86_64.tar.gz
@@ -15,7 +15,7 @@ fw_untar ${SAVE_AS}
 
 
 # install shards
 # install shards
 
 
-SVERSION="0.6.3"
+SVERSION="0.7.1"
 SAVE_AS=shards-${SVERSION}_linux_x86_64
 SAVE_AS=shards-${SVERSION}_linux_x86_64
 URL=https://github.com/crystal-lang/shards/releases/download/v${SVERSION}/shards-${SVERSION}_linux_x86_64.gz
 URL=https://github.com/crystal-lang/shards/releases/download/v${SVERSION}/shards-${SVERSION}_linux_x86_64.gz