giovannibajo1's comments

giovannibajo1 | 7 years ago | on: Secure Secure Shell (2015)

I (ab)use SSH persistent connections which means my git pushes are super fast even if I live in Europe. Is there some security issue with them? I would say no, but I’m not an expert

giovannibajo1 | 7 years ago | on: Announcing Rust 1.28

> * Partial borrow. > The status of this is unclear. It does work in many cases. It's complicated. I would push back a little on the "no good reason" though, but this is gonna be long so I'll leave it at that.

Not all partial borrows are safe, but a lot of them are. Most programmers know how to write safe code coming from different languages without borrow checker; they do put bugs sometimes -- that's true -- but most of the times the code I write is safe. It's just that there's no way to tell Rust that it is, and the workaround has a global impact on the code being affected (it forces to split structures, which greatly increases the cognitive load in reading and writing the code).

> * Rc/RefCell/Box > Yes, this is painful, but that's because shared ownership is painful.

But the point is that I do NOT want shared ownership. What I want is to have a single owner of a long-living object, and several long-living references to it in other objects. When I say "long-living", I mean that the liveness of those objects is not visible through the call stack, so I can't use borrowing references. The only way to model this today is with shared ownership, which implies more than I would be willing to imply.

The same problem is apparent when trying to implement the callback pattern (which I forgot to list in my OP). Callbacks are basically impossible to do in Rust, and I found out I must have used callbacks everywhere in my last many years of programming in different languages, because I feel helpless in Rust when structuring code without being able to register and use callbacks.

> This is perceived as a good thing; if you code changes later to use threads, you're not hosed.

This does not sound very Rustecean :) If Rust is not opinionated and gives me full power with zero cost overhead, why does it force me to pay for thread-safeness (overhead) so that I can use threads later (opinion)?

Notice also that code which is not thread-safe doesn't prevent me from using parallelism. It just prevents me from moving objects across threads. But I can surely leverage the power of multi-core with threads, as long as the thread-unsafe objects are created and used within a single thread. So I'm not sure why I should make them thread-safe... just because I want to use them in a non-const global.

> If you want something that's not for multi-threading, then don't use something that can be used with multiple threading! TLS is probably what you actually wanted here.

What I want is actually much simpler: let me initial globals with runtime code that the compiler schedules for me to run before main. C++ does that very well; Go does that optimally. Either approach is good enough.

PS: TLS is potentially overhead again: indirect reference on non-PIE binaries.

> Rust is pickier about numbers than many langauges; 1u32 + 1u8 doesn't compile either.

I love that "1u32 + 1u8" doesn't compile, I hate integer promotion. What I'm saying is that "1u32 + {integer}" compiles, while "Wrapping<u32> + {integer}" doesn't. I think it's been a bad tradeoff to force people to use generics for wrapping integers when generics are still not good enough to implement a type which behaves like a native integer on common operations like "+ {integer}" or "as <type>".

giovannibajo1 | 7 years ago | on: Announcing Rust 1.28

I've been studying Rust on and off in the past 3 months. There are a few things that I find annoying, they are somehow discussed in the issue tracker, but it's not clear to me what the priorities are to land them:

* Partial borrow. I can't borrow a field of a structure and then reference another field. I can't cite how many times in a few weeks I've been forced to rethink and split my structures just to work around this, making my code harder to read and write for no good reason than working around this limit of the borrow checker.

* The Rc/RefCell/Box dance is very verbose, when you just want to share a reference to some long-living object within other long-living objects. Worse than verbose, it also causes a runtime overhead because of the RefCell.

