Sign Up

Sign Up to our social questions and Answers Engine to ask questions, answer people’s questions, and connect with other people.

Have an account? Sign In

Have an account? Sign In Now

Sign In

Login to our social questions & Answers Engine to ask questions answer people’s questions & connect with other people.

Sign Up Here

Forgot Password?

Don't have account, Sign Up Here

Forgot Password

Lost your password? Please enter your email address. You will receive a link and will create a new password via email.

Have an account? Sign In Now

You must login to ask a question.

Forgot Password?

Need An Account, Sign Up Here

Please briefly explain why you feel this question should be reported.

Please briefly explain why you feel this answer should be reported.

Please briefly explain why you feel this user should be reported.

Sign InSign Up

The Archive Base

The Archive Base Logo The Archive Base Logo

The Archive Base Navigation

  • SEARCH
  • Home
  • About Us
  • Blog
  • Contact Us
Search
Ask A Question

Mobile menu

Close
Ask a Question
  • Home
  • Add group
  • Groups page
  • Feed
  • User Profile
  • Communities
  • Questions
    • New Questions
    • Trending Questions
    • Must read Questions
    • Hot Questions
  • Polls
  • Tags
  • Badges
  • Buy Points
  • Users
  • Help
  • Buy Theme
  • SEARCH
Home/ Questions/Q 8509087
In Process

The Archive Base Latest Questions

Editorial Team
  • 0
Editorial Team
Asked: June 11, 20262026-06-11T03:20:23+00:00 2026-06-11T03:20:23+00:00

I am trying to prove Clojure performance can be on equal footing with Java.

  • 0

I am trying to prove Clojure performance can be on equal footing with Java. An important use case I’ve found is the Quicksort. I have written an implementation as follows:

(set! *unchecked-math* true)

(defn qsort [^longs a]
  (let [qs (fn qs [^long low, ^long high]
             (when (< low high)
               (let [pivot (aget a low)
                     [i j]
                     (loop [i low, j high]
                       (let [i (loop [i i] (if (< (aget a i) pivot)
                                             (recur (inc i)) i))
                             j (loop [j j] (if (> (aget a j) pivot)
                                             (recur (dec j)) j))
                             [i j] (if (<= i j)
                                     (let [tmp (aget a i)]
                                       (aset a i (aget a j)) (aset a j tmp)
                                       [(inc i) (dec j)])
                                     [i j])]
                         (if (< i j) (recur i j) [i j])))]
                 (when (< low j) (qs low j))
                 (when (< i high) (qs i high)))))]
    (qs 0 (dec (alength a))))
  a)

Also, this helps call the Java quicksort:

(defn jqsort [^longs a] (java.util.Arrays/sort a) a))

Now, for the benchmark.

user> (def xs (let [rnd (java.util.Random.)] 
        (long-array (repeatedly 100000 #(.nextLong rnd)))))
#'user/xs
user> (def ys (long-array xs))
#'user/ys
user> (time (qsort ys))
"Elapsed time: 163.33 msecs"
#<long[] [J@3ae34094>
user> (def ys (long-array xs))
user> (time (jqsort ys))
"Elapsed time: 13.895 msecs"
#<long[] [J@1b2b2f7f>

Performance is worlds apart (an order of magnitude, and then some).

Is there anything I’m missing, any Clojure feature I may have used? I think the main source of performance degradation is when I need to return several values from a loop and must allocate a vector for that. Can this be avoided?

BTW running Clojure 1.4. Also note that I have run the benchmark multiple times in order to warm up the HotSpot. These are the times when they settle down.

Update

The most terrible weakness in my code is not just the allocation of vectors, but the fact that they force boxing and break the primitive chain. Another weakness is using results of loop because they also break the chain. Yep, performance in Clojure is still a minefield.

  • 1 1 Answer
  • 0 Views
  • 0 Followers
  • 0
Share
  • Facebook
  • Report

Leave an answer
Cancel reply

You must login to add an answer.

Forgot Password?

Need An Account, Sign Up Here

1 Answer

  • Voted
  • Oldest
  • Recent
  • Random
  1. Editorial Team
    Editorial Team
    2026-06-11T03:20:25+00:00Added an answer on June 11, 2026 at 3:20 am

    This version is based on @mikera’s, is just as fast and doesn’t require the use of ugly macros. On my machine this takes ~12ms vs ~9ms for java.util.Arrays/sort:

    (set! *unchecked-math* true)
    (set! *warn-on-reflection* true)
    
    (defn swap [^longs a ^long i ^long j]
      (let [t (aget a i)]
        (aset a i (aget a j))
        (aset a j t)))
    
    (defn ^long apartition [^longs a ^long pivot ^long i ^long j]
      (loop [i i j j]
        (if (<= i j)
          (let [v (aget a i)]
            (if (< v pivot)
              (recur (inc i) j)
              (do 
                (when (< i j) 
                  (aset a i (aget a j))
                  (aset a j v))
                (recur i (dec j)))))
          i)))
    
    (defn qsort 
      ([^longs a]
         (qsort a 0 (long (alength a))))
      ([^longs a ^long lo ^long hi]    
         (when
             (< (inc lo) hi)
           (let [pivot (aget a lo)
                 split (dec (apartition a pivot (inc lo) (dec hi)))]
             (when (> split lo)
               (swap a lo split))
             (qsort a lo split)
             (qsort a (inc split) hi)))
         a))
    
    (defn ^longs rand-long-array []
      (let [rnd (java.util.Random.)] 
        (long-array (repeatedly 100000 #(.nextLong rnd)))))
    
    (comment
      (dotimes [_ 10]
        (let [as (rand-long-array)]
          (time
           (dotimes [_ 1] 
             (qsort as)))))
      )
    

    The need for manual inlining is mostly unnecessary starting with Clojure 1.3. With a few type hints only on the function arguments the JVM will do the inlining for you. There is no need to cast index arguments to int for the the array operations – Clojure does this for you.

    One thing to watch out for is that nested loop/recur does present problems for JVM inlining since loop/recur doesn’t (at this time) support returning primitives. So you have to break apart your code into separate fns. This is for the best as nested loop/recurs get very ugly in Clojure anyhow.

    For a more detailed look on how to consistently achieve Java performance (when you actually need it) please examine and understand test.benchmark.

    • 0
    • Reply
    • Share
      Share
      • Share on Facebook
      • Share on Twitter
      • Share on LinkedIn
      • Share on WhatsApp
      • Report

Sidebar

Related Questions

Simple case of trying to prove I can convert NSString to NSDate . Create
I have been trying to use the Perl utility/module "prove" as a test harness
I'm trying to prove that changing document.domain can be used only for cross scripting
I'm trying to use heterogenous equality to prove statements involving this indexed datatype: data
I have been trying to maintain session vars between two subdomains and found it
Trying to prove correctness of a insertion function of elements into a bst I
I'm trying to prove the statement ~(a->~b) => a in a Hilbert style system.
Trying to build out an exception if move.UserId does not equal currentUserId then Redirect
Trying to make this jQuery filter that uses .find case-insensitive. For example, when the
Trying to figure out how I can do this properly. The print_r looks like

Explore

  • Home
  • Add group
  • Groups page
  • Communities
  • Questions
    • New Questions
    • Trending Questions
    • Must read Questions
    • Hot Questions
  • Polls
  • Tags
  • Badges
  • Users
  • Help
  • SEARCH

Footer

© 2021 The Archive Base. All Rights Reserved
With Love by The Archive Base

Insert/edit link

Enter the destination URL

Or link to existing content

    No search term specified. Showing recent items. Search or use up and down arrow keys to select an item.