The better question to ask is this real code you intend on using? Are you
really going to generate 100,000 random keys of 1024 chars each all at once
in a real running program?

(def *valid-chars* [\a \b \c \d \e \f \g \h \i \j \k \l \m
    \n \o \p \q \r \s \t \u \v \w \x \u \z
    \0 \1 \2 \3 \4 \5 \6 \7 \8 \9])
(def *len* (count *valid-chars*))
(defn rand-char [] (nth *valid-chars* (rand-int *len*)))
(defn generate-key [keylength]
  (take keylength (repeatedly rand-char)))

(apply str (generate-key 1024)))

This program is about twice as slow as your optimized Clojure.

If you actually need to generate all these keys at once then why not just
write it in Java and make a nice Clojure function wrapper for it? If you're
aren't going to generate all these keys at once then this cost is
distributed over the actual runtime behavior of your program and in that
case, does it really matter for your specific use case?

On Fri, Oct 30, 2009 at 4:56 PM, Chick Corea <chick.zco...@gmail.com> wrote:

>
> How do I make this code faster?  And leaner, i.e., use less memory ?
>
> It's a simple function to generate NUMKEYS strings of length
> KEYLENGTH,
> store them in a Java array then store them in a HashMap<String,Object>
> hash-map.  [it doesn't store them in the hash-map yet; but it
> allocates it]
>
> (set! *warn-on-reflection* true)
>
> (def *valid-chars* [ \a \b \c \d \e \f \g \h \i \j \k \l \m
>                     \n \o \p \q \r \s \t \u \v \w \x \u \z
>                     \0 \1 \2 \3 \4 \5 \6 \7 \8 \9 ] )
>
> (defn generate-random-keys [ numkeys keylength ]
>  (time
>   (let [ rand (new java.util.Random)
>         key (make-array Character/TYPE keylength) ;;  :initial-
> element \a))
>         keys (make-array String numkeys)
>         data (new java.util.HashMap (int numkeys))
>         ]
>     (.println System/out (format "generating [%d] keys of length
> [%d]" numkeys keylength ))
>     (dotimes [i numkeys]
>       (dotimes [j keylength]
>         (aset key j (nth *valid-chars* (. rand nextInt (int 36)))))
>       (let [tmp (String. #^chars key) ]
>         ;;       (.println System/out (format "keys[%d] => [%s]" i
> tmp))
>         (aset keys i tmp)))
>     (.println System/out (format "inserting [%d] keys into HashMap"
> numkeys)))))
>
> (generate-random-keys 100000 1024)  ;; 100k strings, 1024-chars each
>
> The corresponding Java code (w/ the hash-insert omitted in the clojure
> version)
> runs in 5.5sec and uses 290MB.
>
> This code runs (which omits the hash-insert) runs in 17.8sec and uses
> 353MB.
>
> I thought that I added all of the casts and "warn-on-reflections" that
> would help.
> Also, I thought using Java data structures directly would bypass some
> of Clojure's
> overhead.  What am I missing?
>
> Granted, the initial memory allocated is
>
>        * for POJ, ~12MB
>        * for Clojure, ~90MB
>
> That may or may  not be relevant.  It's hard to know w/ auto mem-mgmt.
>
>
> CHICKEE
>
>
> >
>

--~--~---------~--~----~------------~-------~--~----~
You received this message because you are subscribed to the Google
Groups "Clojure" group.
To post to this group, send email to clojure@googlegroups.com
Note that posts from new members are moderated - please be patient with your 
first post.
To unsubscribe from this group, send email to
clojure+unsubscr...@googlegroups.com
For more options, visit this group at
http://groups.google.com/group/clojure?hl=en
-~----------~----~----~----~------~----~------~--~---

Reply via email to