#clojure logs

2008-06-25

00:34jgrantanyone had any experience with jvm on FreeBSD multi-core systems ?
00:35jgranti have a multi-threaded app written in clojure and i'm not seeing it(probably the jvm) distribute threads across the 4 cores ?
00:36jgrantUsing jdk-1.6 on FreeBSD 7.0 SMP (4 cores)
00:36jgrantsurely the jvm uses native threads ?
00:37jgrantthe java process itself will shift between the 4 cores but top reports only 25% cpu usage (100% for the cpu that the process is currently running on)
01:33albinojgrant: are you using the jvm that comes with freebsd?
01:57jgrantalbino : i'm using the port jdk16
02:00jgrantok i just figured out that it is not the jvm on freebsd7
02:00jgrantthe following simple code maxes out all 4 cores :
02:00jgrantpublic class Test implements Runnable
02:00jgrant{
02:00jgrant private volatile int m_counter;
02:00jgrant public void run()
02:00jgrant {
02:00jgrant for (;;)
02:00jgrant for (int i = 0; i < 1000000; i++)
02:00jgrant m_counter++;
02:00jgrant }
02:00jgrant public static void main(String[] args)
02:00jgrant {
02:00jgrant Test test1 = new Test();
02:01jgrant Test test2 = new Test();
02:01jgrant Test test3 = new Test();
02:01jgrant Test test4 = new Test();
02:01jgrant Thread thread1 = new Thread(test1);
02:01jgrant Thread thread2 = new Thread(test2);
02:01jgrant Thread thread3 = new Thread(test3);
02:01jgrant Thread thread4 = new Thread(test4);
02:01jgrant thread1.start(); thread2.start(); thread3.start(); thread4.start();
02:01jgrant try {
02:01jgrant thread1.join(); thread2.join(); thread3.join(); thread4.join();
02:01jgrant } catch (InterruptedException iex) {
02:01jgrant System.out.println(iex);
02:01jgrant }
02:01jgrant if (test1.m_counter == test2.m_counter)
02:01jgrant System.out.println("Don't care, this is just to fool the optimiser");
02:01jgrant }
02:01jgrant}
02:05albinojgrant: for code of that size please use a pastebin
02:07jgrantsure
02:07cgrandjgrant: what is the problem? Maxing out 4 cores is expected: you put each core in a busy loop.
02:09jgrantno no, that is an example of what i want, i.e. to max out cores
02:10jgrantbut in my other code ( a socket listener ) it sticks to one core only even though it's using a newFixedThreadPool
02:10jgrantthe other code is in clojure too
02:11jgranti've heard the synchronized blocks can cause that sometimes
02:13jgrantrich's example of parrallel map apparently works --> http://clojure.org/refs
02:13cgrandcan you paste some code?
02:14cgrandhttp://paste.lisp.org/new/clojure
02:14lisppaste8jgrant pasted "jgrant" at http://paste.lisp.org/display/62808
02:15jgrantit makes use of a single ServeSocket and pool is just pool (. Executors (newFixedThreadPool nthreads))
02:15jgrantwhere nthreads is 64
02:19jgranthandle-req function is trivial it just reads the input from sin and writes some simple text out
02:28cgrandhow do you stress this server?
02:29jgrantab -v1 -n 10000000 -c 400 http://127.0.0.1:8000/
02:29jgrantusing apache bench
02:29jgrantit's picky, only accepts ips for url
02:32cgrandyou said that this code "sticks to one core only" but does it max out during ab runs?
02:32jgrantit maxes out only one core
02:32jgrantwhen running ab to stress it
02:32cgrandok
02:34cgrandand if you try to put some more "stuff to do" in your handle-req (eg a small busy loop) does it still stick to one core?
02:38jgrant (. Thread (sleep 100)) is what i tried at the end of handle-req and that makes no difference
02:39jgrantanother detail : each thread updates a global ref defined as (def *serve-count* (ref 0))
02:39jgrantby calling (dosync
02:39jgrant (commute *serve-count* inc))
02:39jgrantcould that be a problem ?
02:41cgrand(. Thread (sleep 100)) doesn't keep the cpu busy, so the scheduler can hand it another thread -- it just prevents the executor from sending a new job.
02:41jgrantdo you have an example of 'busy loop' ?
02:42cgrandI haven't had any pb with (dosync (commute *something* inc)) so far (on windows, linux and solaris)
02:42jgrantme either on OS X / FreeBSD
02:42jgranti may have seen some on linux
02:44cgrandbusy loop (reduce + (range 1000000))
02:46jgranthandle-req is already reading the input and generating a response then sending it back
02:47jgrantsurely that is 'busy' enough for each thread ?
02:50cgrandI can't tell. Does the pb go away when you remove the code updating the global ref?
02:53jgrantno
03:37cgrandjgrant: I tried to write a server that reads 3 lines and send them back mirrored (using yiour main loop), I stressed it with your ab command line, CPU usage stayed around 100%. I then added (reduce + (range 1000000)) at the start of handle-req and CPU usage maxed out (>190%, dual core -- I even saw 202% at some point :-))
03:38jgrantah
03:38jgrantso i guess just sending a response is not enough stress for the jvm to spread the threads across cpus then ?
03:39jgranthow many threads did you use in ab and how many did you use for the thread pool ?
03:40cgrandfor ab I used your command line as is and 64 threads in the pool
03:49jgrantcgrand : thanks i verified the same
03:49jgrantcgrand : the socket handling is not enough to require more than one cpu it seems
03:50cgrandor it requires too much syscalls
03:51jgrantno don't think that's it because leaving the socket handling in but adding the reduce call makes use of multiple cpus
03:53jgrantturning up ab concurrent clients may get multiple cpu usage
03:53jgrantbut the socket handling may be the bottle neck at that point
08:47wwmorgan(= (disj (sorted-set :a) :a) (sorted-set)) evaluates to false but it should be true
09:28wwmorganrhickey: that's a bug, right?
09:35cgrandwwwmorgan, in the meantime you can fix it in your copy by replacing ([] {}) with ([] (. clojure.lang.PersistentTreeSet EMPTY)) in the def of reduce-set in boot.clj, it should do the trick
09:43wwmorgancgrand: thanks
09:44cgrandwwmorgan: it seems that you can even delete this line entirely
11:30cemericklooks like genclass.clj isn't loaded by default -- am I crazy, or wasn't that being loaded automatically before?
12:44Lau_of_DKEvening Gents
12:45blackdogcemerick, you can load the base cljs like this (import '(clojure.lang RT))
12:45blackdog(. RT loadResourceScript "inspector.clj")
12:57cgrandLau_of_DK: evening
13:11Lau_of_DKI remember somebody mentioning porting Clojure to ikvm - I just want to know, does this mean that Clojure can run on .Net without making any use of Java whatsoever?
13:13blackdogLau_of_DK, it was cemerick who was talking about that
13:13Lau_of_DKcemerick: awake and educate :)
13:13blackdogalthough i think he was La_mer at the time
13:14cemerickblackdog: regarding genclass.clj, etc., I know about loadResourceScript and such -- I was just hoping to avoid having to bring up the "standard libraries" myself ahead of generating classfiles
13:14blackdogk
13:15cemerickAnd yes, I was la_mer until recently -- changed to cemerick so that people in the real world would know who I was and vice versa
13:15Lau_of_DKcemerick: Did I understand you correctly? You got Clojure running on pure .Net ? No Java...
13:15cemerickLau_of_DK: ikvm/ikvmc allows you to use just about any java library in .NET without the JVM -- the java standard libraries are required, though (and are provided as DLL's by ikvm)
13:16Lau_of_DKOh ok. That provides a gigantic performance boost doesnt iT?
13:18cemerickLau_of_DK: Well, keep in mind that .NET is a runtime just like the jvm -- it's not like Clojure (or any other java lib) is being distilled to a native library.
13:19cemerickSo, performance is good as a ikvm-generated DLL -- good enough that I haven't benchmarked things in that area for a long time.
13:20blackdogcemerick, so you use ikvm for production stuff?
13:21cemerickblackdog: Yes: http://snowtide.com/PDFTextStream.NET
13:21blackdoghave you used it for long running servers?
13:21cemerickYes, although our customers beat it up more than we do....with good results. :-)
13:21blackdogah ok,
13:21Lau_of_DKpretty awesome
13:22cemerickThere was a hiccup recently related to the correspondence between classloaders and AppDomains, but that was fixed in ikvm v0.34, IIRC
13:22blackdogit's amazing, and ikvm done by one guy too
13:22Lau_of_DKThere are a few guys gifted with unique intellects obviously
13:23cemerickWe're pretty far behind in the ikvm releases (for PDFTextStream, anyway), simply because we have customers on .NET 1.1 still.
13:23blackdogi've seen snowtide befoer somewhere
13:23Lau_of_DK.Net is backwards compatible - why not upgrade?
13:25blackdogah
13:25blackdogthat's where, i ported your difflib libaray to haxe
13:26blackdogah and you are chas emerick the author of the difflib
13:26cemerickLau_of_DK: Yes and no -- ikvm v0.36 doesn't support .NET 1.1, only 2.0+
13:26cemerickblackdog: Indeed. Nice to meet you. I'm glad to see that jsdifflib is getting around. :-)
13:27cemerickI'm afraid it's pretty neglected at this point.
13:27blackdog:)
13:27blackdogas is my port
13:27cemerickThanks for mentioning haxe -- I hadn't seen it before.
13:27blackdoghaxe was last years language du jour, now it's clo jure
13:28blackdogit does rock
13:28blackdogbut the server side story is weak, hence i'm looking at jvm/clojure
13:28cemerickSo, given that genclass and friends aren't loaded by default, is there a "recommended" way to bootstrap clojure maximally? I'd like to not reinvent the wheel.
13:29cemerick(if a such a wheel exists, I suppose)
13:43Lau_of_DKcemerick: if the wheel does exist, it just stopped turning
13:43rhickeyuser.clj is auto-loaded
14:08cemerickrhickey: That's interesting; user.clj in pwd is autoloaded -- is there a standard search path for finding user.clj (pwd, ~/.user.clj, etc)?
14:10rhickeyit uses the classpath
14:24cemerickA good and bad thing ;-)
15:28cemerickrhickey: you mentioned (.get clojure.lang.Compiler/SOURCE_PATH) yesterday -- that works great when you're using load-file, but it's a relative path (relative to the classpath entry's root, I suppose) when the file being loaded is user.clp
15:30cemerickI know it's an unofficial API point, but I thought I'd mention it anyway :-)
15:30Lau_of_DKHas anybody started any bigger projects in Clojure yet ?
15:30Lau_of_DK(bigger = bigger than a port of msPaint)
15:31cemerickLau_of_DK: I'm guessing that no one's going to spill the beans until there's something impressive to look at. ;-)
15:31arbschtI have difficulty making my projects look big when written in lisp :)
15:40Lau_of_DKcemerick: sure - It'd just be nice with some inspiration - Im not sure Im fully grasping the possibilities yet
15:40Lau_of_DKLike Rich talked about Election Projection systems... I have no clue :)
16:13abw_hello guys, could someone tell me how to go through the sexp history in the clojure repl as rich hickey did in the screencast?
16:13drewrabw_: Got Emacs?
16:13abw_yes
16:14abw_and all the clojure code stuffs
16:15drewrThen M-p, my friend.
16:15drewrJust like anything else.
16:16abw_drewr: great, thanks!
16:17cemerickabw_: FWIW, it's Ctrl-up in Enclojure :-)
16:17cemerick(just in case you want to join the herd someday ;-) )
16:24abw_cemerick:cool, I've noted that for when enclojure gets more mature
16:59abw_I'm thinking of writing a ClojureTutorial app once I know the Clojure language more completely and with more experience. It will draw ideas from Lisp Critic and the socratic method and work like a more computationally intelligent text based adventure game because of the Lisp Critic. Right now I am taking notes on what it's like to know less Clojure, how I learn it and what the knowledge dependancies are.
17:31cemerickrhickey: I'm having trouble defining a method for a class in gen-and-save-class that has as a return type the generated class. I'd like to do this, but gen-class complains that the 'pkg.Foo symbol doesn't have a getType method: (gen-and-save-class "." 'pkg.Foo :implements [Bar] :methods [['union [java.util.Collection] 'pkg.Foo]])
18:13pjb3Hey clojurers, I just wrote up a function to execute a sql query and return the first column of the first row as a string
18:13pjb3http://pastie.org/222226
18:13pjb3So if you execute (db/select-first "SELECT login FROM users")
18:13pjb3You get "pbarry"
18:14pjb3Any comments on the code? I'm wondering if there are better, more idiomatic ways to do that
18:18pjb3specifically I'm wondering how to put a try/catch statement into do-with-connection, which will always make sure the connection gets closed
18:31lisppaste8blackdog pasted "sql" at http://paste.lisp.org/display/62844
18:31blackdogpjb3, i'm using that
18:33blackdogi can't tell you if it's better or not as i'm new to clojure too, but it's different !
18:34pjb3What happens when getConnection throws an exception?
18:35blackdogoh i didn't hand;e that :)
18:36pjb3Yeah, this is the Java code: http://pastie.org/222245
18:37pjb3You set con to null, then do the getConnection in the try, and then check to see if con is null in the finally
18:37pjb3but I can't figure out how you would do that in clojure
18:37blackdogoh
18:37pjb3since you can't let [con nil] and then change it later
18:37blackdogyea i see
18:38pjb3rhickey: help?
18:38blackdogwell i suppose it's the same as with-open in boot.clj
18:38blackdogsomehow it doesn't matter :)
18:39blackdogi don't know
18:39blackdogyes, now i realise i glossed over the matter
18:42pjb3To use with-open, wouldn't it be (with-open con (.getConnection DriverManager "jdbc:whatever") (stuff))
18:42pjb3which gives you the same problem, because the call to .getConnection happens outside the try
18:51lisppaste8pjb3 pasted "with-connection" at http://paste.lisp.org/display/62845
19:14jgrantIs it really not possible to modify a hash map created with (hash-map ...) ?
19:14jgrant(get mymap :key) works
19:14jgrant(put mymap : val) fails ?
19:15jgrantthat is (put mymap :key val) fails ?
19:24jgrantanyone ?
19:24jgrantor should i just use Java's HashMap class instead ?
19:30jgrantok assoc works (i guess i should read the API more carefully)
21:16abw_the clojure-mode does not detect soft word wrapping of Clojure comments in Aquamacs highlighting the wrapped comments as code. Anyone else notice this bug?
21:22pjb3If I try to add metadata to a java object, specifically a java.sql.ResultSet, I get a java.lang.IncompatibleClassChangeError
21:22pjb3Is that to be expected?
22:29rhickeypjb3: metadata is only supported on certain Clojure data structures - symbols and collections
22:29pjb3rhickey: Ok
22:31cemerickrhickey: Good evening. I don't suppose you noticed my note about regarding defining methods that take or return the type that is being generated....
22:32rhickeyyes, when I saw it you weren't on - right now there is no way to do that
22:34rhickeyI'll look into it
22:38cemerickrhickey: That's what I thought. I've been idly working on understanding what's going on in gen-class, and I think I can see what needs to be done, though dimly. :-)