* No simple way to declare non-const global objects, like something as easy as a global HashMap of constants strings to constant integers. I'm a little spoiled from Go's excellent support of init functions (both compiler-generated and manually written), but this is something I really miss in Rust. lazy_static! is a workaround which is harder to use and forces the code to be thread-safe even if no threading support is necessary (that is, I can't use my non-thread-safe classes in a lazy_static).

* In generic code, there is no simple way to represent integer types. You need to use the "num" trait which breaks the "as" operator causing big pain and less readable code (as it's normal to covert between integer types).

* No integer generic parameters. We have to use the "typenum" crate which ends up causing less readable code and generates C++-like error messages.

* PhantomData is awkward, it absolutely sounds like something the compiler should handle, not the programmer.

* "Wrapping<u32> + 1" doesn't compile, but is there a good reason why it does not? I really wish Rust added wuNN/wiNN native wrapping types, or evolved in a way that I can write the same code with "u32" and "Wrapping<u32>" (another example: "as" doesn't work). Right now, it seems like the solution is half-baked: it tries to use the generic to avoid adding a native type, but the code that users must write is more bloated compared to native types.

giovannibajo1 | 7 years ago | on: Replacing Linux with a Database System

That’s Redis’ initial persistence design, that is still available, but nowadays most people use it with append-only logs because it provides more resistance to random crashes (eg: power going off)

giovannibajo1 | 7 years ago | on: Performance patches in Go 1.11

I wrote a Nintendo DS emulator in Go (see my GitHub) and ended up seeing lots of missing optimizations in generated code. I opened a few tickets and then focused on BCE. I realized that one of the main problems was the missing transitivity of the pass, so I ended up writing a largish piece of code to implement a partial-order set (see the poset data structure) and then picking on a few low hanging fruits that it opened up to be picked (searching for open tickets on GitHub issues). These were my first contributions to the SSA passes btw.

giovannibajo1 | 7 years ago | on: Mailing lists vs Github

I think that one of the reasons is that the mailing list workflow tends to produce a final deliverable (commit) that makes sense by itself because the whole context will be hard to find (no direct link to mailing list discussion). On GitHub instead when you find a commit you’re always one click away from the PR that produced it, with its discussion inside.

giovannibajo1 | 8 years ago | on: New autoplay policy in Chrome

That’s because websites developers haven’t learnt the 5-years-old iOS UX pattern of not asking for privacy permissions the moment the user opens the app but later in a more contextual way. Eg: request for contacts permission when the user is explicitly looking for a friend to share something.

giovannibajo1 | 8 years ago | on: The Feds Can Now Probably Unlock Every iPhone Model

That doesn’t work as well because the counter is kept in the Secure Enclave so it’s not part of the flash contents. Also the exponential delay in attempts is enforced by the enclave.

Previous iOS versions used to have some small window where you could race and power off after trying a passcode but before the enclave had incremented the counter, but that bug was fixed long ago. Maybe there are others unknown bugs of similar kind

giovannibajo1 | 8 years ago | on: Net Promoter Score Considered Harmful

My feeling about NPS has always been that the very wide pointing system polarizes users towards the two extremes; most people aren’t analytical and they don’t build up a mathematical way to objectively come up with a number between 0 and 10. They would instinctively vote 10 if they’re happy, 0 if they’re angry, and something in the middle if they’re not fully satisfied. The way they map partial satisfaction to a number is unscientific, and this is why NPS only rewards perfect scores (9 or 10).

Similar findings were made by Google with the YouTube rating system that was switched from 1 to 5 stars to a simple upvote/downvote after realizing that most users are polarizing towards the extremes: https://techcrunch.com/2009/09/22/youtube-comes-to-a-5-star-...

giovannibajo1 | 8 years ago | on: Eight years of Go

> - Stdlib just loosely wraps posix features with many C flags copied verbatim. These APIs are old and could use a refresh but Go never bothered. > - Similarly, Go doesnt bother to hide the differences of different OSes.

I disagree with these. Go runtime/stdlib is architected to work around many many POSIX headaches and design bugs, hiding them completely from programmers, and to be fully portable. For instance:

* Concurrency is completely redesigned (goroutines). * Signal handling is redesigned and doesn't cause bugs when interacting with concurrency. * Forking/Exec'ing is redesigned not to cause fd leaks in subprocesses (all file descriptors are marked as O_CLOEXEC, in a race-free way), nor have races while interacting with concurrency * Sockets are exposed through a higher-level API (Dialer/Listener). * epoll is not exposed but transparently used by a single thread to handle all supported file descriptors without wasting OS threads, to improve performance

In fact, I think the only thing that is pretty much low-level is os.File and filesystem access in general, which tends to expose lower-level details.

giovannibajo1 | 8 years ago | on: Evio – Fast event-loop networking for Go

It depends if you're describing a semantic model or you're concerned about implementation details.

Semantically, a goroutine is a thread, within a shared memory model. But what makes Go unique (or let's say more unique) is that it offers programmers a thread-like programming approach (linear, blocking code) but internally turns it into an event-driven approach (epoll/kqueue) for networking.

Moreover, the fact that goroutines are much cheaper than OS-level threads enable a more pervasive approach to concurrency.

giovannibajo1 | 8 years ago | on: Evio – Fast event-loop networking for Go

That is exactly what Go does by default. Any time a blocking operation is performed, Go either leaves the OS-level thread blocked there and switches away, or hand the blocking operation to an internal thread which is running epoll for the whole process.

The end result is much easier than Python/NodeJs because there is no explicit "async/await" or deferred-style programming. You simply write linear code and any blocking operation (at the syscall level) is transparently handled.

giovannibajo1 | 8 years ago | on: Gmail Launches Add-ons

Well, on one hand, mobile operating systems like iOS were designed to be a big step up from the security perspective; android was born more like a desktop operating system scaled down to mobile but has progressively increasing security isolating apps more and more within their sandbox with less options to run in background, hook into the general user experience of the system, and manage things that they don’t belong to them.

On the other hand, your example is wrong on macOS where apple mail and safari are sandboxed. So desktop operating systems are trying to catch up security wise and go beyond the traditional Unix security model.

giovannibajo1 | 8 years ago | on: The trouble with text-only email

FWIW Gmail does that: it triggers trackbacks from a pool of Google-owned IP addresses that don’t map to any specific users, and then serves themselves the images to the clients. This is why they now load images by default: there’s no more privacy issue.
page 8