HNHacker News
TopNewBestAskShowJobs

jlokier

6,144 karma · joined October 23, 2018

Mail: jamie@jlokier.co.uk LinkedIn: https://linkedin.com/in/jlokier

Knowledgable & helpful person, available for hire :-)

I'm looking for more work, ideally on a consulting / freelance / part-time basis.

LinkedIn is better than email to make first contact if you'd like to talk, whether for work or just chat about something you liked here on HN! (I often miss interesting one-off mails among the deluge, and don't check it every day.)

I work 80% time at a funded stealth startup as hands-on tech lead, with zero-knowledge (ZK) cryptography, Bluetooth low energy (BLE), and peer-to-peer distributed systems, linking physical devices as well as the usual web stack. Can't say more, but it is intended to become open source. This a really fun and challenging project, with a great team! (It's not on my LinkedIn - stealth).

With my remaining 20% I am currently available and looking for software dev and/or tech leadership and/or business strategy consulting.

I'm versatile but develop mostly low-level or "system" software in C, C++, Go, Rust and Nim, with Linux as my main OS (but MacOS and Windows also). I have about 30 years professional dev experience over a wide range of systems, from embedded to supercomputers, Linux kernel, database engines, as well as GUIs, the web, and even games. Good at performance optimisation, debugging. Also good math & physics.

I've worked as an Ethereum core dev (EVM), so I know that environment well, especially improving EVM database speed, which is a critical factor! Currently my rabbit holes are ZK cryptography speed optimisation, and a novel fast database engine (neither B-tree nor LSM-tree, but with characteristics of both).

(ZK = zero-knowlege cryptography).

submissionscomments
jlokier··on The Beginner's Textbook for Fully Homomorphic Encryption
> In turn, every computable function on the real numbers is a continuous function

That doesn't seem right. Consider the function f(x: ℝ) = 1 if x ≥ 0, 0 otherwise. That's computable but not continuous.

jlokier··on Be careful with Go struct embedding
> you always need to access them via the embedded type's name, so there's nothing to conflict.

The article talks about "opts.URL" in its example being accepted by the compiler, which accesses "opts.FooService.URL" without using the embedded type's name.

jlokier··on Xcode Is the Worst Piece of Professional Software I Have Ever Used
Yup.

Once it took Vivado 40 minutes just to add one small Verilog file to a project. Not to compile it. Just to add it to the list of project source files, for which it scanned the file for definitions. Each time I edited the file, Vivado stalled for another 40 minutes. Same file compiled and ran all its simulation tests in Verilator (an open source tool) in a couple of seconds.

For my compiles, Vivado routinely took hours for sparse designs and over 24 hours for dense (but still conceptually small) ones. This made iteration impossible on the timescales my last FPGA project required, so I had to stop using Xilinx.

I accept that dense P&R compiles may take a long time, as it's algorithmically complex. But Vivado's occasional extremely slow and janky process for minor things left my wondering if the full P&R compile time was more due to similar bad coding issues on their side, not any real need to take that long.

jlokier··on OpenAI and Nvidia announce partnership to deploy 10GW of Nvidia systems
onlyrealcuzzo wrote:

> Google is pretty useful. It uses 15 TWh per year.

15TWh per year is about 1.7GW.

Assuming the above figures, that means OpenAI and Nvidia new plan will consume about 5.8 Googles worth of power, by itself.

At that scale, there's a huge opportunity for ultra-low-power AI compute chips (compared with current GPUs), and right now there are several very promising technology pathways to it.

jlokier··on Lidar, optical distance and time of flight sensors
From a physics point of view, continuous transmission and correlation detection of a temporally- and spatially-diverse optical signal over the entire field of view addresses the problem of energy being spread out, and gets you better, more robust depth information for less emitted energy than scanning or full-field flashes.

But from an optical and electronics point of view, it's much harder to process the return signal that way, and probably uses a lot more energy due to the processing required (with current tech).

jlokier··on Why, as a responsible adult, SimCity 2000 hits differently
To my mind, "think of the children" is something I've only ever seen as a motivating force of anti-liberal politics.

With liberals saying the "think of the children" argument is a specious, misdirecting, crude appeal to emotion that should be looked past.

jlokier··on Vibe coding cleanup as a service
There's still a market, but when I looked into COBOL work out of curiosity (I've never been anywhere near it in real life), the salaries I found were surprisingly low, compared with common modern languages.

Perhaps the old adage "it's getting hard to find X employees [at the price we are willing to pay]" applies.

That surprised me because I've seen articles and heard podcasts for years where they've said COBOL programmers are well paid due to scarcity, though never quoting amounts.

jlokier··on Mirror Life Worries
> All sugars have chirality so they would need some enzymes to eat their own mirrored sugars and another set of enzymes to eat normal sugars.

