This page is not created by, affiliated with, or supported by Slack Technologies, Inc.
2018-09-06
Channels
- # 100-days-of-code (15)
- # beginners (32)
- # calva (2)
- # cider (37)
- # clara (1)
- # cljs-dev (47)
- # clojure (177)
- # clojure-boston (1)
- # clojure-dev (2)
- # clojure-germany (1)
- # clojure-greece (5)
- # clojure-italy (13)
- # clojure-nl (2)
- # clojure-sanfrancisco (1)
- # clojure-uk (72)
- # clojurescript (46)
- # cursive (20)
- # datascript (7)
- # datomic (14)
- # devcards (6)
- # docker (1)
- # duct (1)
- # emacs (1)
- # figwheel (3)
- # figwheel-main (151)
- # graphql (2)
- # hyperfiddle (1)
- # interop (3)
- # jobs (3)
- # lumo (2)
- # off-topic (21)
- # pedestal (1)
- # re-frame (9)
- # reagent (25)
- # shadow-cljs (57)
- # slack-help (4)
- # specter (21)
- # tools-deps (53)
- # vim (2)
We are deeply concerned by clojure startup time. In order to fix that I want to reimplement clojure’s lambdas with MethodHandle and invokeDynamic. And after that, make vars initialization lazy. But it’s quite hard task to do with current Compiler impl.
if you aren't doing anything dynamic at runtime, you could check out Graalvm native execution
try the later version of the GraalVM, they just released Release Candidtate 6 with better support for resolving reflection cases
troubles with core-async and our huge java codebase that is not compatible with it either
have you spoken with @ghadi at all? he has done a lot of experiments with clojure and invoke dynamic
@hiredman can’t see where. even old compiled code will be compatible. it’s just another IFn impl
A MethodHandle is a reference to an already existing method in the JVM. Who loads that?
I don't doubt that, but with compiler improvements realistically you're going to shave a couple seconds off, max
why not just emit bytecode equivalent to that java does and delay as much work on vars init as possible.
heard about that, yeah. but that is classloading optimization. which could be optimized with method handles a lot more efficiently. imagine emitting one static class with static method per ns
you are talking about shift the work from loading each fn class and its single method, to analyzing all the static methods on a ns
java is quite good at that. the overhead per class is much bigger. (based on IntelliJ bytecode volume)
I would be very surprised if loading and verifying the bytecode isn't the dominating factor there
I think you are right to suspect that the volume of classes loaded is almost certainly the #1 issue
I thinks the problem there might be the interpretation. class initializers most probably are interpreted, not jitted. even small amount of work there can lead to significant slow-downs.
just don’t use vars where you don’t need them. do something clever with macros or something. but it is possible only after addressing the #1 problem
Yeah I remember talking to cfleming about this, I think he got spanked because cursive was slowing intellij startup
you might look at some of the clojure android stuff, they similar want basically and optimizing compiler
how do they do clojure on android with this problem? some byte code tree-shaking and post-processing?
clojure.core itself is quite fast to load. the problem seems to distribute between our codebase, datascript and core.async
Changing the way clojure loads namespaces is a promising possibility... You might break stuff though
@jetzajac clojure-android doesn’t solve this problem, which is one of the main reasons basically no-one uses it.
tools.emitter.jvm is not in a usable state right now, but it’s something I’ve thought about updating for similar reasons to yours.
Basically having a more hackable compiler. It’s much much slower than the Clojure compiler, but since I AOT I don’t care about that. Currently I run a fork of Clojure, and I’d much prefer to be able to implement the extensions I need as macros or analyser passes.
However I think the Clojure language design places some fundamental restrictions on startup time right now. It’s possible that redesigning the var implementation using indy might help that, but @ghadi is the man to ask about that.
@priornix We'll take it to DM (there's #slack-help BTW for general Slack questions)
I know one of the reasons you cant just trim out core statically is that any code can use "eval" and sidestep static analysis
I use eval as a JIT for my DSLs but I’m probably unique there :)
@jetzajac what problems are you experiencing with slow startup times? Most apps I’ve worked on in my Clojure career have taken close to a 60 Sec to start, none of them have been a problem beyond a slight annoyance.
Ah, I see, a plug-in
I'm using it for emacs like user config on my new browser written in clojure, works like a charm
people can bind any code expression or existing calls to any key without having to touch the source
Hello everyone,
So I'm trying to write a code for requesting quite large amount of URL using clj-http
. My approach right now is by using pmap
, it does the job, and I must note, faster than when I was using map
. But then I notice that because for each request I didn't use any connection pool, the number of connections opened correlates linearly with the number of the URL I requested, this is unfortunate, since most of those URLs came from the same domain. When I tried to use with-connection-pool
, wrapping my pmap
call, it often results in an error stating that the connection pool has already closed.
Has anybody ever succeeded in doing a bunch of HTTP requests in parallel, and by reusing connections?
@hawari.rahman17 you have to separate issues here. one is that http-kit
does not use connection pooling by default and is very eager . for that, your connection pooling should work, but if you use different domains, it would not. the other problem is the use of macros like with*
together wi realising lazy sequences. just wrap you pmap
with a doall
to prevent realising the lazy sequence after the pool is already closed.
for the general case of different domains I once use a java counting semaphore in combination with http-kit async api
You could wrap it in channels as well with core.async if you want to stay within Clojure.
Put the requests on a channel, have it take X requests, wait until those are done, put the results on another channel, take X more, and so on.
Hi @ido, your solution by using doall
to wrap pmap
successfully prevents the connection pool created by with-connection-pool
to be closed, but I don't understand why does it runs way slower than the "use pmap
, don't use connection pooling" solution, is it highly dependent on the number of maximum threads option assigned to it?
Hi @henrik, yes, core.async isn't a solution I've already explored yet, but I think I might need to state my use case first to improve the quality of discussion here:
My program first reads a response from a service in the forms of JSON. From this response, I want to hydrate each of the object, the hydration process involves calling another service which ideally I want to run concurrently.
So I tried to do the hydration requests in parallel using pmap
which works well until I realize that it is using a new connection for each request. Isn't using core.async will results in the same situation?On second thought, for that use case, is using a new connection for each request necessarily a bad thing? Will connection reuse actually prove to be helpful instead of becoming a bottleneck?
What caused me to worry is if for some reason the number of requests increases greatly, won't it exhaust the ports quickly if I stick to my current approach? What is the conventional wisdom here?
@hawari.rahman17 Here’s an example. This solves the number of concurrent requests, but doesn’t deal with connection reuse.
Ah, I see, maybe I can use this approach to use connection pool exclusively per partition, let's see if that's better Thank you for the inspiration @henrik
Can anyone recommend a clojure project that they really rate in terms of code style? I'd like to see how the pros do it
Do you mean this https://github.com/bbatsov/clojure-style-guide ?
I tried following the conventions mentioned in that guide here: https://github.com/manuel-uberti/boodle But I won't go as far as considering myself a pro 😄
check out Datascript: https://github.com/tonsky/datascript
Hmm I don’t see any conventions on given links
Thanks all - I meant just code I could look through to see how other have done it but all of that is useful - appreciated
Just wanted to give a heads up that I’ve created a new channel #healthcare for the discussion of clojure in healthcare. Thought it might be a good place for people working in or around that space to announce or collaborate on healthcare-specific libraries (FHIR specs, etc), for example.
Anyone with experience in message passing? I am trying to create a queue right now for a game where a user can cancel/accept.
tried to get some advice in /beginner a few days ago i dont really find much info on this subject. Maybe just suck at googling on this subject..
core.async is one way of doing coordination via queues (aka channels in this case) - it's a whole dsl for async
a "queue" displayed to a user is mode likely to be a model of a queue stored in something like a database
Well, I kind of have theese steps: • User clicks "Start" from the UI - will hit my api • I batch together users using LinkedBlockingQueue and refs • When 10 users are in the queue, I send a notification to the users. If they accept, I will create the game for them. If 1 user declines I will remove the declining user and re-fill the queue again. I think it's best to go with core async, and when I am done with the whole batching/accept-decline stuff I will send it on the message queue.
If I restart the server/crash it's ok to lose track of the users who are in "queue" so I can hold them in-memory I guess.
@hiredman I'll look into it. Thank you and @U051SS2EU for the advice, it's gold 🙂.
have some datastructure where you keep track of the state of each user :joined
:joining
:available
, and when a user joins, send-off something that adds them to the datastructure in the :available
state, then tries to select 10 :available
users and switch them to :joining
, before the send-off the user adds a watch to the agent and then when it sees its own record in the joining state, it can either accept (moves to :joined) or decline(moves back to :available)

