From 6e894fbb85371c11167947b873c3dde2887ae1a4 Mon Sep 17 00:00:00 2001 From: Julien Vincent Date: Fri, 12 Jan 2024 08:10:45 +0000 Subject: [PATCH] Enable *warn-on-reflection* and add missing hints (#18) At the moment there are several reflection calls occuring on the hot-path for request handling. This is both slow and makes it harder to compile with GraalVM. This commit enables the `*warn-on-reflection*` global on all namespaces and adds the missing type hints to locations where reflection were occuring. In some cases this required restructuring code a bit to better apply the hints. --- src/s_exp/hirundo/http/request.clj | 38 ++++++++++++++++------------- src/s_exp/hirundo/http/response.clj | 15 ++++++------ src/s_exp/hirundo/utils.clj | 2 ++ 3 files changed, 30 insertions(+), 25 deletions(-) diff --git a/src/s_exp/hirundo/http/request.clj b/src/s_exp/hirundo/http/request.clj index a583118..0a61b4a 100644 --- a/src/s_exp/hirundo/http/request.clj +++ b/src/s_exp/hirundo/http/request.clj @@ -5,6 +5,8 @@ (io.helidon.http HttpPrologue Headers Header) (io.helidon.webserver.http ServerRequest ServerResponse))) +(set! *warn-on-reflection* true) + (defn ring-headers [^Headers headers] (-> (reduce (fn [m ^Header h] @@ -49,21 +51,23 @@ (let [qs (ring-query (.query server-request)) body (let [content (.content server-request)] (when-not (.consumed content) (.inputStream content))) - ring-request (-> (.asTransient PersistentHashMap/EMPTY) - (.assoc :server-port (.port (.localPeer server-request))) - (.assoc :server-name (.host (.localPeer server-request))) - (.assoc :remote-addr (let [address ^java.net.InetSocketAddress (.address (.remotePeer server-request))] - (-> address .getAddress .getHostAddress))) - (.assoc :ssl-client-cert (some-> server-request .remotePeer .tlsCertificates (.orElse nil) first)) - (.assoc :uri (ring-path (.path server-request))) - (.assoc :scheme (if (.isSecure server-request) :https :http)) - (.assoc :protocol (ring-protocol (.prologue server-request))) - (.assoc :request-method (ring-method (.prologue server-request))) - (.assoc :headers (ring-headers (.headers server-request))) - (.assoc ::server-request server-request) - (.assoc ::server-response server-response)) - ;; optional + + ring-request (transient + {:server-port (.port (.localPeer server-request)) + :server-name (.host (.localPeer server-request)) + :remote-addr (let [address ^java.net.InetSocketAddress (.address (.remotePeer server-request))] + (-> address .getAddress .getHostAddress)) + :ssl-client-cert (some-> server-request .remotePeer .tlsCertificates (.orElse nil) first) + :uri (ring-path (.path server-request)) + :scheme (if (.isSecure server-request) :https :http) + :protocol (ring-protocol (.prologue server-request)) + :request-method (ring-method (.prologue server-request)) + :headers (ring-headers (.headers server-request)) + ::server-request server-request + ::server-response server-response}) + ring-request (cond-> ring-request - qs (.assoc :query-string (ring-query (.query server-request))) - body (.assoc :body body))] - (.persistent ring-request))) + qs (assoc! :query-string (ring-query (.query server-request))) + body (assoc! :body body))] + + (persistent! ring-request))) diff --git a/src/s_exp/hirundo/http/response.clj b/src/s_exp/hirundo/http/response.clj index 6969f00..21d30a1 100644 --- a/src/s_exp/hirundo/http/response.clj +++ b/src/s_exp/hirundo/http/response.clj @@ -5,6 +5,8 @@ (io.helidon.webserver.http ServerResponse) (java.io FileInputStream InputStream OutputStream))) +(set! *warn-on-reflection* true) + (def ring-core-available? (try (require 'ring.core.protocols) @@ -44,12 +46,12 @@ (when ring-core-available? (extend-protocol BodyWriter Object - (write-body! [o server-response] + (write-body! [o ^ServerResponse server-response] (let [StreamableResponseBody @(ns-resolve 'ring.core.protocols 'StreamableResponseBody) write-body-to-stream (ns-resolve 'ring.core.protocols 'write-body-to-stream)] (if (satisfies? StreamableResponseBody o) (write-body-to-stream o nil (.outputStream server-response)) - (.send ^ServerResponse server-response o)))))) + (.send server-response o)))))) (defn header-name ^HeaderName [ring-header-name] (HeaderNames/createFromLowercase (name ring-header-name))) @@ -58,12 +60,9 @@ [^ServerResponse server-response headers] (when headers (run! (fn [[k v]] - (.header server-response - (header-name k) - (if (sequential? v) - (into-array String v) - (doto (make-array String 1) - (aset 0 v))))) + (let [values-seq (if (sequential? v) v [v]) + headers ^"[Ljava.lang.String;" (into-array String values-seq)] + (.header server-response (header-name k) headers))) headers))) (defn- set-status! diff --git a/src/s_exp/hirundo/utils.clj b/src/s_exp/hirundo/utils.clj index 7e1e5df..fa1b3db 100644 --- a/src/s_exp/hirundo/utils.clj +++ b/src/s_exp/hirundo/utils.clj @@ -1,6 +1,8 @@ (ns s-exp.hirundo.utils (:require [clojure.string :as str])) +(set! *warn-on-reflection* true) + (defn camel->dashed [s] (-> s