Until mirrored life evolves enzymes to eat non-mirrored sugars, mirrored life will be at a large disadvantage.

But with exposure to our environment, replete with non-mirrored sugars, that sets up a large evolutionary pressure in the direction of finding those enzymes, in addition to the mirrored enzymes they will already have for eating mirrored sugars.

With such evolutionary pressure, it seems plausible mirrored life will evolve those enzymes, even though non-mirrored life appears not to have done so, or at least not retained it. Because there has been no equivalent evolutionary pressure for non-mirrored life to eat mirrored sugars.

If mirrored life does evolve those enzymes, due to that asymmetric evolutionary pressure, then instead of being at a disadvantage, it might give them a temporary advantage over non-mirrored life.

jlokier··on Mirror Life Worries
> All sugars have chirality so they would need some enzymes to eat their own mirrored sugars and another set of enzymes to eat normal sugars.

Until mirrored life evolves enzymes to eat non-mirrored sugars, mirrored life will be at a large disadvantage.

But with exposure to our environment, replete with non-mirrored sugars, that sets up strong evolutionary pressure in the direction of finding those enzymes, in addition to the mirrored enzymes they will already have for eating mirrored sugars.

With such evolutionary pressure, it seems plausible mirrored life will evolve those enzymes, even though non-mirrored life appears not to have done so, or at least not retained it. Because there is no equivalent evolutionary pressure for non-mirrored life to eat mirrored sugars.

If mirrored life does evolve those enzymes, due to that asymmetric evolutionary pressure, then instead of being at a disadvantage, the ability to eat both types of sugars might give them a temporary advantage.

jlokier··on Show HN: The text disappears when you screenshot it
> You could make sensitive data non-screenshottable and non-photographable.

That made me curious, so I took a photo of my laptop screen running this page.

With default camera settingse, the text wasn't visible to me in the photo on my phone screen.

However, setting the exposure time manually to 0.5s, the text came out white on a noisy background and I could easily read it on the phone screen.

I would not be surprised if the default camera settings photo could be processed ("enhance!") to make the text visible, but I didn't try.

jlokier··on iPhone dumbphone
You can actually use an alternative authenticator app for Microsoft logins. I use Aegis on my phone for it.

They don't make it clear in the messaging during the sign-up flow, which just says Microsoft Authenticator everywhere. But when you proceed through the steps to get a TOTP code for Microsoft Authenticator, there's a step with a link to something like "I want to use an another authenticor app", which presents a QR code for any generic TOTP app.

jlokier··on Writing a C compiler in 500 lines of Python (2023)
That's why I described a not very well known trick that requires just +1 line, the definition of hash(). It's neither fast nor maintainable, it's just a neat hack that gives you some of the performance of hash tables for negligible source code overhead. Perfect for tiny, self-contained programs like this one.
jlokier··on io_uring is faster than mmap
This branch of the discussion is is about dereferencing on multiple threads concurrently. That doesn't block the application, each mmap'd dereference only blocks its own thread (same as doing read()).

In my own measurements with NVMe RAID, doing this works very well on Linux for storage I/O.

I was getting similar performance to io_uring with O_DIRECT, and faster performance when the data is likely to be in the page cache on multiple runs, because the multi-threaded mmap method shares the kernel page cache without copying data.

To measure this, replace the read() calls in the libuv thread pool function with single-byte dereferences, mmap a file, and call a lot of libuv async reads. That will make libuv do the dereferences in its thread pool and return to the main application thread having fetched the relevant pages. Make sure libuv is configured to use enough threads, as it doesn't use enough by default.

jlokier··on Type-safe and user-friendly error handling in Swift 6
That's actually the same as Java, with its "checked exceptions" (aka listed in function signatures), and the RunTimeException hierachy which don't have to be listed.

In Java common errors and exceptions, like file I/O errors, have to be declared on each function signature, except everything under the RunTimeException hierachy is exempt from this requirment. In the language, RunTimeExceptions these are the messy errors like NullPointerException and ArithmeticException.

In practice, people do subclass program-specific exceptions under RunTimeException in Java, as well as wrapping existing exceptions inside a RunTimeException, for the sole purpose of not having to add them to function signatures all over the place.

jlokier··on A Random Walk in 10 Dimensions (2021)
It's not 0.8^10 anyway, because there aren't 10 neighbours.

There are neighbours in both directions in each dimension, i.e. 20 neighbours in 10 dimensions if you're allowed to wrap around the edges of the lattice.

With wrapping, I think the probability is 0.2 × (0.8^20) ≈ 0.002306 ≈ 0.23%.

If you're not allowed to wrap at the edges, a unformly random point has 2/N probability of having one neighbour on each dimension independently, and (N-2)/N probability of having two. With D dimensions, that's on average D(2N-2)/N neighbours.

