I'm new to Clojure so bare with me, but I'm trying to figure out what it does...
Is it doing something like this: user=> (apply pr (.split #"\n" (str "hello\n" "world\n"))) "hello" "world"nil Or do you want those concatenated? Or is that too slow? On Tue, Jul 28, 2009 at 12:07 AM, Mark Addleman <mark_addle...@bigfoot.com>wrote: > > I have written some Clojure code to implement java.lang.CharSequence > that is constructed with a length and an ISeq of strings. I need this > because I want to pass the resulting CharSequence into Java's regex > library. I got the thing working (thanks to the docs and some good > examples that I found in the discussion group) and I'm trying to > optimize it now. I'm willing to accept the Clojure code being ~2x > slower than the Java equivalent, but the best I can do is 10x slower. > > The code is below. After examining the resulting bytecode, it looks > to me that the problem is that the Clojure compiler dispatches every > method to an IFn that is bound as part of the class initialization. > It's a cool idea that probably saved implementation effort but I'm > pretty sure all the boxing/unboxing of primitives is what's killing > the performance. > > My question is: Can someone come up with a better way of implementing > this to avoid the performance problems? > > ;; char_sequence > > (ns SeqCharSequence > (:gen-class > :implements [java.lang.CharSequence] > :init init > :state state > :constructors {[Integer Object] []}) > (:use > [clojure.contrib.test-is])) > > (defstruct state-struct > :buffer > :strings > :length) > > (defn -init [length strings] > [[] > (struct state-struct (StringBuilder.) (atom strings) length)]) > > (defmacro ensure-capacity [state index] > `(let [{#^StringBuilder buffer# :buffer} ~state] > (while (>= ~index (. buffer# (length))) > (let [{strings# :strings} ~state > strings-seq# @strings# > #^String newString# (first strings-seq#)] > (. buffer# (append newString#)) > (compare-and-set! strings# strings-seq# > (rest strings-seq#)))) > buffer#)) > > (defn -charAt [#^SeqCharSequence this i] > (let [#^StringBuilder buffer (ensure-capacity (.state this) i)] > (. buffer (charAt i)))) > > (defn -subSequence [#^SeqCharSequence this start end] > (let [state (.state this) > #^StringBuilder buffer (ensure-capacity > state end)] > (. buffer subSequence start end))) > > (defn -length [#^SeqCharSequence this] > (let [{length :length} (.state this)] > length)) > > (defn -toString [#^SeqCharSequence this] > (let [length (. this (length)) > #^CharSequence charSequence (. this > subSequence 0 length)] > (String. charSequence))) > > (deftest performance-test > (let [words ["hello\n" "world\n"] > #^java.util.regex.Pattern pattern #"\n"] > (time (dotimes [_ 10000000] > (let [#^SeqCharSequence cs (SeqCharSequence. 10 > words)] > (. pattern split cs)))))) > > (deftest test-length > (let [cs (SeqCharSequence. 10 ["hello" "world"])] > (is (= 10 (. cs (length)))))) > > (deftest test-toString > (let [cs (SeqCharSequence. 10 ["hello" "world"])] > (is (= "helloworld" (. cs (toString)))))) > > fyi - I made ensure-capacity a macro in an effort to avoid boxing/ > unboxing before I realized how the dispatching to IFns worked. > > > -- John --~--~---------~--~----~------------~-------~--~----~ 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 -~----------~----~----~----~------~----~------~--~---