A long time ago I worked with someone who read 1 byte at a time from a socket because they insisted data was cached so the kernel was going to batch it magically somehow. It took me days to convince them to measure it.
I used to make it a general rule to start all my optimisation of any network code by running strace and look for excessive read's and write's, because you'd be shocked how many did stuff like that if they didn't know the length of a string, or to read the length first, instead of reading into a buffer.
I had to convince people with benchmarks regularly that, yes, you could write the handful of lines to do proper user-space buffering and trivially run rings around any code that did extra context switches, because a lot of people didn't realise the cost difference between system calls and calling their own functions.
This included, by the way, the MySQL client library, at one point, which would do small read for length fields instead of larger non-blocking reads into a buffer all the time
That's different: you're talking about the application code, like OP.
But I think the parent comment's point is that the issue is in the implementation of fread itself in the standard library. It's perfectly reasonable for an application to pass it 1, 65536 (i.e. one byte, up to 65536 times) and expect it not to issue 65536 separate OS calls.
Is it? I get what you're saying, but asking for 1 byte 65536 times, is indeed different than asking for 65536 bytes, 1 time. There may be reasons, such as when you pull off the end of a buffer, it shifts. And the buffer size is 1 byte. Or 10. Or whatever.
No, I'm not saying that's why. I'm simply saying there is a difference between asking for 1 byte or 65k bytes of something. Even dd runs the same under Linux.
dd bs=10k count=1 is faster than bs=1 count=10k
I remember trying to recover some data from a spinning disk, and trying to slowly creep up on the data. So I wanted 1 byte per, I wanted it to nibble, until it hit whatever the errored part was. If I just grabbed the lot, it'd error out from the whole read.
The latter (as usual when comparing OpenBSD and Linux) is more complex, but both multiply count by size and then go their way.
Also, the API contract allows fread to read fewer bytes than requested. I would except any implementation to do that.
But maybe, somebody interpreted the contract differently than major OSes, in the sense that a call isn’t allowed to write partial size-sized chunks to user memory and/or advance the file position further than its return value advocates (that, I think, is something that the implementations above can do, and might be considered a bug)
> asking for 1 byte 65536 times, is indeed different than asking for 65536 bytes, 1 time.
Yes it's different. As others have noted, the difference is what is returned if less than 65536 are available to read in the file: total failure vs partial read.
There is, unsurprisingly, no requirement that it has an unnecessarily inefficient implementation to meet this behavioral requirement. (The C standard doesn't talk about such things as syscalls but, even if it did, it surely wouldn't require such a thing.)
The irony is that that partial read is actually the default on both Windows and Posix (i.e. both ReadFile and read() will read up to the number of bytes specified). So a one-syscall implementation for fread would have been easier than multiple calls, and certainly would be standard compliant.
The dd example isn't comparable because dd is much lower level, and you really are specifying how the syscalls should be made.
Also you need to be careful what you read/write. In some cases.
As many examples out there use int/char etc to show how to use the thing. But if you switch to structs that fwrite can totally burn you if you use the sizeof call. As the sizeof a struct can vary between platforms and compilers. Depending on packing. Then endianness can sometimes mess you up. If you are reading/writing for yourself you can get away with a lot. But if you are trying to interop then you have to be wildly careful what you do.
fwrite is another one where people will do one byte at a time (same up to for the windows version). Bash out a loop, use the sizeof for the input to the for loop. copy and paste just doing 1 byte and you can easily end up here. One program I added a cache in front of the thing so it would always write on disk block boundaries and then come back for more. I started off with just packed struct sizes but the perf was just 'ok'. The file block boundary thing really made it fast. Not all OS's have a readahead/write buffer behind that call so perf can vary.
It is honestly such an easy mistake to make. As many of the examples/docs do not really show you why/how to use both of those calls in the way needed. You sort of have to stumble into it and work it out.
Once you see it you know. But until then you do not really notice if it is 'working'.
Are you sure you're not thinking of raw read() / write() (the operating systems calls) rather than fread() and fwrite() (the C standard library functions)? fread and fwrite already have a cache, so repeated calls won't make lots of OS calls.
Or, at least, they shouldn't! Clearly OP's implementation was a counterexample (it made lots of OS calls just for a single fread call).
Unfortunately not all of them. It depends on the device you are using, and the storage device, and the kernel, and the CRT you are using. The process I was using went from like 20-30 seconds to run to less than a second once I put a cache in front of it. Current implementations may have that cache. I would look first and see what they are doing. At the time I was working with about 6 different CRT's of varying age and quality. Some systems you can turn it on and off per device, or global, or per call depending on flags passed in. Really it comes down to reading the docs (probably right), and testing it out (empirical evnidence). That project I learned to not trust the c runtime libraries. But to verify what they are doing and re-read the docs and make sure I am even using the thing correctly vs what is written in the code and my assumptions.
Another possibility for why it needs to be done that way is dealing with error conditions.
I've not looked at the code (or even the man pages) and it is a long time since I touched anything that low level, so this might be completely wrong, but if there is an error before the next 64KiB (including just hitting EOF) then the semantics could be different. Asking for 1x64KiB I would expect to just error as there aren't the requested number of bytes. Asking for 64Ki lots of 1 byte might simple error just the same, or it might at least populate the buffer with what it can read, or if the meaning of 1,65536 is actually “up to 64Ki lots of 1B” then it would populate the buffer as far as possible and return the amount read rather than an error condition.
If the per-byte option is slow but still fast enough, and dealing with the semantics is less faf, then people will go for that because the tiny time loss is worth the larger effort reduction. Of course this assumes the underlying system doesn't change, as with the “making local code to run as on-demand networked code” example higher in the thread which changes the relative performance characteristics of the two calling methods significantly.
dd is designed to request a certain block size from the kernel. fread is not and should just multiply the two arguments and read that many bytes, just like calloc.
Over time I must have spent several dozen hours looking into fonts, but I somehow always end up sticking to Menlo which looks just right to me.
But this one looks really good ! I will give it a spin, thanks for sharing.
Funny, I don’t know if you’re being sarcastic or sincere because I can’t tell the difference between that car and a Mustang or a Charger from the same decade.
In any case, the '67 and '68 Mustangs are the best looking of the Mustang line, and the '68 Dodge Charger is to die for.
If you cannot tell the difference, may I suggest you spend a wonderful evening watching "Bullitt".
When I was in high school, a friend of mine bought a '67 Mustang for $200, so of course he offered me a ride. I had never ridden in one before. I barely had the door closed when he stomped on the gas. What can I say, it was a transformative experience! I soon acquired one for myself. Converted it to a 4-speed, hopped up the engine, and had a grand time with it for years until a garbage truck turned it into an accordion.
I still miss that car.
But I did wind up replacing it with a 72 Dodge Challenger, which is close to being a Cuda. I spent a lot of money on its engine in the machine shop. I enjoy every second driving it, and giving friends rides in it.
Like me before I got the ride in the Mustang, you gotta get a ride in one before you dis it.
Everyone telling you that it's fast because iTerm2 is slow. Terminal.app is already faster than iTerm2 and on par o very close to most other alternatives in terms of speed.
I also used Terminal until recently and don't use any of the advanced features alternatives provide. The main reason to switch from Terminal.app is truecolor support. The terminfo thing is annoying but I just setenv TERM in ssh config. Better split panes is nice. Configuration in a text file is a matter of taste, but documentation is good.
> Playlists are ok, but heavily recommending entire albums is bizarre. Its like trying new foods by going to Costco. It would make more sense to select top picks from an artist.
Strongly disagree. It’s probably a generational thing but I listen to music in albums, not in popular hits. This was by far the main reason I used to use Rdio instead of Spotify.
I listen to entire albums too! But not from artists I've never heard of before, as is commonly the case in recommendations. It takes me a few listens from their singles to warm up to them, and then dig further into their discography.
"My New Music Mix" is updated 1x week for some inexplicable reason (I know Spotify does this too), while it seems to recommend albums programmatically based on likes/listening habits. Other playlists seem to be manually curated and recommended based on genre.
Understandably, there is just no way to expect manually curated playlists to cover everyone's personal tastes.
I believe it is possible to recommend songs/artists/albums without favoring one form of discoverability over the other as it is currently done.
Spotify does suggest albums (and singles, it makes no distinction, ugh). But yeah I use the Spotify Premium subscription to almost exclusively play albums.
EDIT: Discovery is terrible, the only sites that had excellent discovery was last.fm (butchered by CBS) and what.cd (nuked by law enforcement)
Strangely the on that had the best discovery for me was Google Music. It just seemed to eerily read my mind and I stumbled on so many good titles that I love. Rarely did I need to skip any song during, say, a workout playlist.
As for the UI, I loved the Google Music one... when I was on Android. Now that I'm on iOS it's totally alien and just unusable because zero iOS conventions are respected, like I'm in a virtual machine, it's just frustrating. I find all of the other music platform UIs quite awkward and despite its flaws Apple Music is still the best for me.
Seems like we hit a wall and "all MUAs suck" just changed the M from "Mail" to "Music".
There's a lot of things I don't like about Google Music UI but the artist page with the top 5 songs and the albums below works great for both getting a taste of a new artist and entire album listening.
yea, but still the problem is that all users who created a vault before Nov 2015 never got any message neither is their database upgraded automatically. They will unknowingly keep using the old database format.
Seems alarming for a company who's business is security/privacy.
> and is not selected by default when you create a new vault.
I was clearly only responding to this part, which is still useful information. Nowhere I said there is no issue, there is no need to always nitpick on everything. I'll go back to not commenting on anything for another year.
That style is usually called “single story a”. Monaco is a common monospaced typeface that uses it. I suspect that style is less common because at small sizes it's easily confused with o.