53 karma · joined March 6, 2022
Can't wait to hear about this brand new approach from my managers and VP.
Meanwhile, for a software business, Github is a wide and deep attack vector and nobody seems to be concerned about it.
Of course the same can be said about any other public git hosting, especially if it combines CI/CD, artifact distribution, identity and trust management.
That is a cynical take and not very different from an advice to never write any documentation, or never help your teammates. Only that resemblance is superficial. In any organization you shouldn't help people stealing you time for their benefit (Sean Goedecke calls them predators https://www.seangoedecke.com/predators/).
On the other hand, it may be beneficial to privately save CLAUDE.md and other parts of persistent context. You may gitignore them (but that will be conspicuous unless you also gitignore .gitignore) or just load them from ~/.claude
I expect an enterprise version of Claude Code that will save any human input to the org servers for later use.
- schema-less: we don't have to think about DDL statements at any point.
- oplog and change streams as built-in change data capture.
- it's dead simple to setup a whole new cluster (replica set).
- IMO you don't need a designated DBA to manage tens of replica sets.
- Query language is rather low-level and that makes performance choices explicit.
But I have to admit that our requirements and architecture play to the strength of mongodb. Our domain model is neatly described in a strongly typed language. And we use a sort of event sourcing.
https://www.mongodb.com/company/blog/product-release-announc...
In the beginning there was a need for a low-latency Java in-process database (or near cache). Soon intolerable GC pauses pushed them off the Java heap. Next they saw the memory consumption balloon: the object graph is gone and each object has to hold copies of referenced objects, all those Strings, Dates etc. Then the authors came up with ordinals, which are... I mean why not call them pointers? (https://hollow.how/advanced-topics/#in-memory-data-layout)
That is wild speculation ofc. And I don't mean to belittle the authors' effort: the really complex part is making the whole thing perform outside of simple use cases.
I think it boils down to the power of balance in the org. Likewise I've met developers who cannot book a meeting. Some people have privilege to choose what to learn and what to laugh at. Actually, I'm surprised your sales guys wrote any documentation at all:)
Yes, but isn't it insane? What is the benefit from treating your own product as a black box? Yet that's mainstream. Sometimes I have the analyst (not on my team, but from a team we share a monorepo with) asking me questions that can be answered literally with a line of code. And she's a technical kind, knows SQL and such. And we write very idiomatic, high level code. But still, culture cannot change itself until it dies due to inherent inefficiency.
On a personal level I'm interested too. My son is too young, so we only watch youtube together, even then he's very susceptible to the attention-grabbing recommendations. "Theater mode" helps put the recommendations off-screen. "Don't recommend channel" helps a curate the feed a little bit.
But ideally I should be in control of the whole interface.
Anyway, I felt I had to run the benchmarks myself.
@Benchmark
@Fork(1)
@BenchmarkMode(Mode.Throughput)
@OutputTimeUnit(TimeUnit.SECONDS)
public Object arrayListPreallocAddMillionNulls() {
ArrayList<Object> arrList = new ArrayList<>(1048576);
for (int i = 0; i <= 1_000_000; i++) {
arrList.add(null);
}
return arrList;
}
@Benchmark
@Fork(1)
@BenchmarkMode(Mode.Throughput)
@OutputTimeUnit(TimeUnit.SECONDS)
public Object arrayListAddMillionNulls() {
ArrayList<Object> arrList = new ArrayList<>();
for (int i = 0; i <= 1_000_000; i++) {
arrList.add(null);
}
return arrList;
}
@Benchmark
@Fork(1)
@BenchmarkMode(Mode.Throughput)
@OutputTimeUnit(TimeUnit.SECONDS)
public Object linkedListAddMillionNulls() {
LinkedList<Object> linkList = new LinkedList<>();
for (int i = 0; i <= 1_000_000; i++) {
linkList.add(null);
}
return linkList;
}
And as I expected, on JDK 8 ArrayList with an appropriate initial capacity was faster than LinkedList. Admittedly not an order of magnitude difference, only 1.7x. JDK8
Benchmark Mode Cnt Score Error Units
MyBenchmark.arrayListAddMillionNulls thrpt 5 229.950 ± 9.994 ops/s
MyBenchmark.arrayListPreallocAddMillionNulls thrpt 5 344.116 ± 7.070 ops/s
MyBenchmark.linkedListAddMillionNulls thrpt 5 199.446 ± 15.910 ops/s
But! On JDK 17 the situation is completely upside-down: JDK17
Benchmark Mode Cnt Score Error Units
MyBenchmark.arrayListAddMillionNulls thrpt 5 90.462 ± 18.576 ops/s
MyBenchmark.arrayListPreallocAddMillionNulls thrpt 5 214.079 ± 15.505 ops/s
MyBenchmark.linkedListAddMillionNulls thrpt 5 216.796 ± 19.392 ops/s
I wonder why ArrayList with default initial capacity got so much worse. Worth investigating further.While right now I enjoy the privilege to develop on Linux, things may change.
What I didn't find is a mention of a context when reading a particular function. For example, while programming in Scala I was burnt more than once by one particular anti-pattern.
Suppose you have a collection of items which have some numerical property and you want a simple sum of that numbers. Think of shopping cart items with VAT tax on them, or portfolio positions each with a PnL number. Scala with monads and type inference makes it easy and subjectively elegant to write e.g.
val totalVAT = items.map(_.vat).sum
But if `items` were a `Set[]` and some of the items happened to have the same tax on them, you would get a Set of numbers and a wrong sum in the end.You could append to the list of such things until the OutOfMemoryError. But it's such a beautiful and powerful language. Sigh.