Fork me on GitHub
#datomic
<
2018-01-28
>
cap10morgan00:01:24

so what should I do to enable a transactor to sustainably keep up with this load?

stuarthalloway12:01:16

@cap10morgan it depends on the load, can you describe it in some detail?

cap10morgan14:01:53

It's a high number of concurrent website users. They're signing up for our service through a multi-step process. This results in lots of transactions from various microservices to add their data to the database. When I scale up the cluster of services to hundreds of each, I find that things gets worse and Datomic throws back pressure alarms and the MemoryIndexMB gets pretty high. We've recently re-architected one of the services to pipeline transactions w/ transact-async, but I was hoping that we could also get a lot of transactions in flight by having many instances of the synchronous services. But it pretty quickly hits a bottleneck at the transactor, and I'm not sure how to widen it.

laujensen13:01:32

laujensen [2:25 PM]
I have an immutant app, which has many handlers responding to web requests. These pull out some data, generate some html and store some stuff in datomic. When it hands off to the browser, nothing is left hanging in memory. And still, once per day, sometimes twice, the entire system crashes due to the GC spinning out of control. What am I looking for?


noisesmith [2:27 PM]
> When it hands off to the browser, nothing is left hanging in memory.
do you have proof of this?
[2:29 PM]
doesn't datomic implicitly use a local cache so that you'd have to make new dbs and let the old be gc'd or else the other facts are sticking around in memory?

laujensen13:01:43

Is the peer library hoarding data?

laujensen13:01:16

Ive just run a profiler. As soon as the app is taken into use, datomic hoards 2gb of char[]. How do I control this?

stuarthalloway14:01:40

hi @laujensen — by Datomic do you mean peer, transactor, client, peer server, … ?

laujensen14:01:46

This is what happens to the heap when I trigger the first few handlers @stuarthalloway, GC does not diminish it, and the heapdump has 2GBs og char[] from Datomic

stuarthalloway14:01:13

lemme try it locally

stuarthalloway14:01:26

(with my own data -- back in a minute)

stuarthalloway14:01:22

how much JVM RAM are you allowing the peer?

laujensen14:01:46

The App and Peer have 3Gb

laujensen14:01:52

Same for Transactor

laujensen14:01:59

Would lowering the objectCacheMax reduce performance but guarantee lower memory footprint?

stuarthalloway14:01:20

I was about to say almost that

laujensen14:01:38

My OCM is 512m

stuarthalloway14:01:33

I just ran a peer on a small database here, confirming it doesn’t hold nearly that much memory

stuarthalloway14:01:56

so you have three variable knobs that relate to the size of your db

stuarthalloway14:01:03

1. objectCacheMax (like you said)

laujensen14:01:09

This is not a small db (relatively), its 25 websites, each holding about 20 pages, each having quite a bit of html and css stored in the db

stuarthalloway14:01:31

2. memoryIndexMax (unindexed log tail held in all peers)

stuarthalloway14:01:59

3. index nodes held in memory (implied by your usage)

stuarthalloway14:01:09

HTML and CSS do not make good datoms, better to content address them and store in S3

laujensen14:01:46

That would be better in terms of datomic, but we're rendering webpages in about 260msecs now and I'd hate to see that drop. Which reaching into s3 would do

laujensen14:01:01

But do you have a way for me to calculate a good objectMax for 3Gb total heap ?

robert-stuttaford14:01:03

core.memoize - put it on S3 but memoize it in memory

stuarthalloway14:01:48

or core.cached or guava — don’t think memoize evicts things

robert-stuttaford14:01:52

or even better use cloudfront and avoid dynamic processing

stuarthalloway14:01:11

if your HTML or CSS have occasional changes halfway down the page and you save the history, can be particularly nasty for Datomic indexes

stuarthalloway14:01:44

root and branch nodes must store a prefix big enough to distinguish two datoms

laujensen14:01:53

The HTML/CSS are frequently updated, as any change in the editor updates the datoms

stuarthalloway14:01:12

if those datoms are 50K HTML blobs that change say at the 25K mark, then you will blow up the dir and root nodes

laujensen14:01:26

Then Im pretty sure thats happening routinely

stuarthalloway14:01:58

this will get worse quickly as you add data

stuarthalloway14:01:17

and I am tallying another implicit vote for blob support in Datomic 🙂

laujensen14:01:54

This will be problematic to resolve then, as I need to store html/css outside datomic, and implement my own version control, for which Im relying on tx history now

stuarthalloway14:01:11

