Browse Source

Merge branch 'master' of gitlab.techempower.com:techempower/frameworkbenchmarks

Patrick Falls 12 years ago
parent
commit
fbebce8ea9
3 changed files with 109 additions and 4 deletions
  1. 2 1
      compojure/benchmark_config
  2. 4 0
      compojure/hello/project.clj
  3. 103 3
      compojure/hello/src/hello/handler.clj

+ 2 - 1
compojure/benchmark_config

@@ -6,8 +6,9 @@
       "json_url": "/compojure/json",
       "db_url": "/compojure/db/1",
       "query_url": "/compojure/db/",
+      "fortune_url": "/compojure/fortune-hiccup"
       "port": 8080,
       "sort": 2
     }
   }]
-}
+}

+ 4 - 0
compojure/hello/project.clj

@@ -7,6 +7,10 @@
                  [korma "0.3.0-RC5"]
                  [log4j "1.2.15" :exclusions [javax.mail/mail javax.jms/jms com.sun.jdmk/jmxtools com.sun.jmx/jmxri]]
                  [mysql/mysql-connector-java "5.1.6"]
+                 [org.clojure/java.jdbc "0.3.0-alpha1"]
+                 [c3p0/c3p0 "0.9.1.2"]
+                 [hiccup "1.0.3"]
+                 [enlive "1.1.1"]
                  ]
   :plugins [[lein-ring "0.8.2"]]
   :ring {:handler hello.handler/app}

+ 103 - 3
compojure/hello/src/hello/handler.clj

@@ -1,11 +1,17 @@
 (ns hello.handler
+  (:import com.mchange.v2.c3p0.ComboPooledDataSource)
   (:use compojure.core
         ring.middleware.json
         ring.util.response
         korma.db
-        korma.core)
+        korma.core
+        hiccup.core
+        hiccup.util)
   (:require [compojure.handler :as handler]
-            [compojure.route :as route]))
+            [compojure.route :as route]
+            [clojure.java.jdbc :as jdbc]
+            [clojure.java.jdbc.sql :as sql]
+            [net.cgrand.enlive-html :as html]))
 
 ; Database connection
 (defdb db (mysql {:subname "//localhost:3306/hello_world?jdbcCompliantTruncation=false&elideSetAutoCommits=true&useLocalSessionState=true&cachePrepStmts=true&cacheCallableStmts=true&alwaysSendSetIsolation=false&prepStmtCacheSize=4096&cacheServerConfiguration=true&prepStmtCacheSqlLimit=2048&zeroDateTimeBehavior=convertToNull&traceProtocol=false&useUnbufferedInput=false&useReadAheadInput=false&maintainTimeStats=false&useServerPrepStmts&cacheRSMetadata=true"
@@ -38,11 +44,105 @@
      queries ; Number of queries to run
      (repeatedly get-world)))))
 
+; Database connection for java.jdbc "raw"
+; https://github.com/clojure/java.jdbc/blob/master/doc/clojure/java/jdbc/ConnectionPooling.md
+(def db-spec-mysql-raw
+  {:classname "com.mysql.jdbc.Driver"
+   :subprotocol "mysql"
+   :subname "//localhost:3306/hello_world?jdbcCompliantTruncation=false&elideSetAutoCommits=true&useLocalSessionState=true&cachePrepStmts=true&cacheCallableStmts=true&alwaysSendSetIsolation=false&prepStmtCacheSize=4096&cacheServerConfiguration=true&prepStmtCacheSqlLimit=2048&zeroDateTimeBehavior=convertToNull&traceProtocol=false&useUnbufferedInput=false&useReadAheadInput=false&maintainTimeStats=false&useServerPrepStmts&cacheRSMetadata=true"
+   :user "benchmarkdbuser"
+   :password "benchmarkdbpass"})
+
+(defn pool
+  [spec]
+  (let [cpds (doto (ComboPooledDataSource.)
+               (.setDriverClass (:classname spec))
+               (.setJdbcUrl (str "jdbc:" (:subprotocol spec) ":" (:subname spec)))
+               (.setUser (:user spec))
+               (.setPassword (:password spec))
+               ;; expire excess connections after 30 minutes of inactivity:
+               (.setMaxIdleTimeExcessConnections (* 30 60))
+               ;; expire connections after 3 hours of inactivity:
+               (.setMaxIdleTime (* 3 60 60)))]
+    {:datasource cpds}))
+
+(def pooled-db (delay (pool db-spec-mysql-raw)))
+
+(defn db-raw [] @pooled-db)
+
+; Query a random World record from the database
+(defn get-world-raw []
+  (let [id (inc (rand-int 9999))] ; Num between 1 and 10,000
+    (jdbc/with-connection (db-raw)
+      (jdbc/with-query-results rs [(str "select * from world where id = ?") id]
+        (doall rs)))))
+
+; Run the specified number of queries, return the results
+(defn run-queries-raw [queries]
+  (vec ; Return as a vector
+   (flatten ; Make it a list of maps
+    (take
+     queries ; Number of queries to run
+     (repeatedly get-world-raw)))))
+
+(defn get-query-count [queries]
+  "Parse provided string value of query count, clamping values to between 1 and 500."
+  (let [q (try (Integer/parseInt queries)
+               (catch Exception e 1))] ; default to 1 on parse failure
+    (if (> q 500)
+      500 ; clamp to 500 max
+      (if (< q 1)
+        1 ; clamp to 1 min
+        q)))) ; otherwise use provided value
+
+
+; Set up entity World and the database representation
+(defentity fortune
+  (pk :id)
+  (table :fortune)
+  (entity-fields :id :message)
+  (database db))
+
+(defn get-all-fortunes []
+  "Query all Fortune records from the database."
+    (select fortune
+            (fields :id :message)))
+
+(defn get-fortunes []
+  "Fetch the full list of Fortunes from the database, sort them by the fortune
+message text, and then return the results."
+  (let [fortunes (conj (get-all-fortunes) {:id 0 :message "Additional fortune added at request time."} )]
+    (sort-by #(:message %) fortunes)))
+
+(defn fortunes-hiccup [fortunes]
+  "Render the given fortunes to simple HTML using Hiccup."
+  (html
+   [:head
+    [:title "Fortunes"]]
+   [:body
+    [:table
+     [:tr
+      [:th "id"]
+      [:th "message"]]
+     (for [x fortunes]
+       [:tr
+        [:td (:id x)]
+        [:td (escape-html (:message x))]])
+     ]]))
+
+(defn fortunes-enlive [fortunes]
+  "Render the given fortunes to simple HTML using Enlive."
+  "todo")
+
 ; Define route handlers
 (defroutes app-routes
   (GET "/" [] "Hello, World!")
   (GET "/json" [] (response {:message "Hello, World!"}))
-  (GET "/db/:queries" [queries] (response (run-queries (Integer/parseInt queries))))
+  (GET "/db/:queries" [queries] (response (run-queries (get-query-count queries))))
+  (GET "/dbraw/:queries" [queries] (response (run-queries-raw (get-query-count queries))))
+  (GET "/fortune" [] (response (get-fortunes)))
+  (GET "/fortune-hiccup" [] (fortunes-hiccup (get-fortunes)))
+  (GET "/fortune-enlive" [] (fortunes-enlive (get-fortunes)))
   (route/not-found "Not Found"))
 
 ; Format responses as JSON