Benchmarking is a mess everywhere. Sure you can get some level of accuracy but reproducing any kind of benchmark results across machines is impossible. That's why perf people focus on things like CPU cycles, heap size, cache access etc instead of time. Even with multiple runs and averaged out results you can only get a surface level idea of how your code is actually performing.
HN user
thecodrr
Building Notesnook: https://notesnook.com
React is not slow. React is not "big". React is not the reason your website is slow.
Any engineer who thinks that its React that is causing the slow renders and replacing it with X is deluded. Yes, there are ways to make slow React web apps. But there are also ways to make fast React web apps. It just requires effort and a little bit of foresight.
You might want to give Notesnook [0] a try.
You'd already be using source maps in any real-world scenario so I am not sure what's the value proposition here outside of "just for fun, I guess".
The tsc transpilation to lower ES versions is actually really useful when using not-so-recent Node versions. Not to mention this severely restricts TypeScript syntax to "just types" which isn't too bad but it means you now have to worry about yet another thing.
Then there's the ESM & CJS mess. You almost always want to export in both formats which will change a lot of the syntax, so this quickly falls apart for anything serious.
Just use esbuild if you want speed.
Hello everyone!
After around 2 years, we are back on HN with a massive update for Notesnook. But before that, here's a short introduction:
Notesnook is an end-to-end encrypted, 100% open source [0] note taking app that prioritizes user privacy.
v3 brings a lot of really radical changes, such as:
- Migration to SQLite
- At rest encryption
- Note linking
- Nested notebooks
- App lock on all platforms
You can read more about all these here: https://blog.notesnook.com/introducing-notesnook-v3/
Our goal with Notesnook has always been to make privacy simpler to adopt for normal users who don't have time to think about privacy. We do that by making privacy that "default" everywhere in the app. We recently crossed 100K registered users with over 4 million notes created on our platform.
If anyone has any questions I'd be happy to answer.
Not slow changes. Offering self hosted officially means that we have to be aware of users who are self hosting before we make any drastic changes, writing migrating guides, and giving some sort of support. All that has an impact on productivity.
There's no point in offering users self hosting if you are going to throw them into a fire by doing so. Notesnook is rapidly evolving and changing, and hoping for self hosted users to keep up is impractical. Instead, we want to first stabilize the backend, and then think about self hosting.
After v3, our primary focus will be on self hosting and getting an audit done.
It seems to me you are looking for a syntax highlighter in a note taking app. Which modern language are you looking for?
There are encrypted backups. Actually, backups are encrypted by default.
Notesnook also works offline by default so there's no need for a special mode. It's also, obviously, local-first since everything gets encrypted on your device. We don't have a lot of options there.
What "might be better" in the editor?
What did you find painful?
v3 will be even smoother. We are migrating to SQLite so startup times will be instant. Performance is a feature.
Markdown itself is more technical than, say, a WYSIWYG editor. People are more used to using MS Word and Google Docs. Obsidian prioritizes a different kind of note taking and, hence, you'll find a lot of tech-savvy users among its community. There's a reason for that.
Evernote is not E2EE.
Obsidian is a cool app but it's targeted for a very specific kind of user. Of course, for a technical user Obsidian would feel like home but for an average user with not a lot of technical know how, Obsidian would go way over their heads. Not everyone appreciates having to handle files, worry about syncing, security etc.
We are very close to fully supporting self hosted Notesnook. After v3 that'll be our primary focus. That and an audit.
Oh wow. Just heard the Notesnook is on the front page of HN. I am the co-founder so if you have any questions, feel free to ask.
Oh and to clear a few confusions:
1. Notesnook is 100% open source. That includes the server, client apps, and everything else. It's not partially open source.
2. Zero knowledge does not mean Zero Knowledge Proof but Zero Knowledge as in we, the company and people behind Notesnook, have no knowledge regarding what you have in your notes. I see that this might be more accurately called "no knowledge".
Ah war stories.
Just a few weeks back a user came to us after failing to migrate GBs of their data off of Evernote. This, of course, included attachments. They had successfully imported & synced 80K items, but when they tried to login on their iPhone, the sync was really, really slow. They had to wait 5 hours just to get the count up to 20K items. And that's when the app crashed resetting the whole sync progress to 0.
In short, we had not considered someone syncing 80K items. To be clear, 80K is not a lot of items even for a local-first sync system, but you do have to optimize for it. The solution consisted of extensively utilizing batching & parallelization on both the backend & the users' device.
The result? Now their 80K items sync within 2 minutes.
I don't think even you understand what you just said.
Consumer devices are notorious for their reliability problems. Compared to a full blown server that you have 100% control over with almost insane amounts of RAM & CPU power & a lot of guarantees.
Running a migrations on a server is far, far different to running it on every users' device. The sheer scale of it is different.
Using 4 GB per user on your backend works?
That was a comment on the average RAM on a consumer device - not the total RAM required per user.
I think you misunderstand. My intention was not to say local-first is bad or impossible; it's not. We have been local-first at Notesnook since the beginning and it has been going alright so far.
But anyone looking to go local-first or build a local-first solution should have a clear idea of what problems can arise. As I said in the original comment: it's not all gardens and roses.
As someone who has been doing local-first for the last 3 years with Notesnook, let me tell you: it's not all gardens and roses. Local first has its own very unique set of problems:
1. What to do with stale user data? What happens if a user doesn't open the app for a year? How do you handle migrations?
2. What about data corruption? What happens if the user has a network interruption during a sync? How do you handle partial states?
3. What happens when you have merge conflicts during a sync? CRDT structures are not even close to enough for this.
4. What happens when the user has millions of items? How do you handle sync and storage for that? How do you handle backups? How do you handle exports?
One would imagine that having all your data locally would make things fast and easy, but oh boy! Not everyone has a high end machine. Mobiles are really bad with memory. iOS and Android have insane level of restrictions on how much memory an app can consume, and for good reason because most consumer mobile phones have 4-6 gbs of RAM.
All these problems do not exist in a non-local-first situation (but other problems do). Things are actually simpler in a server-first environment because all the heavy lifting is done by you instead of the user.
I don't think that's true. We have been using ASP .NET Core + SignalR for everything in Notesnook[0]. It has great performance, libraries for everything out there, very good ergonomics, and a mature ecosystem.
I know you can probably get more performance out of Rust or Go but I don't think rq/s benchmarks really hold up in reality. If you are running a startup, you'd probably see 1 to 2 rq/s unless you become viral. .NET Core can easily handle that and more.
The author is going into technicalities without much actual substance, ending with: it depends.
I think whenever we, as programmers, try to pin down a certain principle, it bites us. Hard. DRY was cool as an observation but when it got turned into a law we saw the spaghetti code.
Duplication, on the other hand, is detested almost as much as the goto statement. Let me tell you, it's not that bad. Duplicate code makes everything more flexible. It helps you to NOT bend over backwards in order to change a line of code. It allows you to NOT touch anyone else's code.
So many good things. Of course, I agree with the author's summary of the bad things that can happen with duplicated code. But there's a litmus test for that:
If you have to make changes in multiple blocks of duplicated code in order to change the behavior of something, there's a problem. DRY out the code so you only have to touch 1 place.
If, however, 2 blocks of code LOOK similar but aren't actually the same, and changing one block doesn't make the other block outdated and stale, you are good to go.
Judge and decide. It's just 2 approaches that when taken to an extreme can cause a lot of pain, but if used with common sense, nothing is simpler.
Anyone who says X must be done in Y way is most absolutely wrong. Who is Tiago Forte to tell how I should organize my thoughts? Am I a robot to follow so simply in the footsteps of another? I would like a more general approach, please.
Any serious note taker eventually realizes that the way their brain works doesn't really fit into any PARA, ARPA or any other standarized system.
Note taking is a messy business. It's not supposed to be organized because you take notes to become more organized, not to organize more notes.
Just take your notes.
Organization will automatically happen. Humans are very bad at doing things randomly. There's always an order, a sequence, a method to the way we do things. Who's to say your method is better than mine?
I think all note apps are just databases. Some day an LLM might be able to make sense of the messy notes in my note taking app but I am not holding my breath. My notes are not supposed to stand the test of time. They are ephemeral thoughts relevant only for a specific period - a best-worst case against the risk of forgetting them.
The most an AI should do is find relevant notes on a topic I search. That's it. I don't need its robotic voice summarizing my grotesque ideas in a painless, unpassionate way. The last thing I need is more of my ideas seeping into more of my computers in hopes of somehow making me smarter.
These guys also tried to submit PRs on the Notesnook[0] repository. The PRs are really good but there's no way to talk to the actual developer working behind those PRs. They have a single central account named "gitstart" and all PRs that any of their user works on falls under that account. Of course, we couldn't accept PRs from them because they don't follow DCO[1] i.e., DCO requires that the committer MUST NOT be an organization.
I talked to them about this and they said they'd work on it etc. etc. Not sure if anything has changed in that regard or not.
I would NOT call this frugal at all, actually. You are overspending in a lot of places and under spending in others. $281.32 per month for such a simple service is...astonishing. Change Vercel and Intercom with Cloudflare and Chatwoot (self hosted), and you have saved $120/mo. Get rid of Ahrefs for Ubersuggest (or no SEO tool at all) to save about $80 more. That leaves you with $81.32/mo. If you try even harder, you can easily bring that under $50.
But I get it. If X tool saves time, why not pay for it? I wouldn't call that frugal though because you are still spending where you can save.
No. I found Remirror quite a while after Tiptap while searching for a more stable React Node View implementation.
The good news, though, is that it's really simple to mix and match Tiptap and Remirror since both of them use Prosemirror internally.
We have been using Tiptap in production for more than a year in Notesnook[0]. Glad to see it finally launching here on HN!
We have had quite a long and rough ride in search of a stable rich text editor. We began with Quill.js then migrated to TinyMCE and then finally settled on Prosemirror. Unfortunately, contenteditable is still absolutely horrible on web browsers, especially mobile ones.
Tiptap is a good choice if you are looking for a framework agnostic and thin abstraction over Prosemirror. However, if you are primarily working with React you should go with Remirror[1]. Tiptap's APIs are heavily inspired by Remirror (almost a duplicate in some places). Remirror takes the edge on the maturity and stability of the API and extensions. The sheer number of utilities offered by them to simplify Prosemirror's APIs is astounding. And trust me, you will need a lot of those utilities eventually. Prosemirror is not an easy API - really, really well designed but not easy.
In the end, though, its Prosemirror that's doing all the heavy lifting. And no matter how many abstractions you put on it, you will have to get really, really close in with Prosemirror's internals. Tiptap or Remirror do not make that any easier or harder aside from the initial bootstrapping.
---
Edit: almost forgot this but the only real selling point of Tiptap is their extensive documentation.
I tried it on my end. Built bfs from source using `make release`:
$ hyperfine -w1 "NODE_ENV=production node ./fdir.mjs" "./bin/bfs /
home/thecodrr/ -false"
Benchmark 1: NODE_ENV=production node ./fdir.mjs
Time (mean ± σ): 965.5 ms ± 53.0 ms [User: 703.0 ms, System: 1220.5 ms]
Range (min … max): 858.4 ms … 1041.3 ms 10 runs
Benchmark 2: ./bin/bfs /home/thecodrr/ -false
Time (mean ± σ): 1.530 s ± 0.127 s [User: 0.341 s, System: 2.282 s]
Range (min … max): 1.401 s … 1.808 s 10 runs
Summary
'NODE_ENV=production node ./fdir.mjs' ran
1.58 ± 0.16 times faster than './bin/bfs /home/thecodrr/ -false'
$ cat fdir.mjs
#!/usr/bin/env node
import { fdir } from "fdir";
console.log(await new fdir().onlyCounts().crawl("/home/thecodrr").withPromise());
For some reason, reducing the UV_THREADPOOL_SIZE to 2 gives the best result on my machine (I have heard the opposite in case of macOS): $ hyperfine -w1 "UV_THREADPOOL_SIZE=2 NODE_ENV=production node ./fdir.mjs" "NODE_ENV=production node ./fdir.mjs" "./bin/bfs /home/thecodrr/ -false"
Benchmark 1: UV_THREADPOOL_SIZE=2 NODE_ENV=production node ./fdir.mjs
Time (mean ± σ): 355.8 ms ± 16.1 ms [User: 479.4 ms, System: 356.0 ms]
Range (min … max): 328.3 ms … 387.5 ms 10 runs
Benchmark 2: NODE_ENV=production node ./fdir.mjs
Time (mean ± σ): 935.4 ms ± 52.7 ms [User: 695.8 ms, System: 1176.5 ms]
Range (min … max): 850.6 ms … 1031.9 ms 10 runs
Benchmark 3: ./bin/bfs /home/thecodrr/ -false
Time (mean ± σ): 1.534 s ± 0.104 s [User: 0.353 s, System: 2.307 s]
Range (min … max): 1.428 s … 1.773 s 10 runs
Summary
'UV_THREADPOOL_SIZE=2 NODE_ENV=production node ./fdir.mjs' ran
2.63 ± 0.19 times faster than 'NODE_ENV=production node ./fdir.mjs'
4.31 ± 0.35 times faster than './bin/bfs /home/thecodrr/ -false'
Another factor to take into account is that I ran all this on a WSL instance which may or may not affect the performance. However, since both programs are running on WSL, the results should be accurate.You are using fdir synchronously. Try this:
console.log(await new fdir().onlyCounts().crawl("/home/tavianator/code/android").withPromise());
Would love to see how bfs compares to fdir[0] for directory traversal. Even though fdir is using Node.js underneath, the comparisons I have done with fd & find are pretty close. Of course, bfs would probably be quite a bit faster...but how much faster exactly?
Disclaimer: I am the developer of fdir.