With D = 10, N = 5, I think it's 16 neighbours on average, with a distribution from 10 to 20.

That makes the probability of landing on a mountain peak lower than ~2% and higher than ~0.23%. (Not 0.2 × (0.8^16) though, due to the distribution.)

jlokier··on Google was down in eastern EU and Turkey
I remember going to an outside toilet in the UK...
jlokier··on Writing a C compiler in 500 lines of Python (2023)
If you can search (and do other operations) on a linked list, and the lists are long enough to matter, you can trivially speed it up to a fixed-size hash table with hardly any code changes.

This:

    entry = list_search(key, list);
becomes:

    entry = list_search(key, lists[hash(key) % (sizeof(lists)/sizeof(lists[0]))]);
This:

    list_add(key, entry, list);
becomes:

    list_add(key, entry, lists[hash(key) % (sizeof(lists)/sizeof(lists[0]))]);
etc.

A simple hash(), not high quality but good enough for non-adversarial inputs, can be a one-liner.

A good dictionary does more than this of course, especially dynamic sizing, but this simple change can radically speed up simple linked list code when the lists are long, you don't have a hash table implemention you can use, and you want to keep the code change very small.

The same principle can be used with other things than lists too.

jlokier··on We already live in social credit, we just don't call it that
In my experience, in the UK, the rental agency required 12 months rent in advance (plus another 2 months rent as deposit) when I was self-employed. They would have accepted monthly rent if I had 5x the annual rent in cash savings, but I didn't.

And then every year after that they required another 12 months rent up front, when it came to the annual tenancy renewal. Track record of paying the rent wasn't good enough to prove that I could keep paying the rent.

jlokier··on The future of 32-bit support in the kernel
You're right about the VMM.

But three out of those four features: page cache, dynamic I/O buffering and shared memory between processes, do not require that kind of VMM subsystem, and memory-mapped files don't require it for some kinds of files.

