This post is full of Claude's irritating verbal ticks ("It's not X, it's Y"). It is fine to use Claude (or another LLM) to help with this kind of reverse engineering, but I would prefer the write-up be done by hand.
HN user
robertknight
[ my public key: https://keybase.io/robertknight; my proof: https://keybase.io/robertknight/sigs/8sIWi2mXXCYCcJpcSJ7dMDcXNg-GpHRFv4JGtNAbQIg ]
This would have been more effective if written by hand. The issue content is typical LLM-generated markdown that has a lot of noise (formatting, headings, lists etc.) which makes it fatiguing to read. It comes across like a PowerPoint deck of dense slides. What is really needed is a clear, focused and well-written letter that effectively gets across a message and has the potential to be persuasive to the people within Microsoft who might be in a position to help. An additional problem with the LLM-written style is that it comes across as low-effort, which also lessens its impact.
The major constraint is that the compiler needs to guarantee that transformations produce semantically identical results to the unoptimized code, with the exception of undefined behavior or specific opt-outs (eg. `-ffast-math` rules).
An ML model can fit into existing compiler pipelines anywhere that heuristics are used though, as an alternative to PGO.
The custom scroll behavior on this page is infuriating and distracts from the content. It is like scrolling in treacle. If someone who works at Microsoft sees this and is able to file an issue, could you please do so.
I've seen talks on this topic at Rust conferences which seemed strongly influenced by Swift's approach, so that will probably be the direction this ends up going in.
I use fish + atuin. I leave the "Up" arrow set to use fish's default history search (see https://docs.atuin.sh/faq/#how-do-i-remove-the-default-up-ar...), which keeps the UI minimal when just going back one or two commands, then use atuin via Ctrl+R when I need to find a command from earlier in my history. At that point Atuin provides a nicer UI for searching the history.
Good post! The inefficient code for comparing pairs of 16-bit integers was an interesting find.
Does Hypothes.is have a self-hosting option? https://web.hypothes.is/sales/
The code for both the client and server are open source (https://github.com/hypothesis/h) so this is possible. The server is designed to support the needs of large scale deployments, so this does come with some complexity compared to a system you would design for smaller scale usage.
The text on https://web.hypothes.is/ mostly targets schools and universities, because Hypothesis pays for itself by selling integrations with online learning platforms (Canvas, D2L, Blackboard etc.) and associated support.
One interesting thing I discovered comparing various matrix multiplication implementations used in ML libraries is that several of them (ONNX Runtime, XNNPack, any others?) skip the step, from BLIS's textbook algorithm, of packing the LHS matrix. Instead they pack only the RHS. Since those are the weights, this can be done once ahead of time and then an inference pass does not need to do any packing at all.
From skimming various papers it seems like the motivation for packing the LHS originally, even though a single element is broadcast from it at a time (nb. this is opposite to the order in this post, where the row count in the microkernel is a multiple of the register size, rather than the column count), was to reduce TLB misses. Apparently this is not a problem in practice on modern CPUs and for problem sizes common in ML inference.
For context, ultralytics is the Python package for YOLO v8 and YOLO v11, two of the most widely used object detection models. The GitHub repo has 33K stars.
A couple of suggestions:
1. Try not to stress too much. The point of review is to improve the quality of the code that lands, and the health of the codebase as a whole, not to grade the author.
2. When you think your work is ready for an initial review, take a short break and then review it line by line yourself, looking for any obvious mistakes or possible simplifications. I recommend doing this in a different editor or view than the one you authored the code in originally.
When reviewing someone else's code, it is annoying if there are silly mistakes that the author could obviously have caught themselves. Issues where the author was not aware of a subtle detail or a coding practice in some other part of the code are less of an issue. Identifying these are exactly what reviews are for.
This effectively means that if I were to bundle ffmpeg and ffprobe executables within my app, I would have to make the app open-source as well and provide it under the same license.
This is a misunderstanding of the LGPL license requirements, as they are usually interpreted. LGPL requires that if your application dynamically links to a modified version of the library, then you must make the source code _for the modified version of the library_ open source.
The original use case for the LGPL license was the C runtime, which practically every binary on a system will link to, proprietary or otherwise. The idea is that the binary can be closed source, but any modifications made to the C runtime itself must be distributed. The idea is that an end user could take your modified version of the C library and further customize it to their needs.
In the context of bundled ffmpeg and ffprobe executables, the user could replace them with their own versions. You should make clear which version of the source was used to build them and if you have made any modifications, those must be open source.
All Maven/PIP/NodeJS/etc. dependencies are pulled through via proxy and scanned before first use.
What does the scanning process check for / which tools are used?
This is not unique to X. Windows for example uses the same kind of "HWND" object for buttons as for top-level windows. Windows doesn't have the same client/server overhead as X though.
In Qt, there is an option to use either native windows for individual widgets or "alien" windows, in which only the top level widget is a native window - https://doc.qt.io/qt-6/qwidget.html#native-widgets-vs-alien-....
Tools like https://web.hypothes.is exist and have a decent number of installs.
The hard part of a generic third-party commenting tool is creating the right social context for it to actually be useful. Hypothesis for example is mostly used via its integration into online learning platforms, where that context already exists.
You could try something like https://aws.amazon.com/textract/ or https://cloud.google.com/vision/docs/handwriting. Both have support for modern handwriting. I don't know if it will work with a script written a century ago though.
Related to this, I recommend Felienne Hermans' talks on Excel as a functional programming language - https://www.youtube.com/watch?v=0yKf8TrLUOw.
Other than EasyOCR and Tesseract, PaddleOCR (https://github.com/PaddlePaddle/PaddleOCR) is probably the most well known open-source OCR solution.
What are you planning to do with the text after detecting / recognizing it? How fast does the detection / recognition need to be in order to be useful?
In general, no. React has been around for over 10 years now, and it generally remains popular and well supported. It is not going anywhere. Some sites will choose to migrate between React and Web-components based frameworks such as Lit for various reasons (technical preferences, standardizing technology stacks within an organization etc). Some sites will combine chunks of UI built with React and chunks of UI built with Web components (eg. by different teams within an organization). Others will create web applications which use Web components for style/DOM isolation at the top level, but where web components are built internally with React (which has various tooling and API advantages over WCs at the lower level).
EasyOCR is a popular project if you are in an environment where you can use run Python and PyTorch (https://github.com/JaidedAI/EasyOCR). Other open source projects of note are PaddleOCR (https://github.com/PaddlePaddle/PaddleOCR) and docTR (https://github.com/mindee/doctr).
How is Netflix so blind to this? They think they will gain those recipients of shared accounts, but in reality they're losing the ones who are actually paying for it.
I would guess they see it as a numbers game. Enforcing sharing restrictions more aggressively will cost them some customers who rely on it, and gain them some (maybe only a minority) who currently freeload. What will the overall result be? I don't know. I would have expected them to model various scenarios though and decide there was enough potential to make it worth trying.
It hasn't been officially deprecated or anything like that, and it still works fine for the most part [1]. However it hasn't received a lot of active development in the last couple of years.
I do think the whole concept behind Gulp, of creating processing streams through which files are fed to transform them, before writing to disk, is less useful than it used to be. This is because a lot of that functionality can now be handled by bundlers which understand the inter-dependencies between modules rather than just taking the input as a set of files. Also Node/JS's own async functionality is much more ergonomic to use than it needs to be, so additional async abstractions on top are less useful than they were.
[1] I'm aware of some issues related to file watching. See https://github.com/gulpjs/gulp/issues/2654
Google does it with millions of search results
Google cheats, but in a way that very few users will notice. You can only access the first 20 pages of search results. Depending on user behavior, this is one way to offer navigation via page number while limiting worst-case cost.
Thanks for this test case. When I drop that image I see that the individual words are recognized correctly, but starting from about mid-way though are not displayed in the correct order in the text box at the bottom. If the image is rotated so that the text baselines are horizontal (about a ~1.5 degree rotation), the words are displayed in the correct order. So it looks like smarter methods or defaults are needed for the layout analysis.
I think with modern methods it ought to be relatively easy to teach a system to predict the amount of rotation needed to straighten the image, or make the layout analysis tolerate minor rotations of the input better. Needs someone to actually implement it though!
If you want to OCR a document image, modern versions of Tesseract can work well. If you last used it a few years ago, the recognition has improved since due to a new text recognition algorithm that uses modern (deep learning) techniques. Browser demo using a modern version: https://robertknight.github.io/tesseract-wasm/.
OCR processing typically consist of two major steps: detecting/locating words or lines of text on the page, and recognizing lines of text.
Tesseract's text recognition uses modern methods, but the text detection phase is still based on classical methods involving a lot of heuristics, and you may need to experiment with various configuration variables to get the best results. As a result it can fail to detect text if you present it with something other than a reasonably clean document image.
Doctr (https://github.com/mindee/doctr) is a new package that uses modern methods for both text detection and recognition. It is pretty new however and I expect will take more time and effort to mature.
This was a fun distraction to start the morning with, and I like that it is testing a set of directly-useful-on-the-job skills. It feels well calibrated in terms of difficulty.
Misleading HN title. Actual title is "Chrome is experimenting with a Qt backend."
To expand on the link between generators and async functions, the way that async functions were made to run in old browsers that didn't support them by tools like Babel and TypeScript was to rewrite the async function in two stages:
1. Rewrite the async function to be a generator function with a wrapper that calls `next` on the generator whenever `await`-ed Promises resolve
2. Rewrite the generator function to be a big switch statement, together with a wrapper function that drives execution.
You can play around with generators and async functions in the TypeScript playground, with TSConfig set to target ES5, to see how this works: https://www.typescriptlang.org/play?target=1#code/GYVwdgxgLg...
Async functions are conceptually quite similar to ES6 generator functions. In an ES6 generator every `yield` expression is a point where the function can be paused and later resumed. With an async function it is an `await`. The difference between a generator and an async function is that whereas the caller manually resumes generators by calling (`next`) on the generator, async functions are automatically resumed when they yield a promise that is resolved.
Making a function support being paused and resumed requires changes in how the function is run and the data that is maintained while it is executing. In addition to behaving differently than sync functions when they execute, the results are also handled differently. Async functions always return a promise - whether they `return` a literal value, return another promise or throw an exception.
Due to these differences, it makes sense that the special nature of async functions and generators must be declared up-front, with the `async` keyword or `*` for generators. It would be possible to design the language such that the function type was determined by looking at whether it contains `yield` or `await` keywords. Python does this with generator functions. However this makes an important aspect of behavior less explicit.
What are your requirements (data model, non-functional priorities, data size, data types)?