I just had a look at the code and it is indeed very compact. I haven't compiled or used it.
Looks like RISC-V 32-bit integer and multiply and atomic instr extension. Floating point supported when compiling via gcc or similar the example apps (not by the emulator itself but by the compiler emiting the required software functions to emulate the floating point operations instead).
I think it is very clever. Very compact instruction set, with the advantage of being supported by several compilers.
Wow. Really cool. I wasn't expecting something so polished.
JIRA speed drives me crazy sometimes, so a couple of months ago I decided to build myself a tool to do instant searches/filters on multiple projects right from the browser just to scratch my own itch.
I just wanted to see if I could have near-instant filtering. I think I got a pretty decent performance by using some JS tricks. I'm sure there might be ways to make it even faster.
Page is around 70kb (HTML+CSS+JS). Everything is manually crafted. I know the design won't win a beauty contest, but it does feel instant and works for my personal use-case. I had a lot of fun building this side-project.
There is a public URL, feel free to try it out [1]. Already mentioned in a previous comment in HN a while ago [2].
For the record, it uses a proxy because of CORS. Proxy is in few lines of golang. No NPM or any other framework used to make the project. In any case, if anybody is interested in the source code to run it yourself I'm happy to make the project public. Trusting a proxy on some random's guy on internet is probably a bad idea, given all NPM shit that happened yesterday, in any case, if you want to try, feel free, but use at your own risk :P
Looks cool, but definitely a security team's nightmare. Putting an API key into some random HN'ers hobby project is a bad, bad idea, whoever you are (not saying you're a bad actor, but a zero-trust policy would agree with me).
Indeed. That's why I was transparent from the start. As I mentioned, using an API key this way is generally a bad idea. Even if I'm not a bad actor (which I'm not, but you shouldn't trust me), if someone compromises my server and forges requests, they could potentially access your projects.
JIRA's OAuth implementation requires apps to be registered, involves public/private key pairs, and changes the auth flow. That adds complexity and makes setup harder, which is why I opted for a simpler API key setup, you get the API key, you write it down, you can make requests. It is just simpler and does not require JIRA admin rights.
For comparison, JiraTUI also uses the user's API token. The difference, I guess, is that it runs locally on your machine, but they could also send it somewhere else. At the end of the day, it comes down to whether you trust what you're downloading versus trusting what runs on a remote server. It is true that locally you could potentially inspect all HTTPS or even TCP requests whereas in the remote server you don't have a clue.
The thing is, OAuth in JIRA demands app registration and certificate management, so I guess many developers end up defaulting to user API keys as the path of least resistance, even if they encourage OAuth as well.
For what is worth I built myself a custom jira board last month, so I could instantly search, filter and group tickets (by title, status, assignee, version, ...)
Motivation: Running queries and finding tickets on JIRA kills me sometimes.
The board is not perfect, but works fast and I made it superlightweight. In case anybody wants to give it a try:
Don't dare to try on mobile, use desktop. Unfortunately it uses a proxy and requires an API key, but doesn't store anything in backend (just proxies the request because of CORS). Maybe there is an API or a way to query jira cloud instance directly from browser, I just tried first approach and moved on. It even crossed my mind to add it somehow to Jira marketplace...
Anyway, caches stuff locally and refreshes often. Filtering uses several tricks to feel instant.
UI can be improved, but uses a minimalistic interface on purpose, like HN.
If anybody tries it, I'll be glad to hear your thoughts.
The jump table is interesting, although I guess the performance of switch will be similar if properly optimized with the compiler, but would not be able to tell without trying. Also different compilers might take different approaches.
A few months ago I built a toy boolean expression parser as a weekend project. The main goal was simple: evaluate an expression and return true or false. It supported basic types like int, float, string, arrays, variables, and even custom operators.
The syntax and grammar were intentionally kept simple. I wanted the whole implementation to be self-contained and compact, something that could live in just a .h and .cc file. Single pass for lexing, parsing, and evaluation.
After having the first version working, I kind of challenged myself to make it faster and tried many things.
Once the first version was functional, I challenged myself to optimize it for speed. Here are some of the performance-related tricks I remember using:
- No string allocations: used the input *str directly, relying on pointer manipulation instead of allocating memory for substrings.
- Stateful parsing: maintained a parsing state structure passed by reference to avoid unnecessary copies or allocations.
- Minimized allocations: tried to avoid heap allocations wherever possible. Some were unavoidable during evaluation, but I kept them to a minimum.
- Branch prediction-friendly design: used lookup tables to assist with token identification (mapping the first character to token type and validating identifier characters).
- Inline literal parsing: converted integer and float literals to their native values directly during lexing instead of deferring conversion to a later phase.
I think all the tricks are mentioned in the article already.
For what is worth, here is the project:
https://github.com/pausan/tinyrulechecker
I used this expression to assess the performance on an Intel(R) Core(TM) i7-8565U CPU @ 1.80GHz (launched Q3 2018):
myfloat.eq(1.9999999) || myint.eq(32)
I know it is a simple expression and likely a larger expression would perform worse due to variables lookups, ... I could get a speed of 287MB/s or 142ns per evaluation (7M evaluations per second). I was gladly surprised to reach those speeds given that 1 evaluation is a full cycle of lexing, parsing and evaluating the expression itself.
The next step I thought was also to use SIMD for tokenizing, but not sure it would have helped a lot on the overall expression evaluation times, I seem to recall most of the time was spent on the parser or evaluation phases anyway, not the lexer.
I might be wrong, but at first glance I don't think it is only using those 4 commands. It might be using them internally to get context to pass to the AI agent, but it looks like it exposes:
Yes, that's exactly the point. LLMs "know" about WinDBG and its commands. So if you ask to switch the stack frame, inspect structs, memory or heap - it will do so and give contextual answers. Trivial crashes are almost analyzed fully autonomous whereas for challenging ones you can get quite a cool assistant on your side, helping you to analyze data, patterns, structs - you name it.
I think I would call it naive algorithm rather than greedy.
It looked like an interesting problem so I spent some time this morning exploring if there would be any performance improvement by pregenerating an array of X items (where X around 1M to 16M items) and then randomly returning one of them at a time. I explored the project and copied the functions to be as faithful as the original implementation as possible.
Generating 10M unit sphere (best of 3 runs, g++ 13, linux, Intel i7-8565U, one core for tests):
That's almost 6x faster than rejection method. Setup of the 1M elements is done once and does not count on the metrics. Using double type, using float yields around 4x improvements.
After looking at those results I decided to try on the project itself, so I downloaded, compiled and applied similar optimizations in the project, only updating circle and sphere random generators (with 16M unit vectors that are only created once on app lifetime) but got almost no noticeable benefits (marginal at most). Hard to tell because of the random nature of the raytracing implementation. On the bright side the image quality was on par. Honestly I was afraid this method would generate poor visuals.
Just for the record, I'm talking about something as simple as:
std::vector<Vec3> g_unitSpherePregen;
uint32_t g_unitSpherePregenIndex = 0;
void setupUnitSpherePregen(uint32_t nElements) {
g_unitSpherePregen.resize(nElements);
for (auto i = 0; i < nElements; i++) {
g_unitSpherePregen[i] = unitSphereNaive(); // call the original naive or analytical method
}
}
Vec3 unitSpherePregen() {
g_unitSpherePregenIndex = (g_unitSpherePregenIndex + 1) % g_unitSpherePregen.size();
return g_unitSpherePregen[g_unitSpherePregenIndex];
}
I tried as well using a psrng (std::mt19937 and xorshf96) in unitSpherePregen instead of the incremented variable, but increment was faster and yielded good visual results.
Next step would be profiling, but I don't think I will invest more time on this.
The idea is based on the Ziggurat Method. You overlap the circle with n boxes that each encapsulate the same amount of area of the underlying circle, select a random box, and then do rejection.
With 128 boxes, this reduces the average number of additional iterations from 27% to 0.7%, which should massively reduce the number of branch miss predictions.
It ended up about 2x faster the simple rejection method.
I haven't applied this to spheres yet, but that should also be possible.
Didn't know about Ziggurat algorithm, the use of a table to directly accept or reject is interesting, although I think I would need to implement myself to fully understand. Your comments in the code are great, but I still need I would need to dedicate some time to fully grasp it.
I'm wondering what if a 2D or 3D array was used instead, so that instead of working with the unit circle / unit sphere, you worked on a 256x circle/sphere.
Assuming the center of the circle/sphere was on the position (127, 127) or (127, 127, 127), then you could precompute which of those elements in the array would be part of that 256 sphere/circle radius and only the elements in the boundary of the circle/sphere would need to be marked as special. You would only need 3 values (2 bits per item).
0 = not in the circle/sphere
1 = in the circle/sphere
2 = might be in or out
Then you would only need to randomly pick a point and just a lookup to evaluate whether is on the 2d/3d array. Most of the times simple math would be involved and simple accept/reject would cause it to return a value. I guess it would also produce the number of additional retries to 0.7% on a circle (one circle intersection for every 128 tiems = 1/128 = 0.78%).
From my limited understanding, what I'm saying looks like a simpler implementation but would require more memory and in the end would have the same runtime performance as yours (assuming memory and processor caches were the same, which are probably not). Uhm... I guess the implementation you present is actually doing something similar but with a quarter of the circle, so you need less memory.
I think this is a really cool project. Scrapping aside, I would definitely use this with playwright for end2end tests if it had 100% compatibility with chrome and ran with a fraction of the time/memory.
At my company we have a small project where we are running the equivalent of 6.5 hours of end2end tests daily using playwright. Running the tests in parallel takes around half an hour. Your project is still in very early stages, but assuming 10x speed, that would mean we could pass all our tests in roughtly 3 min (best case scenario).
That being said, I would make use of your browser, but would likely not make use of your business offering (our tests require internal VPN, have some custom solution for reporting, would be a lot of work to change for little savings; we run all tests currently in spot/preemptible instances which are already 80% cheaper).
Business-wise I found very little info on your website. "4x the efficiency at half the cost" is a good catch phrase, but compared to what? I mean, you can have servers in Hetzner or in AWS and one is already a fraction of the cost of the other. How convenient is to launch things on your remote platform vs launch them locally or setting it up? does it provide any advantages in the case of web scrapping compared to other solutions? how parallelizable is it? Do you have any paying customers already?
Thank you! Happy if you use it for your e2e tests in your servers, it's an open-source project!
Of course it's quite easy to spin a local instance of a headless browser for occasional use. But having a production platform is another story (monitoring, maintenance, security and isolation, scalability), so there are business use cases for a managed version.
I bought a treadmill + standup desk 2.5 years ago, and to this day, it remains the best investment I've made to avoid sitting for most of the day.
Before I started using the treadmill desk, I averaged around 2.5-3k steps per day. On days when I exercised, it could go up to 8-10k steps, although I wasn't exercising regularly at that time. Now, 2.5 years later, I consistently reach 10k-12k steps on a bad day (about 2 hours of walking) and can go up to 18-24k steps on a good day (3-4 hours). Occasionally, I hit 30k steps, but that's quite rare, to be honest.
I was hesitant about the idea, but a friend who got one himself and shared his experience encouraged me to give it a try.
Pros:
- Feels more natural than just standing on the desk (after 20 min I get tired of standing still, whereas I can walk 2h without even realizing)
- I can work comfortably with the computer when typing, using the mouse (programming, writing... and even playing games), at speeds up to ~4.5km/h (~2.8 miles per hour). Beyond that the thoughts don't flow in the same way. Below this threshold I don't notice much difference in my work. I initially found 3 km/h (~1.8 mph) fast enough, but over time, 4 km/h (~2.5 mph) has become my sweet spot.
- You can enter a flow state just as easily as when seated (or at least that's my feeling)
Cons:
- Space: The treadmill takes up room, so I keep it next to my desk when not in use for convenience. Setting up the treadmill desk takes around 1 minute.
- Meetings: It felt awkward at first. Initially, I avoided attending meetings while walking, but I gradually started participating in 1:1s and eventually team meetings. Nowadays, I’m comfortable walking during most meetings, although I avoid it during large group or company-wide calls. My webcam is positioned to show only my shoulders and face, minimizing visible movement and reducing distractions for others during calls (probably the others won't care anyway).
- Limited Upper Body Movement: The upper body remains relatively still since my hands are usually on the keyboard or mouse. This limits overall activity compared to walking outside. However, when reading, my arms and hands move off the desk, mimicking the motion of walking, so it really depends.
- Noise: I live in a flat, and while the treadmill isn't very noisy, it could be bothersome if people are sleeping (whether in the next room or in the floor below). I avoid using it early in the morning or late in the evening.
My treadmill automatically beeps after 2 hours and shuts off for 30 minutes. It does force me to take a break (or even take a shower depending on the speed I was walking). After the break, I switch to a seated position. I typically have one walking session in the morning, and on some days, another in the afternoon. When it beeps and I'm in the zone I just move it aside and continue seated (sometimes I just continue standing still for some minutes), so it does not get in the way if you are focused.
Overall I think it is an improvement over staying still for most of the day (seated or standing), and also an improvement over forcing regular/spaced interruptions (I honestly tried several times, but it breaks my concentration and prevents me from going into the zone). Standing desk + treadmill: Totally worth the investment.
One more thing I forgot to mention on the "Con" side is the noise.
Treadmills aren't completely silent; there's always some level of sound from the engine. Over time, you tend to get used to it. Personally, I wear regular headphones to listen to music, which helps mask the noise.
Seconding the treadmill desk (if one's situation allows). My previous job had one for communal use, and once I started working remotely, I picked up the same model (LifeSpan TR1200-DT5) on Craigslist.
I get in between 2 and 10 miles depending on the day, and have a little drafting chair that's intentionally pretty mediocre to encourage walking instead.
I find the idea of intentionally interrupting myself every 20 minutes kinda insane, seems like it would preclude getting "deep" work done.
I've been considering getting something like that at home, because I've found I can walk at a steady pace outside for ages, and it would probably help me get a little bit of exercise as well, but I also don't have a standing desk and I feel bad about making noise when it's late since my flat has very thin walls :/
If you choose a manual or motorized standing desk with adjustable height (like the one I use), you can easily move the treadmill to the side when you're not walking and switch to working while seated.
I mean, you need to have the space to put the treadmill on the side, but other than that you'll have the flexibility to choose between walking and sitting as needed.
That might be an option tbh, I have been needing another desk for non-computer work, so I could just swap them over. Do you have any recommendations for a desk? Is this HN Comment sponsored by flexispot? :P
WalkingPad R1 Pro. I thought the ability to run would be a plus, but honestly, I've only used it for running twice (I'd rather run outdoors than stare at a wall, tv or computer).
KingSmith walking pads can be folded and take less space. R1 can also be stored vertically, but I always keep it horizontally for convenience.
If I had to buy one treadmill again, I would chose either a regular model or a cheaper foldable model. I would probably lean towards a smaller and cheaper regular model since I believe 40cm x 80cm (16in x 32in) is enough to walk and is not that big.
Also even the "pure" C one depends on Java, because Activities exist only on the Java side of Android.
In practice to be usable on a standard Android system, native code must always be compiled to a shared object, with JNI entry points to be called from Java userspace.
The only option is to write such native methods ourselves, or use one of the two predefined Activities for NDK that already expect specific functions to be present on the shared library.
Additionally, the zero Java part only works, if what NDK exposes as stable API is enough, and from Google's point of view, that is only for games, or faster compute, everything else requires JNI fun.
As tip, it is easier to deal with Android IPC for Java <-> NDK communication, than going through JNI boilerplate.
Couldn't one simply make the boilerplate once, as a library, that takes the pertinent bits as arguments? In which case if your app is C anyways it would make sense to just keep it simple with that.
I've been following the progress of bun since your initial announcement and today I decided to give it a try, just to play around.
Haven't done much with it, but even for the 5 min I played with it I'm kind of impressed so far.
- Superquick install PLUS did not require root (like many other installs)
- It identified I was using fish shell and added to path (nice!)
- I ran a very quick bench on "npm install" vs "bun install" on one of the projects I have, and the performance is amazing. 50seconds vs 4.5 seconds on the first install. Moreover re-executing "bun install" takes 122ms on my machine. Removing node_modules and re-executing it takes 769ms (because of course, it uses a local cache elsewhere, but still). Amazing.
I'll probably continue exploring tomorrow and see whether it is able to run the rest of the backend/frontend or whether it gives me a hard time. I've seen there are certain things that are not 100% compatible with node yet, but since the initial impressions are great I'll explore further.
BTW A code formatter and a linter would be a great addition to bun.
But one of the advantages of integrating both things in bun is that it makes it the perfect standard tool to be used inside of a team. So no extra installations from other projects, no extra mental burden of what to use, etc... bun would be the perfect dev companion with both ;)
Probably a linter is a different beast (and not sure you or the rest of people working in bun want to get in there... probably not important right now), but a formatter seems doable and it does add a lot of value from my point of view. Given that bun already runs, installs, tests and bundles, to the very least _formatting_ seems like a natural addition to the family. To me a formatter is part of the standard toolset for developers nowadays.
Once again, thanks a lot for the effort to you and the rest of the people contributing to the project!
Looks like RISC-V 32-bit integer and multiply and atomic instr extension. Floating point supported when compiling via gcc or similar the example apps (not by the emulator itself but by the compiler emiting the required software functions to emulate the floating point operations instead).
I think it is very clever. Very compact instruction set, with the advantage of being supported by several compilers.
Wrapper over this other project which is the one implementing the instruction set itself: https://github.com/cnlohr/mini-rv32ima
Kudos to both projects.