store the hash in Datomic and you still get version control

stuarthalloway14:01:34

the only thing you don’t get is garbage collection

stuarthalloway14:01:43

of S3 or wherever

laujensen14:01:58

Yeah hashes would work

laujensen14:01:15

Thanks for your input, very valuable! I'll start by reducing the OCM and then work out a file-storage solution

stuarthalloway14:01:56

@laujensen thanks for your feedback! definitely thinking about how to automate this in Datomic

robert-stuttaford14:01:30

@stuarthalloway what’s the backup/restore story for Cloud? could I e.g. restore an on-prem db?

stuarthalloway14:01:09

@robert-stuttaford still in development. There is more subtlety with Cloud being encrypted at rest

stuarthalloway14:01:09

teaser: Cloud’s support for the time model is superior to On-Prem in such a way that On-Prem data is insufficient to directly populate a Cloud database

laujensen14:01:09

@stuarthalloway thanks! And just an FYI, we would have switched to cloud ASAP if there was a good import story.

robert-stuttaford14:01:10

is it the plan to be able to restore from one to the other?

laujensen14:01:27

Ideally, just providing a datomic-uri during the first setup, and having it import everything

robert-stuttaford14:01:39

ah 🙂 now i’m super curious about how the time model is superior 🙂

laujensen14:01:47

We'd also want a backup-db option, but thats prio #2 🙂

stuarthalloway14:01:23

@laujensen hear you loud and clear. The import will need to have knobs to control how semantic differences are handled

robert-stuttaford14:01:07

are these semantic differences still in flux, @stuarthalloway? i’ve read the words you’ve shared thus far - curious what else has changed!

robert-stuttaford16:01:52

@stuarthalloway seems datomic-client doesn’t support [:find [?e ...] :in or [:find ?e . :in or [:find [?e] :in ? [:find ?e works fine. com.datomic/client-pro "0.8.14". "Only find-rel elements are allowed in client find-spec, see "

marshall17:01:52

@robert-stuttaford that's correct. Clients only support the relation find

marshall17:01:45

That's true of all clients (for peer server and for cloud)

robert-stuttaford17:01:32

gosh. might want to make that clear in the docs, @marshall 🙂 curious why that is?

robert-stuttaford17:01:40

right - i meant more that it was surprising that client doesn’t support this, and then i couldn’t find explicit mention of this difference in the docs, leading me to think i was doing something wrong

Chris Bidler17:01:32

Newbie question about this, just to help cement my own understanding: would you work around that limitation of the client query model by using a pull as your find-rel and then extracting your tuple or scalar therefrom?

robert-stuttaford18:01:15

@chris_johnson the pull result would still be wrapped in a vec, so even then, you still have to use first or similar to get at the value per result

robert-stuttaford19:01:42

datomic.api/squuid has no counterpart in Datomic Client. what’s the reasoning for that? it’s the only thing i was still using from Peer in a project i converted. happily i still have Datascript in the project, and could use its impl instead — however, i’m curious - what should folks typically do here?

denik17:01:43

@marshall it would be great if you guys communicated which API omissions of client between on-prem and cloud are permanent vs. temporary. For example, I found find-scalar very useful, and just refactored a ton of my code to use ffirsts due to the omission of it. It would be important for me to understand whether it was removed permanently because it’s considered a bad idea (and why) or because of technical limitations or if we can expect for it or a similar feature to come back.

robert-stuttaford17:01:39

i second this request from @U050CJFRU, @marshall. please let us know what the plan is?

jocrau19:01:20

I found squuids also useful for making the order of a returned collection deterministic when there is no order defined within the business domain.

favila19:01:20

:db/id is generally a better choice for that

jocrau14:01:35

I use Datomic on the JVM and Datascript in JS. IMO squuids are easier to create and need no correlation between client/server.

robert-stuttaford19:01:08

also amusing, needing this pattern to deal with the lack of d/entid / d/ident:

(defn ea->v [db e a]
  (get (d/pull db [a] e) a))

robert-stuttaford19:01:36

i must say, the client api feels a whole heck of a lot simpler and therefore approachable, so i’m feeling empathy for removing all these conveniences

denik17:01:43

@marshall it would be great if you guys communicated which API omissions of client between on-prem and cloud are permanent vs. temporary. For example, I found find-scalar very useful, and just refactored a ton of my code to use ffirsts due to the omission of it. It would be important for me to understand whether it was removed permanently because it’s considered a bad idea (and why) or because of technical limitations or if we can expect for it or a similar feature to come back.