you'll need some additional state so you know which group is joining into a game, etc

@hiredman do you think it's easier to seperate the queues into different stages. Like available-queue which only shuffles all users to joining-queue when enough users are found. And in the joining-queue have a datastructure like this:
{
;; agent! "78bc215a-5a52-442a-b5ed-acb4a446f0d3" {
:state :waiting
:start "yymmddssmm"
:game-type :chess1v1
"1337" :waiting
"1338" :accepted
"1339" :accepted
"1340" :waiting
}
}
Right now every single player is sent to a available queue which is wrapped in a agent with a watch attached to it. As soon as an item is inserted into the available-queue the watch is triggered and I check count etc. When the count is over the min-limit (2 atm) i take 2 items from the vectors head and create a new datastructure (as you see above). Might not be the best way to group things, but it's my plan right now to "group" things together.
If a player would send me cancel I will have the guid (key) of the map and send all the users who responded with "ok" into the available queue again. I need to automatically clear the map since it can be in :waiting for maximum of 10 seconds.with stages.. I mean something like this
(def available-queue (agent []))
(def joining-queue (agent {}))
A problem is that it's not syncronized though, so 1 player could possibly be joining the joining-queue twice I guess. Or well, with the watch this should not be a problem. Also since I have to "remove" users from the "available-queue" its costly.
swap! requires a function to apply, (#(str %) "foobar")
returns "foobar"
, which isn’t a function