100%. I've always used youtube on desktop (connected to the TV usually), and it seems to me they're just making all versions of youtube into a mobile app optimized for shorts type content. Recommendations are hugely influenced by what you watched very recently. What used to be related videos in the side panel of the player is now just the home page again, but vertical. Even just generating a recommendation from "Whatever (part 2)" to "Whatever (part 3)" is hit or miss now. Some of the recommendations are actually quite good, but at least for the way I like to watch, it's only getting worse over time. The category labels on the home page are also pretty telling - horrible labels (e.g. I watch some cooking/recipe videos and the label will be "Baking sheets" or something like that), plus it emphasizes the recency bias when it shows 5 categories that are basically just the same content with different labels and forgets what I've always liked watching.
HN user
ashf023
Genuine question, but have you seen the popup being described? It's absolutely huge, and has a fake x button pattern. The complaint is on how disruptive it is, not the ask for donations
I don't think this applies to Python. There is a core team and there are expenses, but people do contribute code and work. Not to mention corporate sponsors. Sure, donate if you want, but it's not the same as blocking ads on purely ad-funded content (which I do, but won't defend as much)
I looked out of curiosity and on my 15 inch laptop screen it does take up probably about 40%. I'm surprised by how egregious it is. And it looks like they changed it (or there's an A/B test?) since the thread. It also now jokes about how banners are cringe, actually taking up more space!
Yes, and on one request I saw a message like "Restarting server - this won't take long", and soon after it's back up.
I mean, do it if it's worth it. But the parent seemed to imply everyone should be doing this kind of thing. Engineering is about tradeoffs, and sometimes the best tradeoff is to keep it simple.
I'm definitely in favor of not pessimizing code and assuming you can just hotspot optimize later, but I would say to avoid reusing objects and using sync.pool if it's really not necessary. Go doesn't provide any protections around this, so it does increase the chance of bugs, even if it's not too difficult to do right.
paranoid schizophrenia is an increasingly reasonable reaction to the modern world
Yeah, golang is a particular nightmare for SIMD. You have to write plan 9 assembly, look up what they renamed every instruction to, and then sometimes find that the compiler doesn't actually support that instruction, even though it's part of an ISA they broadly support. Go assembly functions are also not allowed to use the register-based calling convention, so all arguments are passed on the stack, and the compiler will never inline it. So without compiler support I don't believe there's any way to do something like intrinsics even. Fortunately compiler support for intrinsics seems to be on its way! https://github.com/golang/go/issues/73787
Henriks true penalty would be living in a country of 6 million people that all know his face and that he is a pedophile.
This is what I object to, not really your comment. Is this factored into the sentencing? If he weren't a public figure would he have a harsher sentence?
You don’t have to worry about him doing anything in Politics again
Sure, if everyone in Denmark remembers this guy then he won't be popular. But really we don't have to worry about him? 4 months later is he just free to go back to collecting CP, maybe leave Denmark, etc?
What an absolutely absurd statement
JPEG is similar actually. The DCT is invertible, but the result of the DCT is quantized, which is where some of the compression happens (DCT -> quantization -> IDCT), so the end to end process is not truly invertible. Maybe an analogy to the non-linearities in between the linear steps in deep learning
Agreed it's missing that detail. I think it makes sense though that the durable queues shouldn't need strong consistency and transaction isolation, just durability, so the DBs can probably be sharded pretty arbitrarily, maybe operate in lower isolation modes, etc, whereas the DB they need to async writes to probably does need transaction isolation and all that. I'd appreciate if the article would confirm or deny my guess here!
Fair enough, I was a little too negative. It is good they're thinking about improvements
Interesting that very few people in that thread seem to understand Go's model, especially the author of this proposal. If you don't allow preemption, you still have a sort of coloring because most non async functions aren't safe to call in a virtual thread - they may block the executor. If you call C code, you need to swap out stacks and deal with blocking by potentially spawning more OS threads - that's what CGo does. Maybe preemption is harder in Python, but that's not clearly expressed - it's just rejected as obviously unwanted.
Ultimately Python already has function coloring, and libraries are forced into that. This proposal seems poorly thought out, and also too little too late.
All goroutines are async in some sense, so generally you don't need to return a channel. You can write the function as if it's synchronous, then the caller can call it in a goroutine and send to a channel if they want. This does force the caller to write some code, but the key is that you usually don't need to do this unless you're awaiting multiple results. If you're just awaiting a single result, you don't need anything explicit, and blocking on mutexes and IO will not block the OS thread running the goroutine. If you're awaiting multiple things, it's nice for the caller to handle it so they can use a single channel and an errorgroup. This is different from many async runtimes because of automatic cooperative yielding in goroutines. In many async runtimes, if you try to do this, the function that wasn't explicitly designed as async will block the executor and lead to issues, but in Go you can almost always just turn a "sync" function into explicitly async
"one obvious way to do something" describes almost none of Python. Easier said than done I guess, but I find Python particularly bad at it
If I understand it correctly, this is only catching ownership violations at runtime, so it doesn't actually prevent writing/shipping the bug? But it does seem to be able to improve the detection rate and determinism, and also help with diagnosing the bug when it's discovered. If this does let simple unit tests in CI discover concurrency bugs, that's a big improvement, even if it's not as strong as static analysis. I imagine there are still cases where the ownership violation is not deterministic though, e.g. depending on the data or the app's configuration, and maybe will not be caught until production
IMO pushing ifs up makes sense when the condition is enforceable by the type system, e.g. in the Option<Walrus> vs Walrus example, and when doing so makes the function's purpose more clear, or gives callers more flexibility. I think it's generally intuitive when writing code - can I use the type system to guard this rather than checking in my function, and should this function decide what happens in the unexpected cases?
Pushing fors down is usually not that relevant in Rust if all it achieves is inlining. The compiler can do that for you, or you can force it to, while improving reusability. It can make sense if there's more optimization potential with a loop e.g. lifting some logic outside the loop, and the compiler doesn't catch that. I also would avoid doing this in a way that doesn't work well with iterators, e.g. taking and returning a Vec.
Yeah I find this so strange. Why not take the opportunity to throw a bunch of heavily cached shorts recommendations in our faces when signed out? I don't understand how the anon home page is not both a money maker and extremely cacheable and cheap to serve
100%. I work in Go and use optimizations like the ones in the article, but only in a small percentage of the code. Go has a nice balance where it's not pessimized by default, and you can just write 99% of code without thinking about these optimizations. But having this control in performance critical parts is huge. Some of this stuff is 10x, not +5%. Also, Go has very good built-in support for CPU and memory profiling which pairs perfectly with this.
sync.Pool uses weak references for this purpose. The pool does delay GC, and if your pooled objects have pointers, those are real and can be a problem. If your app never decreases the pool size, you've probably reached a stable equilibrium with usage, or your usage fits a pattern that GC has trouble with. If Go truly cannot GC your pooled objects, you probably have a memory leak. E.g. if you have Nodes in a graph with pointers to each other in the pool, and some root pointer to anything in the pool, that's a memory leak
This immediately popped into my head! I remember it blowing my mind years ago
Yeah it's definitely similar to having parent nodes summarize their children. The motivation for the flat array structure was to have an entirely fixed-size array that's contiguous in memory to make it friendly for SIMD filtering. Having the data in the tree on the other hand could probably filter a little better since it can summarize at multiple levels, but my bet is that the flat array allows for a faster implementation for the case here with a few thousand intervals. On the one hand, the whole working set should probably fit in L1 cache for both the tree or a flat array, but on the other hand, a tree with pointers needs to do some pointer chasing. The tree could alternatively be represented in a flat array, but then elements need to be shuffled around. I don't know which is faster in practice for this problem, but my gut says the speed of a flat array + SIMD probably outweighs potential asymptotic improvements for the few thousand case
Maybe an additional "lower resolution" index on top of the map could help as a heuristic to skip whole regions, then using the map to double check possible matches. I have a rough idea that I think could possibly work:
Maintain the sum of booked time within each coarser time bucket, e.g. 1 hour or something (ideally a power of two though so you can use shifts to find the index for a timestamp), and keep that in a flat array. If you're looking for a slot that's less than 2x the coarser interval here, e.g. a 90-minute one, look for look for two consecutive buckets with a combined sum <= 30 minutes. 2 hours or more is guaranteed to fully overlap a 1 hour bucket, so look for completely empty buckets, etc. These scans can be done with SIMD.
When candidate buckets are found, use the start timestamp of the bucket (i*1hr) to jump into map and start scanning the map there, up to the end of the possible range of buckets. The index can confidently skip too full regions but doesn't guarantee there's a contiguous slot of the right size. I don't have a great sense of how much this would filter out in practice, but maybe there's some tuning of the parameters here that works for your case.
Updates should be relatively cheap since the ranges don't overlap, just +/- the duration of each booking added/removed. But it would have to deal with bookings that overlap multiple buckets. But, the logic is just arithmetic on newly inserted/deleted values which are already in registers at least, rather than scanning parts of the map, e.g. if you wanted to maintain the min/max value in each bucket and support deletes.
Gotcha. I wasn't quite sure from your post, are you storing free slots in the map, or booked slots? And do you know, for the cases that aren't fast enough, how much they tend to search through? Like are there just a ton of bookings before the first free slot, or are the slow cases maybe trying to find very wide slots that are just hard to find?
A few rough ideas for bitsets:
- To find runs of 15+ 1s you can find bytes with the value 255 using SIMD eq
- For windows of width N you could AND the bitmap with itself shifted by N to find spots where there's an opening at index i AND index i+N, then check that those openings are actually contiguous
- You can use count-trailing-zeros (generally very fast on modern CPUs) to quickly find the positions of set bits. For more than 1 searched bit in a word, you can do x = x & (x-1) to unset the last bit and find the next one. This would require you search for 1's and keep the bitmap reversed. You can of course skip any words that are fully 0.
- In general, bitmaps let you use a bunch of bit hacks like in https://graphics.stanford.edu/~seander/bithacks.html
But the article talks about how the men are basically doing whatever they want and women are left as single mothers with multiple kids...
Is this different than existing instruction level parallelism and hyperthreading?
[CPUs] primary limitation is that as serial rather than parallel processors, they can only do one thing at a time. Of course, they switch that thing a billion times a second across multiple cores and pathways
This is from the article, not the company, but unless I'm misreading it, it's just wrong