276 karma · joined July 25, 2017
100x + 10y + z modulo 3
Removing 9y and 99x gives equivalence: x + y + z modulo 3
Now what’s left is induction with proper base (1-digit).
Provided that you can run multiple builds in parallel but each of them has somehow limited parallelization.
Added talk to the watch later list.
“The luck favors the prepared”
Most languages tend to produce a distinct behavior patterns and properties, such as (in no particular order):
- multi-threaded / single-threaded / multi-process
- frequency of memory safety bugs
- broken locale / unicode handling
- broken or non-standard network settings handling
- only synchronous I/O calls (or in contrast only async I/O)
- releasing memory back to OS (or not)
- fragmenting heap over time (or not)
- fast / slow text processing
- fast / slow binary codecs
- it introduces its own vocabulary, it looks like gibberish until you build up the context
- since the group is small and gifted they have no problem creating and using the power tools of their own
- there is no documentation so your only way is through experimentation and direct communication
- the folks who have built it had to move on to solve another (bigger) problem, leaving no traces of what the vocabulary is, where the design was headed, what should be changed with the new requirements and again next to zero documentation
A - accumulator
X - wildcard for both upper and lower 8-bit parts, this becomes redundant b/c of E prefix
- Avro
- CBOR
- SMILE
And BSON anyone? I think not much people besides MongoDB using it though.
Yes, compressing JSON with gzip-style compressor usually yields 0.5-1% better results then equally compressed binary format (in my limited testing). Still the serialization speed and savings on compression are great to have.
Yes, on 32-bit platform false pointers are a problem esp as you get closer to 1g for instance.
On the other hand on 64-bit I’ve never seen it at all. The chance of arbitrary long/double to point to some object in the heap area is 1/2^32 smaller and that turns the problem from common nuisance to purely theoretical problem.
During _collection_ and N is size of live set, so divided by allocation the cost is amortized and can safely considered as O(1) much like appending a dynamic array where costly O(N) resize is amortized over N appends.
Typically GCs allocate via bump a pointer allocation which is actually faster then what pretty much all of libc malloc implementations would do.
> C++ case iterates over nothing (incurring a cost of O(1)).
Not quite, take a look at jemalloc paper for instance:
https://www.facebook.com/notes/facebook-engineering/scalable...
A lookup to get the metadata for this specific allocation could be anything from O(1) to O(lgN) depending on size and malloc strategy.
Which I believe is the important distinction, and quite often it doesn’t know or care “which allocations to free” because it does it in bulk. That allows it to be efficient.
There is no known algorithm for GC that searches for garbage to delete, the way GCs work is exactly opposite - find all live objects (reachable from roots - registers,stack, statics/globals) and the rest of the heap by definition is garbage.
Classic uncompressed trie sucks pretty much in all cases.
Now if we go for half-decent implementation of packed variation, it does get significantly better:
Sadly at the time there was a big perf problem with indexingdocuments with 20kb+ binary blobs (non-indexed field) and so the change to 2 nodes vs one did have little noticeable effect on the throughput benchmarks I did with our data back then (~2015 ES 1.4) In the end I dropped this split and focused on the other bigger problems.
Would love to revisit this exercise with more of free time and better tools.
Hope to work with you guys on OpenDistro more closely in the future.
Not every application is the same but the moment it involves manipulating a lot of data in Java you fight the platform to get back the control you require for those things. And by the end of day there is a limit at which reasonable people stop and just give up dodging memory allocations, creatively reusing objects, wrangling off-heap memory without the help of type system.
As far as number of shards per index goes there are many considerations some good ones are outlined in the article.
I tried reaching out on forums and was assured they’d get to it. I’m used to things going slow in OpenSource so not too worried at this point.
Would be lovely to upstream it though, as I’ve patched 2 versions now and not looking forward to continue doing so ;) Plus I’d be glad to contribute more things based on our experience running ODFE, I’m very intrigued by other upcoming plugins in ODFE repos as well.
In short there are many variables at play, but without any context generally I’d recommend trying many small instances first. Now depending on your hardware, scale and application things may easily change in favor of big iron.
Do JSON logs take gigabytes?
If they do for you then yes, gigabytes of disk and memory are pretty much guaranteed. Also things tend to pile up with time (even on a few weeks horizon).
In all honesty, I believe a finely crafted native code solution for this problem could achieve x3 less ram usage and x2-3 indexing/search performance. Going beyond that is also possible but will take remarkable engineering.
Update: to expand on the last point, c++ solutions are typically closed sourced. Rust and Go both have interesting open-source full text engines: https://github.com/tantivy-search/tantivy https://github.com/blevesearch/bleve
In near future I totally see someone producing a great open-source distributed search project that is at least on par with today’s ES core feature set.
Simple catalogs and/or web pages search usually fit in RAM, so the advice of disk:ram becomes less relevant, also the type of drive would be mostly irrelevant.
Still waiting on these guys to review my perf patch though:
https://github.com/opendistro-for-elasticsearch/security/pul...
Running with oom circuit-breakers disabled is something I’m currently considering.
In particular full GC is parallel since 10: https://openjdk.java.net/jeps/307
Going beyond dozens takes a fair amount of tuning and trouble-shooting.
There are both advantages and disadvantages. On plus side:
- easier to manage several big machines than shitload of small instances potentially on top of virtualization solution (debugging overlay network etc. at night is not fun)
- nodes are more resilient to big requests (both big bulk indexing and resource-heavy searches). Your risk of hitting sudden OOM is practically zero (although ES does have circuit-breakers that try to prevent processing requests that would cause OOM)
- while not having compressed oops is sad, not having multiple copies of JIT and compiled code cache etc. is a plus
- using a modern concurrent GC is more sensible on bigger heaps. G1 is actually fine on 64g. Some of us are running Shenandoah on Java 13 in production, I’m looking forward to apply it on my clusters (or get back to testing ZGC).
Disadvantages:
- NUMA. Try to pick more recent Java as it’s tuned to run better on NUMA machines, still not all of JVM is NUMA-aware
- fault domain is larger and getting hot node up to speed (in-sync) after restart can easily take about an hour. Getting it up from empty storage going to take a bloody while
- elastic.co folks seem to have recommended settings for lots of small nodes not big ones, so you are on your own to discover proper limits for every setting