I've worked on the Linux kernel and at one time understood it's mm intimately (I'm mentioned in kernel/futex/core.c).

I've also worked on uClinux (no-MMU) systems, where the Linux mm behaves differently to produce similar behaviours.

I found most userspace C code and well-known CLI software on Linux and nearly all drivers, networking features, storage, high-performance I/O, graphics, futex, etc run just as well on uClinux without source changes, as long as there's enough memory, with some more required because uClinux suffers from a lot more memory fragmentation due to needing physically-contiguous allocations).

This makes no-MMU Linux a lot more useful and versatile than alternative OSes like Zephyr for similar devices, but the limitations and unpredictable memory fragmentation issues make it a lot less useful than Linux with an MMU, even if you have exactly the same RAM and no security or bug concerns.

I'd always recommend an MMU now, even if it's technically possible for most code to run without one.

jlokier··on The future of 32-bit support in the kernel
Those features don't require an MMU.

The no-MMU version of Linux has all of those features except that memory-mapped files (mmap) are limited. These features are the same as in MMU Linux: page cache, dynamic I/O buffering, shared memory. No-MMU Linux also supports other modern memory-related features, like tmpfs, futexes. I think it even supoprts io_uring.

mmap is supported in no MMU Linux with limitations documented here: https://docs.kernel.org/admin-guide/mm/nommu-mmap.html For example, files in ROM can be mapped read-only.

jlokier··on The future of 32-bit support in the kernel
There are many options. Executables can be position-independent, or relocated at run-time, or the device can have an MPU or equivalent registers (for example 8086/80286 segment registers), which is related to an MMU but much simpler.

Executables in a no-MMU environment can also share the same code/read-only segments between many processees, the same way shared libraries can, to save memory and, if run-time relocation is used, to reduce that.

The original design of UNIX ran on machines without an MMU, and they had fork(). Andrew Tanenbaum's classic book which comes with Minix for teaching OS design explains how to fork() without an MMU, as Minix runs on machines without one.

For spawning processes, vfork()+execve() and posix_spawn() are much faster than fork()+execve() from a large process in no-MMU environments though, and almost everything runs fine with vfork() instead of fork(), or threads. So no-MMU Linux provides only vfork(), clone() and pthread_create(), not fork().

jlokier··on QEMU 10.1.0
The AMD Processor Programming Reference manuals are also good for this, if you like complete and detailed. They complement the Intel manuals. Much the material is duplicate because the processors are so similar, but written in a different way.
jlokier··on Google will allow only apps from verified developers to be installed on Android
Having read [1] in particular, I think you're right and I was mistaken. Thanks! That's quite eye-opening for me, as I followed discussion about GPLv2 and GPLv3 for years yet didn't know about this view of GPLv2 and reinstallation.

Having heard so much about anti-Tivoization when the GPLv3 was being drafted, and the discussions about it on linux-kernel when Linus decided the kernel will remain GPLv2-only, I was left with the impression that the GPLv2 only required the provision of source code, build scripts, etc. but not the ability to reinstall a new version. [1] makes a pretty good case that the ability to reinstall is also required GPLv2, and I'm heartened that's how Tivo saw it too.

[1] https://sfconservancy.org/blog/2021/jul/23/tivoization-and-t...

jlokier··on Google will allow only apps from verified developers to be installed on Android
For example, Starling Bank in the UK.

They have a nice web app, but you must use their mobile app to login on the web version. The app takes a video of a QR code on the web page during login. Web login completes as soon as the mobile app notifies the server. There's no 2FA code to enter, and no alternative.

I asked them about this, by phone call, when my phone screen broke and I urgently needed to make a transaction. Surely there as an alternative? Or could I do the transaction by phone call?

They told me that indeed there is no other option. Despite having phone customer support, they had no phone or web banking service at all which could be used without a registered mobile device. The only phone service they could perform was to register a new mobile device, which I didn't have. I had a tablet, but it was too old.

So I had no good choice. The Android phone I'm using right now was bought in a hurry just so I could be allowed to make a bank transaction.

It wasn't my first choice of phone. I didn't have time to investigate alternative devices, let alone weigh up open alternatives. I ended up buying a mid-range device under pressure that seemed ok and was available in a store without waiting. (It was a brand new Samsung, and despite the IP rating it got water damaged and stopped working entirely after a few splashes a year or so later, but I was able to get it repaired.)

jlokier··on Google will allow only apps from verified developers to be installed on Android
Locked bootloaders are probably not a GPLv2 violation, and probably are a GPLv3 violation. This type of situation was a major reason GPLv3 was created. Another was clarification of some grey areas (these are the reason for "probably").

But the Linux kernel is GPLv2, and only v2. For better or worse, locking down the bootloader is (probably) pernitted with the Linux kernel.

jlokier··on 4chan will refuse to pay daily online safety fines, lawyer tells BBC
Since we're talking about the UK, in 2010 negotations after a hung parliament produced an opportunity to move towards something a little more representative: The 2011 referendum on changing to AV voting from first-past-the-post.

Unfortunately, voters rejected that change quite strongly, and that probably set the trend for a while against further steps to proportional or more direct democratic systems.

AV is a type of transferable vote system, and a step closer to proportional representation. In AV you get two votes, so you can vote for your preferred candidate first (who may be niche but represents you better), and your tactical-vote candidate second (who doesn't represent you but are better than the even-worse candidate). As opposed to the current FPTP system, where you often have to tactical-vote for candidates who don't represent your interests much, and your actual preference is not recorded at all.

Even though AV is far from ideal, if voters had said yes then I think just the symbolism of changing the system, would have resulted in a greater inclination to change the system again later.

AV, STV and PR have been debated a number of times in the UK parliament in the last centery, so it does keep coming up, and will likely come up again, eventually.

jlokier··on SK hynix dethrones Samsung as world’s top DRAM maker
I've had that happen twice!

Recently I asked for my software developer colleage to be bought a 24 GB Macbook Air instead of 16 GB, and boss came back with "not everyone needs a super-big machine like yours Jamie!".

They seriously spent contractor time investigating whether 16 GB was "enough" to get by for our app development, for a price difference on one laptop (second hand) that was negligible compared with cost of my colleage's time.

When I was using 16 GB I regularly had to watch the spinning beachball waiting for tasks due to memory pressure. Between browsers and VMs, it was nowhere near enough for how I worked. So I knew why I was asking, and I knew the price difference was so small for the company, that it was a no-brainer. I gave justifications but it was seen as over-indulgent.

jlokier··on Without the futex, it's futile
> Is it possible to allocate wait queue nodes on the kernel stacks of waiting threads as well?

Yes, this is exactly what's done. The queue node is an declared as a local variable in kernel code, i.e. on the kernel stack, and its address is passed to the wait function which links it into the waitqueue and then blocks in the scheduler.

jlokier··on Staff disquiet as Alan Turing Institute faces identity crisis
DeepMind was founded in London, UK and still headquartered there, and is one of the leaders in the field..

Notable well-known things from DeepMind are AlphaGo (the first time a computer beat a world champion at Go), AlphaFold (resulting in a Nobel prize). Gemini (LLM, a variant of which is used in Google search results) and Gemma (open-weights LLMs).

They were acquired by Google, so you could argue they aren't centred in the UK any more, but I still think they qualify as international leadership in AI coming from the UK.

jlokier··on Without the futex, it's futile
Perhaps they meant to write WaitOnAddress, which is the same as a basic futex.
← PreviousPage 5 of 34Next →