Efficient string copying and concatenation in C - <AUTHOR> https://developers.redhat.com/blog/2019/08/12/efficient-string-copying-and-concatenation-in-c/ <comment><USER2> I can't see how incrementally improving the approach of the C standard library is the right design decision here. They need to just include a standard, well designed dynamic strings library to C, that stores the length alongside with the (binary safe) string itself, and that's all. Every serious C program uses it, null terminated strings are a joke. However because of this huge background with null terminated strings in C, such library should make sure to always automatically terminate strings with a null term, so that people can trivially print them, call strlen() against them and so forth when needed and when there is no binary data inside.

<comment><USER3> A lot of C developers I know see value in keeping the C standard library small. I implemented my own `l_string` (length-string) struct and associated libraries for a class (we weren't allowed to use external libraries) and it was not prohibitively difficult. Something like this probably covers most use cases: [https://github.com/antirez/sds](https://github.com/antirez/sds)

<comment><USER4> > A lot of C developers I know see value in keeping the C standard library > small.

And what value what that be?

... if you're going to say "easier to fit a small implementation into the memory of some microcontroller" \- not a sufficient argument. There's always some smaller system with not enough memory, and larger systems with more than enough.

<comment><USER5> This is C land. You're not going to make it far by making the case that bloat is acceptable.

People have a range of technical and aesthetic reasons for hating bloat and C attracts a lot of them.

Off the top of my head:

\- Smaller memory footprints

\- Easier reimplementation

\- Lower attack surface

\- Less room for breaking changes

\- Less baggage for when we inevitably wish we could deprecate things

<comment><USER6> > _\- Lower attack surface_

wut?

<comment><USER3> String formatting libraries, and other things that work with buffers are frequent attack surfaces for buffer overflow attacks.

Granted, using C means developers often implement these operations themselves which introduces the possibility of creating more attack surfaces. But it's less likely that the standard library presents an attack surface when the standard library is tiny.

<comment><USER6> I mean, C's attack surface is like that of activated charcoal. I'm not sure that C's small standard library gives it a smaller attack surface, specifically because it means programmers who have better things to do are forced to reinvent the wheel, poorly [1]. But mostly, because C's lack of guardrails means it takes active effort on even trivial operations to be safe.

I've been working with it for nearly two decades, and every year I think more that C programs should be confined to a well-guarded quarantined area with hazard trefoils and a "beware of the leopard" sign.

[1] [https://en.wikipedia.org/wiki/Greenspun%27s_tenth_rule](https://en.wikipedia.org/wiki/Greenspun%27s_tenth_rule)

edit: people reimplementing their "safe" string library isn't something to brag about, but be ashamed of our entire industry for.

</comment></comment></comment></comment></comment></comment></comment><comment><USER7> I think memccpy is an improvement, so I support it, but it's still complicated to use in practice. The article gives this example for a copy followed by concatenation:

        char *p = memccpy (d, s1, '\0', dsize);
        dsize -= (p - d - 1);
        memccpy (p - 1, s2, '\0', dsize);

Notice that you have to recalculate dsize (correctly without one-off errors!), it assumes you have dsize itself, and this doesn't detect overruns (which in many cases you should do).

So real-world code would look more like this:

        // dsize is the space *available* in d, including \0
        size_t dsize = sizeof(d); // if d is an array
        // ...
        char *p = memccpy (d, s1, '\0', dsize);
        dsize -= (p - d - 1);
        if (dsize <= 0) goto overflow; // handle overflow
        char *q = memccpy (p - 1, s2, '\0', dsize);
        dsize -= (q - (p - 1) - 1);
        if (dsize <= 0) goto overflow; // handle overflow

It's a little easier to understand than strncat/strncpy versions, it doesn't unnecessarily read its inputs past where they are needed like strlcat/strlcpy do, and it's more efficient than snprintf. So yes, it's an improvement and I support it. However, this is still rather complex; in particular, it's _way_ harder to understand compared to code that uses snprintf, and certainly harder to understand than pretty much any other programming language higher level than assembly.

So let's accept this improvement, and keep striving to do better.

<comment><USER8> Yeah I think strlcpy is way better exactly for this reason. I'm sure the idea behind returning the pointer was call chaining, but you shouldn't ever be doing that anyway, and with strlcpy you basically can't do an off-by-one.

<comment><USER7> It's true that strlcpy is easier to use. One challenge is that strlcpy always reads its inputs to completion, even when it is not needed to make the copy, because it has to compute the total length of the screen ignoring limits. In some circumstances that is a problem.

</comment></comment></comment><comment><USER9> I feel like one alternative is missing from the list:

      fp = fmemopen(buf, sizeof(buf), "w");

      fputs("one", fp);
      fputs("two", fp);
      fputs("three", fp);

      fclose(fp);

Not sure how it performs, but it reads pretty well IMHO.

</comment><comment><USER10> Why are embedded developers unnerved by the concept of a featureful standard library? There are Linux distributions aimed at statically compiled, musl- based packages, hence you can very much choose what you need for your project.

Look at C++'s std::string in GCC, Clang, and MSVC's standard libraries and respectively its development history. Of course you can make a minimalistic standard string and also eliminate nullpointer checks, trailing \0 checks (everyone passes size_t len anyways), and allocation issues in runtime.

The only standard thing about C strings are vulnerabilities.

<comment><USER11> I used to work on routers that essentially ran embedded linux inside and our new projects started all being c++ after a while. It's amazing after the switch to c++, we basically stopped ever seeing string/array related segmentation faults now that developers use std string/vector/etc by default. Yeah, it's more resource expensive, but we have plenty of RAM now on these boards and it's totally worth not having a maintenence nightmare like our legacy C projects which I swear get a new bug report every other month about a newly discovered string/array-related segmentation fault (I'm not saying C++ can't ever be a maintenance nightmare, to be clear, but as far as memory related issues go, they disappeared the moment we started using std library).

<comment><USER10> Interesting, did you make your own allocators? Can you tell me the company?

</comment></comment></comment><comment><USER12> The refusal of glibc (and I suppose, POSIX) to adopt strlcat/cpy is continually obnoxious.

That said, if you actually need efficient string operations, you probably want a Rope data structure rather than any libc primitive.

<comment><USER13> strlcat and strlcpy are not adopted because they are a really bad design. Using them correctly takes more code than not using them. In practice they are never used correctly, making them, an "attractive nuisance", a feature that causes more trouble than its absence.

<comment><USER12> This argument doesn't hold water. They're absolutely no worse than strcat/cpy and strncat/cpy, which glibc implements. I totally disagree with your premise that truncation is an incorrect use.

In reality, the alternative to strlcpy/cat isn't "force programmers to write correct code," it's "programmers will just use the crappier available functions with even worse behavior on overrun."

<comment><USER13> Perhaps you have some better reason why Posix has rejected it, again and again? Some sort of conspiracy is conceivable, but in service of what?

I have seen much, much better designs, that take into account that these functions are rarely called in isolation. In those, calls cooperate with previous and subsequent calls to share the burdens of maintaining correctness and safety.

<comment><USER14> POSIX never rejected strlcpy/strlcat, because they were never submitted for inclusion. Also, POSIX doesn't control the str* namespace, ISO C does. Not that it matters, as it wasn't submitted there either.

But that's beside the point. Every major OS's libc has an implementation of strlcpy/strlcat, and OpenBSD's can be readily lifted into a project's source tree as it is portable, a simple code search will reveal the breadth of adoption. The /only/ exception is glibc now. And glibc is not a standards committee, for years the primary objections came from one person.

You're being dishonest.

[https://github.com/search?q=strlcpy&type=Code](https://github.com/search?q=strlcpy&type=Code)

</comment></comment></comment></comment></comment><comment><USER15> C-coders of HN, do you use plain vanilla C strings in your project (s)? I was under the impression that most (at least bigger ones) use some custom length carrying string type to avoid exactly these sort of problems

<comment><USER16> It depends. If I'm writing a library, it's bare pointers. If I'm writing something not a library that's big enough, I'll use a struct {size_t length; char* string;} where the length is the string length, and string contains (length) characters + a nul byte. I might even mix in allocation data for the total allocated size of the buffer if it's important enough.

Simple to implement and use (and also backwards compatible), provided you have a library of common functions for allocating, copying, etc.

If I'm size constrained, I'll consider uint16_t for the length field. If I'm REALLY size constrained, I'll use a VLQ [1] for the length field and take the slight performance hit.

[1] [https://github.com/kstenerud/vlq/blob/master/vlq- specificati...](https://github.com/kstenerud/vlq/blob/master/vlq- specification.md)

</comment></comment><comment><USER17> "The strlcpy and strlcat functions are available on other systems besides OpenBSD, including Solaris and Linux (in the BSD compatibility library) but because they are not specified by POSIX, they are not nearly ubiquitous."

This ignores how often they are (re)implemented in userland. glib, X and even the linux kernel have implementations. Perhaps we could just standardize what programmers chose rather than allow glibc an unjustified veto?

</comment><comment><USER7> memccpy definitely has some advantages, so it definitely should be in the ISO standard.

But memccpy has its own problems. In particular, when concatenating you have to constantly recalculate the "space remaining"; that is just _asking_ for an off-by-one error that leads to a buffer overflow, and makes it more complicated to use. The discussion here doesn't detect attempted overflows, and that's a mistake; you often need to not just _prevent_ an overflow, but you also need to _detect_ an attempted overflow and do something different. You also have to pass \0, which makes the function call more complex (and perhaps under-optimized) since \0 would in nearly all cases be the parameter passed.

So I'm glad this is being added, but it's at most a small step to improving simple string copying and concatenation in C.

</comment><comment><USER18> The Microsoft approach to this was to make a set of replacement functions (strsafe.h [1]) that are very explicit and not at all "clever", as the strsplcasdfcpy functions seem to want to be. They return an error code so it's obvious when the operation did what was expected, or ran out of space.

[1] [https://docs.microsoft.com/en- us/windows/win32/menurc/strsaf...](https://docs.microsoft.com/en- us/windows/win32/menurc/strsafe-ovw)

<comment><USER7> But most people want to use standard, portable calls.

The C standard tried to add such functions in "Annex K", but unfortunately annex K hasn't received much of a pickup (for various reasons).

So in many places the problem continues.

</comment></comment><comment> GuB-42 This is one of the reason I tend to avoid str* functions in the first place, except for one strlen() per string.

The way I copy and concatenate strings typically looks like:

      int len1 = strlen(str1);
      int len2 = strlen(str2);
      char *buf = malloc(len1 + len2 + 1);
      if (buf) {
          memcpy(buf, str1, len1);
          memcpy(buf + len1, str2, len2);
          buf[len1 + len2] = 0;
      }

Of course, not memcpy()ing data around is even better if I can avoid it.

<comment><USER19> s/int/size_t/ and check for overflow.

<comment> GuB-42 Totally right about size_t, my bad, hopefully, the compiler will raise a warning.

As for integer overflow, I don't actually know how to handle it properly. In normal conditions, it is unlikely to be a problem. If the two strings can fit in memory, the sum of their size should fit in a size_t, but I agree that making such assumptions can be a bad idea.

Maybe the best way is to limit the size of the input strings to a reasonable value. That would prevent many out of memory situations too and potential DoS too.

<comment><USER19> > As for integer overflow, I don't actually know how to handle it properly.

Something like:

       if (str1 && str2) {
          size_t len1 = strlen(str1);
          size_t len2 = strlen(str2);
          size_t buf_len = len1 + len2 + 1;
          if (len1 < buf_len && len2 < buf_len) {
             char *buf = malloc(buf_len);
             if (buf) {
                memcpy(buf, str1, len1);
                memcpy(buf + len1, str2, buf_len - len1 - 1);
                buf[buf_len - 1] = '\0';
             }
          }
       }

(I probably made a mistake above.)

As you suggest, you'll probably run out of memory before you'll overflow, so in reality, you want to check len1 and len2 are some sane value, but of course, library functions don't usually have that luxury. Take a hint from git:

        #define unsigned_add_overflows(a, b) \
            ((b) > maximum_unsigned_value_of_type(a) - (a))

        if (unsigned_add_overflows(extra, 1) ||
            unsigned_add_overflows(sb->len, extra + 1))
              die("you want to use way too much memory");

[https://github.com/git/git/blob/6d5b26420848ec3bc7eae46a7ffa...](https://github.com/git/git/blob/6d5b26420848ec3bc7eae46a7ffa54f20276249d/git- compat-util.h)

[https://github.com/git/git/blob/9d418600f4d10dcbbfb0b5fdbc71...](https://github.com/git/git/blob/9d418600f4d10dcbbfb0b5fdbc71d509e03ba719/strbuf.c#L90)

> making such assumptions can be a bad idea

It's always a bad idea, especially in an unsafe language. Never trust user input.

</comment></comment></comment></comment><comment><USER20> > Of the solutions described above, the memccpy function is the most general, > optimally _efficient_ [...]

This does not seem to be the case for me AT ALL. _strcpy_ for example, is a lot faster than _memccpy_. Here are my results:

      $ gcc -O0 bench.c && ./a.out
      memccpy: 0.008405
       strcpy: 0.002913

      $ gcc -O3 bench.c && ./a.out
      memccpy: 0.007933
       strcpy: 0.002590

      $ clang -O0 bench.c && ./a.out
      memccpy: 0.008771
       strcpy: 0.003225

      $ clang -O3 bench.c && ./a.out
      memccpy: 0.007966
       strcpy: 0.000383

      $ musl-gcc -O0 -static bench.c && ./a.out
      memccpy: 0.007849
       strcpy: 0.005647

      $ musl-gcc -O3 -static bench.c && ./a.out
      memccpy: 0.005754
       strcpy: 0.005625

      $ tcc bench.c && ./a.out
      memccpy: 0.014252
       strcpy: 0.004045

Source code can be found here: [https://slexy.org/view/s2EHngPvDh](https://slexy.org/view/s2EHngPvDh)

\---

The differences seem to be quite interesting. Did I mess up the code? Compare _gcc -O3_ 's _strcpy_ and _clang -O3_ 's _strcpy_ : _0.002590_ vs _0.000383_! _musl-gcc_ on the other hand has much more similar results.

\---

      $ gcc --version
      gcc (GCC) 9.1.0
      Copyright (C) 2019 Free Software Foundation, Inc.
      This is free software; see the source for copying conditions.  There is NO
      warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.

      $ clang --version
      clang version 8.0.1 (tags/RELEASE_801/final)
      Target: x86_64-pc-linux-gnu
      Thread model: posix
      InstalledDir: /usr/bin

      $ tcc -v
      tcc version 0.9.27 (x86_64 Linux)

<comment><USER21> >Did I mess up the code?

You certainly did; both your benchmark functions overflow their internal buffers.

However, it's not all that improbable for memccpy to be slower than strcpy in this case, even if it was used correctly; after all, it does more, and by doing so would prevent the buffer overflow if supplied with correct arguments (specifically, the last one). As to how much slower, I cannot tell. Also, you're skipping over half the point of the article by using a (fixed) source string, the size of which is known in advance.

In general, I would not benchmark library functions on local variables (buffers) without observing their results. It's far too easy for the compiler to remove the call altogether when said removal doesn't make any difference on the output.

<comment><USER20> > You're skipping over half the point of the article by using a (fixed) source > string, the size of which is known in advance.

You are right. I should have focused more on that instead, that seems more relevant to why the author of the article is suggesting _memccpy_. I am curious as to whether or not it really is the case that _memccpy_ is "optimally efficient" in practice over the alternatives. Would you like to prove or disprove that statement yourself? I modified the code a bit; it uses _strlen_ to calculate the length of the string passed, and the string is _argv[1]_. _memccpy_ is still just as slow. Is this a more acceptable approach to you? In this case we do not know neither the string, nor its length in advance. _strcpy_ still outperforms _memccpy_. Is this sufficient to disprove the claim that _memccpy_ is "optimally" efficient to other alternatives? The other criterion was being widely adopted, in which case, well, _strcpy_ also looks good. Moreover, as dwheeler pointed out, _memccpy_ is a tad difficult to use in practice. I will give _strlcpy_ a try, too, since I prefer that over _strcpy_. In any case, I am not convinced that these criteria hold true for _memccpy_ over the alternatives.

> on local variables (buffers) without observing their results

What do you mean exactly? I did observe the results of the buffer. See the _printf_ , or are you not referring to that?

> both your benchmark functions overflow their internal buffers.

Would you please elaborate on it, and its relevance? Are you referring to N being too high?

<comment><USER21> >Would you please elaborate on it, and its relevance? Are you referring to N being too high?

No, the stack size is implementation-defined anyway. Instead, you have a classic off-by-one error because you didn't reserve any space for the final null terminator.

Correctly used memccpy would protect against an issue like this, although the destination string would not be correctly terminated, as it's not a safe string function. Also, if your memccpy version had the correct arguments inside the loop, you wouldn't have needed the extra call before the loop to hide the issue, as the memccpy call would have been functionally identical to strcpy except for the last pass of the loop.

>What do you mean exactly? I did observe the results of the buffer. See the printf, or are you not referring to that?

At least in the link you provided, all the printf's that would observe the contents of _buf_ after the loop are commented out. No observable change happens in the execution of the program even if your compiler decides to just remove any calls to strcpy or memccpy.

\--

That being said, strcpy is quite efficient at what you're benchmarking; that is, "multiplying" short strings. The task doesn't highlight its shortcomings. (strcpy wouldn't be too bad even if the strings were longer, although memcpy might be slightly faster.)

But consider the following silly example (not checked for errors) that does highlight the issue:

      char *next_insert;
      size_t remaining_size;

      void append_memccpy(const char *str)
      {
        char *tmp = memccpy(next_insert, str, '\0', remaining_size); // single pass over str
        if (tmp) {
          --tmp; // move pointer to terminator from one past it
          remaining_size -= tmp - next_insert;
          next_insert = tmp;
        } else { // insufficient size remaining
          str += remaining_size; // first remaining_size bytes are already copied
          allocate_more();
          append_memccpy(str);
        }
      }

      void append_strcpy(const char *str)
      {
        size_t len = strlen(str); // first pass over str
        if (len + 1 < remaining_size) {
          strcpy(next_insert, str); // second pass over str
          remaining_size -= len;
          next_insert += len;
        } else {
          allocate_more();
          append_strcpy(str);
        }
      }

Now, even though the latter version is extra silly (just to resemble the former more), it doesn't change the fact that with strcpy, we have to process each byte in _str_ twice. If _str_ is long enough, that might not be exactly free.

<comment><USER20> Thank you for the reply. I did think about the significance of the length of the string, but I was too lazy to benchmark that. Perhaps another time. Theoretically, for the reasons you mentioned, _memccpy_ should perform better on larger strings, but I am not sure if that really is the case in practice (slow implementation of _memccpy_ , lack of compiler optimizations, etc.), and it seems like that "stick to _memccpy_ " is not an universal rule (obviously). :D

<comment><USER21> Note that I mentioned the ordinary memcpy (with a single c) there briefly. memccpy should under no circumstances be faster than strcpy for "string multiplying", as it holds no advantages over it in that use.

<comment><USER20> Ouch, my mistake.

In any case, could we sum it up? In what cases should _memccpy_ be used over, say, _str{n,l}cpy_ , or even _memcpy_ , and is it in conflict with the article's recommendation or its statement on performance regarding _memccpy_ vs. the alternatives?

</comment></comment></comment></comment></comment></comment></comment><comment><USER22> > The committee chose to adopt memccpy but rejected the remaining proposals.

Is that the case? Reading the updated standard draft[0] they also included strdup and strndup. May be they rejected first, then chose to add later.

[0] [http://www.open- std.org/jtc1/sc22/wg14/www/docs/n2385.pdf](http://www.open- std.org/jtc1/sc22/wg14/www/docs/n2385.pdf)

</comment><comment><USER23> Why not abandon \0-terminated string and pass the length of strings as an additional parameter?

<comment><USER24> [https://stackoverflow.com/questions/25068903/what-are- pascal...](https://stackoverflow.com/questions/25068903/what-are-pascal- strings)

<comment><USER23> Pascal strings prefix the string with the length. What I'm arguing for is more like fat pointers, where the length is stored at the same location as the pointer. Something that is already standard to do in C for binary data.

</comment></comment></comment><comment><USER25> Efficiency looks past current deficiency.

We have the empty string: "\0"

We have the null string: NULL

There is no concept of an INVALID string, as float has NAN.

This would be the result of trying to copy a string to a buffer that is too small.

Or sprintf() into a small buffer.

Or a raw string parsed as UTF-8 and is invalid.

Correctness over efficiency.

<comment><USER26> I'd argue that an invalid string concept would be neither correct nor efficient. Why should all code that deals with strings carry the burden of fallibility of a subset of string functions?

You've mentioned NaN propagation in another comment and I think that's a perfect example of the problem with this approach. Sorting a vector of arbitrary floats is a notoriously thorny problem because any float could be NaN, and as NaN is incomparable to any other float, there is no total ordering of floats. There is no general solution to this problem that doesn't involve making assumptions that could be faulty for some applications.

<comment><USER25> Please support your argument against correctness by providing an example where an INVALID string as input to a suitable modified generic string function would result in a valid string.

<comment><USER27> What is length of an invalid string? What is the length of the concatenation of two invalid strings?

There are sensible answers. But they are weird.

<comment><USER25> Is it more sensible to cat 2 strings, but cut off the second one, then pass off the result as valid?

I would say let an INVALID string be length 0. Then accept that catting a valid and invalid string would result in a shorter length.

Which one do you think is safer?

<comment><USER27> I would expect an invalid string to have an invalid length. For integer-valued lengths you'd have to use a negative number to differentiate from a valid, empty string. But then the sum of the invalid-string lengths differs from the length of the concatenated invalid strings. Which is wonky.

<comment><USER25> Safe string manipulation never exceeds the bounds of the buffer. So negative values are dangerous, as all as any additions that would exceed the maximum size.

Negative lengths are not compatible with unsigned representation.

A system implementing invalid string values must choose a text encoding such as UTF-8 that supports the concept of an invalid character. Null termination is too flexible. As such is simple length prepending.

</comment></comment></comment></comment></comment></comment></comment><comment><USER28> That web page's color choices have made it very difficult to read. I don't know who thought putting light grey text on white was a good idea. I had to copy and paste the text to a text editor in order to read it.

<comment><USER29> I usually just press Ctrl+A to select all in these situations to make the text readable.

</comment></comment><comment><USER30> Does every org have their own C string library or does it just feel like it?

<comment><USER8> The last job I had working in C didn't--we leaned heavily on libraries for stuff like strings, logging, hashtables, and serialization. Implementing that stuff yourself is either a big timesink, or just asking for bugs and security issues.

</comment></comment><comment> lota-putty OT: Is there any API out there that implements say a length* prefix in all C strings?

* 2 or 4 octets size

<comment><USER31> What you're talking about typically goes by the name of "pascal strings", and while they're possible to do, C's string literals are not compatible with them, so nobody does it.

<comment><USER32> It is certainly possible to declare Pascal string literals with not much hassle: [https://stackoverflow.com/questions/7648947/declaring- pascal...](https://stackoverflow.com/questions/7648947/declaring-pascal-style- strings-in-c)

One of the answers states that GCC and Clang do have support for Pascal strings.

Probably these strings do not work as (well) in #defines, i.e. they don't concat like regular literals.

</comment></comment></comment><comment><USER33> Obligatory sidenote on website itself rather than content: please don't set such a low contrast between font color, choice, and background color. I had to copy/paste this article to read it.

<comment><USER34> Use the developer tool to inspect CSS.

1\. Uncheck

        article .entry-content {
            color: #646464;
        }

And a new CSS color rules appears.

2\. Uncheck

        body {
            color: #333;
        }

Done!

I used to think it's ridiculous to manipulate a webpage like this manually, but now I believe: if it's helpful for your for an one-time browsing on a broken webpage, why not?</comment></comment>


Harvard Medical School in Ethics Quandary - <AUTHOR> http://www.nytimes.com/2009/03/03/business/03medschool.html

<comment><USER2> I understand the dilemma and I definitely believe apparent conflicts of interest should be fully transparent.

With that said, I don't believe that issue is just held to medical schools.

At Florida, all of our faculty's salaries are fully disclosed online. I'm not sure if its a UF thing or a Florida public school thing. Anyways, any student can easily lookup how much a certain faculty member is getting paid as well as where their funds are coming from.

To illustrate a similar ethical dilemma, our group was approached by the military to research explosives detection technologies. My professor is a native German and lived in Germany during WWII, and as a result he is an extreme pacifist. Therefore, we have not taken a dime of military funding because we have no idea how the technology might be used after a transfer. It was a difficult decision because in academia a steady cash flow is hugely important, and the military had deep pockets. Instead, we sought to apply for the more competitive NSF funding because our interests were purely scientific and we wanted to keep it that way.

All graduate students should be cognizant of this subtle detail. In most cases it probably doesn't matter because money is money, but when you present your work you want to appear as unbiased as possible.</comment>


Vim rendered on a cube for no reason - <AUTHOR> https://github.com/oakes/vim_cubed <comment><USER2> "I think that it's extraordinarily important that we in computer science keep fun in computing. When it started out it was an awful lot of fun. Of course the paying customers got shafted every now and then and after a while we began to take their complaints seriously. We began to feel as if we really were responsible for the successful error-free perfect use of these machines. I don't think we are. I think we're responsible for stretching them setting them off in new directions and keeping fun in the house."

\- Alan J. Perlis

<comment><USER3> "How dare you insinuate that my latest amateur radio transceiver firmware is capable of loading a working copy of Contra for the NES!"

-People who give me hope

[https://www.youtube.com/watch?v=VBE- BQNaCh4](https://www.youtube.com/watch?v=VBE-BQNaCh4)

<comment><USER4> I've been trying to change my MacBook startup chime to the Contra intro sound for quite a while now...

<comment><USER5> Dang didn't know I wanted this. Would be real cool to get the SEGA startup from the Megadrive.

</comment></comment></comment></comment><comment><USER6> From the Q&A:

      How do i stop the cube from spinning

      no

<comment> yjftsjthsd-h Really, the whole FAQ is gold.

<comment><USER7> It was a wonderful chaser to [https://xkcd.com/2287/](https://xkcd.com/2287/) , which I encountered minutes before.

Humans are good.

<comment><USER8> I suspect that cartoon implies a deep and chilling insight. COVID-19, or HIV, people notice. But does that mean we notice everything? The greatest vulnerability of pathogens is our brains, so wouldn't that mean strong evolutionary pressure to mess with our brains in such a way that we don't notice we're ill? How much of human social evolution is driven by that?

<comment><USER9> Something like [https://en.wikipedia.org/wiki/Toxoplasma_gondii](https://en.wikipedia.org/wiki/Toxoplasma_gondii) ?

</comment></comment></comment></comment></comment><comment><USER10> The issues are great, but especially [https://github.com/oakes/vim_cubed/issues/1](https://github.com/oakes/vim_cubed/issues/1)

<comment><USER11> Oh man - that is the best first post. The issues are fantastic.

</comment></comment><comment><USER12> This is awesome. The best kind of programming: doing something for the fun of it.

Also, what is Nim? How popular is it? What popular products is it used in?

Would it be a useful language for a python developer to learn? I have a friend who is a python dev and he has lamented that he'd like to learn something else. Should I recommend nim? Is it good for numerical analysis?

<comment><USER13> Nim is a relatively small programming language that uses a Pythonic style of syntax. It adds some features that make it better suited to systems development, like type safety and better performance. It can be compiled using a few backends, to eg C or JavaScript.

Nim recently hit 1.0 and has grown a lot of the years, but it still isn't particularly common to see in industry. You can see some Nim related projects on GitHub: [https://github.com/topics/nim](https://github.com/topics/nim)

I used it to write a few things/just play around with in the pre-1.0 days, and found it quite nice to write and easy to read.

Regarding your question about numerical analysis and Python, this post touches on using Nim for tasks that you might reach for numpy for: [http://rnduja.github.io/2015/10/21/scientific- nim/](http://rnduja.github.io/2015/10/21/scientific-nim/)

This one has a brief comparison of Nim and Python + numpy: [https://narimiran.github.io/2018/05/10/python-numpy- nim.html](https://narimiran.github.io/2018/05/10/python-numpy-nim.html)

Note that both are for pre-1.0 Nim.

Nim's site: [https://nim-lang.org/](https://nim-lang.org/)

<comment><USER14> What are Nim's compile times like? I write a lot of C++, and by far my biggest issue is compile times for large projects. I'd love a systems language that had decent compile times for template-heavy code.

<comment><USER15> As girvo mentioned, compile times are really fast. Might not be as fast if you're heavy user of metaprogramming but it's still really good.

For example see: [https://github.com/mratsim/Arraymancer](https://github.com/mratsim/Arraymancer) in the README it mentions:

> Note: While Nim is compiled and does not offer an interactive REPL yet (like > Jupyter), it allows much faster prototyping than C++ due to extremely fast > compilation times. Arraymancer compiles in about 5 seconds on my dual-core > MacBook.

</comment></comment></comment></comment><comment><USER16> Funny thing is, I think this is just about as useful as every attempt I've ever seen (real or Hollywood) to add value to GUI by adding 3D gfx...

<comment><USER17> I actually really liked the 3d view in firefox ([https://developer.mozilla.org/en- US/docs/Tools/3D_View](https://developer.mozilla.org/en- US/docs/Tools/3D_View))

A lot of people said it was silly, and I think IIRC the help pages for it used to have cheeky comments like "Why? Because we can." There's probably a good reason it was deprecated, but I thought it was useful for debugging my often deeply nested DOM layers.

<comment><USER18> I wanted to try this out, and the closest thing I found is this bookmarklet for Chrome:

[https://github.com/chrisprice/explodz](https://github.com/chrisprice/explodz)

It appears to still work and it even sort-of works on Firefox except for the mouse-click feature that shows the sides. Clearly not as polished as the old Firefox feature though.

</comment></comment></comment><comment><USER19> Now we just need to render Emacs onto a tesseract.

<comment><USER20> Is that what the `C-x 4` keybinding is _really_ for? /s

</comment></comment><comment><USER21> In the 2000s we used to do this, but with the proverbial Linux Desktop.

<comment><USER22> Whatever happened to the promise of cube desktops with wobbly windows?

<comment><USER23> I am using Wobbly Windows right now in KDE. Desktop Cube works too but I don't like it (I use 16 desktops instead of 4 :).

When I have to use Windows every once in a while I am viscerally disgusted by the lack of wobbly windows. Moving windows just feels wrong - very, very wrong. Takes a second to realize they're not wobbling. To me it makes the computer seem less robotic and more natural in a way, I guess. Like haptic feedback on smartphones when you tap stuff.

<comment><USER24> Exactly what I told my sister few months ago. The windows just feel stiff and unnatural.

</comment></comment></comment></comment><comment><USER25> And here I was making fun of the Swordfish hack scene [1]. Turns out he was just assembling the crypto algorithm using vim.

[1]: [https://www.youtube.com/watch?v=u1Ds9CeG- VY](https://www.youtube.com/watch?v=u1Ds9CeG-VY)

</comment><comment><USER26> Can someone make this work in VR and multiplayer? I can imagine it'd increase productivity if you could fly to someone's cube and collaborate by doing Minority Report gestures.

<comment><USER27> Yeah if people stopping by my desk in an open office is good then people dropping in to my desktop environment must be better.

<comment><USER26> It's basically the remote work equivalent of asking for TPS Reports

</comment></comment></comment><comment><USER28> Judging by the feature requests in the open issues, I'd say we are witnessing the inception of the text editor of the century.

</comment><comment><USER29> [https://github.com/paranim/paravim](https://github.com/paranim/paravim) \- A Vim-based editor for Nim [https://sekao.net/paravim/nim/](https://sekao.net/paravim/nim/)

[https://github.com/paranim/pvim](https://github.com/paranim/pvim) \- A Vim- based editor for Nim [https://sekao.net/paravim/nim/](https://sekao.net/paravim/nim/)

So what the fuck is what? paranim? paravim? pvim?

</comment><comment><USER30> Cool. Looking forward to seeing Vim on a torus some day.

</comment><comment><USER31> Remembers me an effect I wrote (in text mode) for neercs, a GNU screen clone [https://www.youtube.com/watch?v=sQr42LjaNCY](https://www.youtube.com/watch?v=sQr42LjaNCY)

</comment><comment><USER32> This is weird combo of "movie hacking" and "real hacking".

</comment><comment><USER33> Technically you're _still_ using it in "two dimensions", only the topology of S^2 requires an embedding dimension 3.

You're still a pleb, only "richer".

</comment><comment><USER34> Perfect for slowing down those pesky 10x developers.

</comment><comment><USER35> Thanks for the comic relief of the day; sure needed it. I like your goofy sense of humor. Please keep doing fun stuff like this.

</comment><comment><USER36> When Compiz came out about several years ago this kind of thing was all the rage.

</comment><comment><USER37> Ah, classic BeOS, love it!

</comment><comment><USER38> Is this the lockdown speaking? Thanks, I needed something light.

</comment><comment><USER39> There's also vim^4 which is great for writing in Forth

</comment><comment><USER40> This is like Hacker's computer in movies!

</comment><comment><USER41> VIM BORG CUBE!

<comment><USER42> :set resistance=futile

</comment></comment><comment><USER43> it's funny.

</comment><comment><USER44> Well done

</comment><comment><USER45> whats the cmd to exit vim3?

<comment><USER46> One of the issues suggests holding down your device's power button.

</comment></comment><comment><USER47> Almost as useless as this comment.

</comment><comment><USER48> This makes it to the front page? Guess it's a slow day on HN land. Is everyone else waiting for the April job threads too?

<comment><USER49> I quite appreciate these kinds of posts. Fun and silly, yet make you think about the way computers work outside the box.

<comment><USER50> Outside the box... Oh thanks...</comment></comment></comment>


We Need Hardware Traps for Integer Overflow (2014) - <AUTHOR> http://blog.regehr.org/archives/1154 <comment><USER2> If this will see the light of day, I expect that iOS will have it first. Reasons? Apple controls its own CPUs, and Swift's 'normal' operators trap on overflow.

I also think that hardware support for tagged pointers ([https://en.m.wikipedia.org/wiki/Tagged_pointer#Examples](https://en.m.wikipedia.org/wiki/Tagged_pointer#Examples)) may be worthwhile for iOS, but that need may decrease if ther will be a gradual move from Onjective-C to Swift.

</comment><comment><USER3> The Mill CPU that Mill Computing is developing, has signalling integer instructions. In fact, each integer operation has four modes that one can choose from: ignore, saturate, excepting and widening. The widening mode has a result that is double-wide as the operands width and hence never overflows.

The Mill CPU is not available yet so have a little patience.</comment>


Read Write Files in Python - <AUTHOR> https://www.techbeamers.com/read-write-file-in-python/ <comment><USER2> No mention of the most commonly used context manager?</comment>


Poaching Etiquette: The Right Way To Take Tech Talent - <AUTHOR> http://www.betabeat.com/2011/11/17/poaching-etiquette-how-to-love-thy-startup-neighbor-while-coveting-their-devs

<comment><USER2> These articles frustrate me because nobody asks why the engineers are 'willing' to get poached. It always boils down to a few reasons:

\- The company's prospects and projects are limited. Shopping comparison was cool in 2003, but it's 2011, and you have an aging flagship product with limited growth and a bunch of half-assed initiatives that never go anywhere because there's too much red tape to actually produce code and the executives are too busy getting fired every six months have any consistency with strategy.

But if you're getting tech talent "poached" in that case, you're probably getting all your talent poached, so let's talk about the other scenario.

\- The engineer's prospects are limited. So few technology companies have any sort of individual contributor advancement path. A star performing sales guy goes from junior sales associate, sales associate, senior sales associate, junior manager, senior manager, etc every 6-12 months, with commissions and bonuses for strong performance.

The star engineer goes from "software engineer" to "senior software engineer" after like, 3-5 years, and then what? Either you figure out a way to get kicked into some sort of manager role or you just kind of hang around getting a pat on the back and a 6% raise every year until some company swoops in and "poaches" you with a 20% raise, which naturally seems astronomical by perspective.

Almost every manager I've had, I've had some conversation like this: "You have to give Joe a raise, and a BIG one. I know he started here out of college, but he's been here 3 years now. Because of his talent and domain expertise, he is easily more productive than any theoretical 'senior engineer' we could hire. Even if he's relatively happy, if you don't give him a raise, it's going to be way too easy for some recruiter to throw out salary numbers that will at least pique his interest."

And instead of bumping Joe's pay by 30% (which would still probably be less than market rates), he gets "poached," and now we have to hire some "senior engineer" at 200% the salary who tries to convince us to rewrite everything in Java for six months until he gets fired.

<comment><USER3> There's also Joe's impression of how much his employer values him: If Joe is perfectly happy working at 10k/year, but you're paying new people just out of college 20k/year it can cause Joe to start looking for ways to get poached.(for example)

<comment><USER4> This happens surprisingly more often than you think.

</comment></comment></comment><comment><USER5> Anti-poaching sentiment is an attempt by executives to drive down the status, pay, and perks of talent.

Programmers' and technicians' status and benefits are already artificially low due to lack of a professional licensing or guild system (thank goodness) and poor negotiating skills rampent in the profession (bad). Execs who pretend to value programmers and participate in anti-poaching schemes are stabbing their workers in the back.

Anti-poaching agreements, formal or implicit, are also illegal everywhere in the USA and most developed countries. They violate the Sherman Anti-Trust Act and its successors. These interviewees who brag on about how they're respecting their investors, partners, and friends by not poaching are admitting to a federal crime. The US Attorney from New York should be investigating.

Of course, the execs and our culture have succeeded in driving down the status of programmers enough that nobody much cares about crimes committed against them. Maybe they do need a guild.

</comment><comment><USER6> I don't like losing good employees, but when one tells me he's thinking of going somewhere, whether it's a competitor, school. different industry, whatever, I don't take it all personally. Sooner or later, I do the same thing. And that's the reason my people will tell me when they're considering something else. P.S. My rule of girlfriends and bosses: You learn more about them when you leave than at any other time.

<comment><USER7> "You learn more about them when you leave than at any other time."

How so? (honestly, I'm dense)

<comment><USER8> At the end of the relationship, people stop doing things to keep the relationship afloat. They start to act like they would around anybody else. It's a learning experience.

</comment></comment></comment><comment><USER9> It's funny, "poaching" in this context refers to hiring away talent from one company to the next. As if the talent is the property of the company.

I prefer to think of "poaching" in more appropriate terms -- supply and demand. Limited supply, demand increasing, and the market bears what it will.

Anyone who complains about this environment needs to consider another line of work.

<comment><USER10> > _"I prefer to think of "poaching" in more appropriate terms -- supply and > demand."_

Exactly. It isn't poaching, it's _competing_. I wouldn't want to work at a place that thought of talent as property to be "poached".

<comment><USER11> It's just a metaphorical term of art. Most people wouldn't want to work with "garbage collection" every day, but of course many programmers do.

<comment><USER10> Yeah, it's a metaphor that analogizes people and property.

I wouldn't have any qualms about working with, say, purchasing managers who talked about "poaching" component orders from one another, because they'd be talking about property as property.

Do you really not see the difference?

<comment><USER11> I think you're really stretching here. The core issue is whether companies value their employees--that comes through in how the employees actually get treated, not the use of one word vs. another.

<comment><USER10> I think it's pretty hard to truly value and treat someone well if you think and speak of them as property.

</comment></comment></comment></comment></comment></comment><comment><USER12> Love the entitlement attitude of some managers, and the weasel words. As if it's some sort of moral failure to get paid market rates.

Employee leaves to get paid their market rate = evil poaching! Management firing everyone to replace with lower cost workers = a necessary market adjustment

<comment><USER13> It may be my limited understanding, but poaching is when a company actively targets a particular person (say by calling them) rather than putting out a general call for CS grads with 10 years Rails experience.

But, again, I may be wrong.

<comment><USER14> Yes but if the employee is getting more at the new job then they were by definition underutilized and/or underpaid at the job they were "poached" from. Collusion amongst employers artificially limits employee earning power and cripples the invisible hand of labor economics.

Top flight employees should always be working at the edge of their abilities for commensurate pay. Anything less is an inefficient allocation of capital that hurts the industry as a whole.

</comment></comment></comment><comment><USER15> Recruiting has become the most sought after skill among founders and one of the things companies look for as extra value a VC can bring.

Not sure there is a good way poach, aside from being a good sport and not rubbing it in. That and following through on the promises you make (looking at you Zynga).

<comment><USER16> If someone else can offer one of my guys a better deal than what I can (and by deal I don't just mean money), then I send them off with my good wishes.

I realise this comes across as naive, and I certainly don't want to minimize the huge disruption someone leaving a busy small team can cause, but if you start seeing people as property and laying your ego on the line every time you have turnover, you are going to have a miserable life.

[Disclaimer: I don't work in startups but I do work somewhere where it typically takes 9 months to re-hire, so don't think I don't feel the pain]

</comment></comment><comment><USER17> As an aside, there can be legal consequences to the "no-poaching agreements" mentioned in the OP's article:

[http://gigaom.com/2010/09/24/doj-settles-with-apple-adobe- go...](http://gigaom.com/2010/09/24/doj-settles-with-apple-adobe-google-over- hiring-collusion-charges/)

</comment><comment><USER18> There are downsides to informal "no poaching" agreements. After I left one e-company, I applied at another, and later learned I wouldn't be interviewed because of the previous company on my resume. The first company was major client of the second, and they didn't want to have even the appearance of "poaching."

<comment><USER19> Did they actually tell you this? I would think this must violate some sort of anti-discrimination law

<comment><USER18> No, the company's representatives did not formally/explicitly say it. My resume just went into a black hole, where I couldn't get a response from anyone.

Later, some colleagues who worked there mentioned (after I'd found a job elsewhere) that it's something of an unspoken policy between the two companies, and was likely the cause of my experience.

</comment></comment></comment><comment><USER20> Poaching is the modern developers equivalent of "climbing the ladder" or getting a promotion. There is a limited ceiling for someone who is dedicated to their craft. They can go into management and "lose half their brain". They can go out on their own, but being a founder isn't for everyone.

There is no real loyalty. Companies will lay off their employees when money is a concern. Employees will leave their companies when they can make more money elsewhere. This is business. It's not personal, right?

</comment><comment><USER21> My father used to tell me stories about when he was a manager within a factory (a good 30-40 years ago... he is 70 next year) essentially the employment rate for tradesmen was at maximum and essentially the only way to hire new help was to go out and offer someone who already had a job more cash/perks I don't think its wrong in any way to poach. its just a change of how the employment market will work when there are not enough skilled labor around to fill the needs of everyone.</comment>


The American Who Designed the PlayStation 4 and Remade Sony - <AUTHOR> http://www.wired.com/gamelife/2013/11/playstation-4/all/ <comment><USER2> I'm seeing a pattern, a cycle between hubris and humility.

When Nintendo ruled, Sony broke in by courting game developers. Then, they became arrogant, and made the best hardware they could, they was difficult to use. Thus, Microsoft won, simply because it was easier for developers. It was then amazing to see how arrogant they had become with the xboxone trying to squeeze everyone, in every way - similar to how they removed the ability to cancel xbox live online.

What Microsoft didn't realize is that _they_ didn't win - Sony lost, by shooting themselves in the foot. But in this generation, if PS4 is easy to develop for, cheaper, more powerful, and not trying to squeeze every cent and control every aspect... things will be different.

Of course, Microsoft will see their mistake and adjust (as they've done many times). But while they can drop prices and relax controls, it may be difficult to make their console more powerful. Also, next year, mobile devices should reach GPU parity with last gen consoles... and with their faster iteration cycle, match PS4/xboxone three years after that. (unlike CPUs, GPUs scale really well).

<comment><USER3> I get what you're saying, but Microsoft never won any console race [http://www.geekwire.com/2013/xbox-360-wii-ps3-won-console- ge...](http://www.geekwire.com/2013/xbox-360-wii-ps3-won-console-generation/)

<comment><USER4> Naive interpretations of the current console generation will lead to incorrect conclusions.

Microsoft unequivocally won the 360/ps3/wii console generation. Not because they shipped more consoles, no console maker actually makes the majority of their profit from raw console shipments, it's a very misleading figure. What matters more are sales of games and DLC and subscriptions to services. In those measures the 360 has been trouncing every other console maker. People who own 360s spend more time playing the console, they spend more money buying physical games, and they spend more money buying DLC and subscribing to xbox live gold. Microsoft does more business on higher margin items than other console makers.

The Wii made ok money for Nintendo but the sales dropped off really fast, and people didn't end up playing it much, or buying many games for it. The PS3 took a long time to reach a state of maturity where there was a sufficient stock of good games on the console to actually justify owning one. And eventually the PS3 managed to get to a state where it was actually doing well. But from a business perspective no matter how much better it was doing the 360 continued to outpace it (in game sales especially). These are some of the major reasons why there even is a new console generation this year, Nintendo and Sony need to put themselves on a new footing in order to have a chance of growing their market share.

<comment><USER5> Why sales matter and not profits? If I go and buy Ferrari F360s for $200K then turn around and sell them for $10K I can probably get a lot of sales yet from the business perspective I am going to be in a pretty bad state.

Has MS turned in any profit from their whole Xbox affair? There had been various estimates around but I've never seen ones claiming significant profits, the best ones I'd seen claimed it broke even. They had shown some minor profit on their entertainment divisions in some quarters but the RROD alone costs them $1B not counting minor stuff like purchasing and running Rare or paying for "exclusivity".

<comment><USER4> If profit figures were available we wouldn't be having this discussion, because the answer would be obvious. But they're not. Nintendo's figures are the most available (since gaming is the majority of their business and they are a public company), but the least relevant because we know they've been struggling. Sony has had reduced profitability and losses over the last few years. The interesting thing is how difficult it is to get numbers out of Microsoft. They fold the Xbox and console gaming part of the company in with web-based gaming and the windows phone (and formerly zune) part of the company, which muddies the waters considerably. Overall though there are many indications that console gaming has been profitable for Microsoft. For example, in 2012 alone xbox live made $1.2 billion in revenue. This is a very high-margin business for MS and that represents about 10% of the entire worldwide video game revenue.

MS has dumped a lot of money into console gaming, but they've built a business that is now generating a lot of revenue in a lot of high margin areas.

<comment><USER5> I think your numbers are way off, the entire worldwide video game revenue is not anywhere around $12B[1]

Also margins are not as high as you seem to imagine, look at any 3d party publisher reports (they are all public corps).

[1] [http://in.reuters.com/article/2013/06/10/gameshow-e- idINDEE9...](http://in.reuters.com/article/2013/06/10/gameshow-e- idINDEE9590DW20130610)

</comment></comment></comment></comment></comment></comment><comment><USER6> The Cerny Method sounds remarkably like the Lean Startup Method, but apparently pre-dates it quite significantly.

<comment><USER7> I had the exact same thoughts while reading the article. Cerny created MVPs of games, got feedback and would pivot/change based on user feedback. And he did this in the mid 90's!!

<comment><USER8> It's not a MVP if you have to build the whole game engine, but it's simular I guess.

</comment></comment></comment><comment><USER9> This was a good read, and the narrative between Sony's launch and Microsoft's launch has the feel of some pretty classic hero's journey stuff in it.

The interesting upstart this time seems to be the SteamBox.

</comment><comment><USER10> The PS4 may well make for a better video game machine and more profit for Sony, but it's too bad the very interesting and powerful cell processor concept will be relegated to the dustbin.

<comment><USER11> The Cell design was interesting, but it was obvious that chip multiprocessors would win. The argument is similar to why x86 continues to prevail vs RISC and VLIW: supporting x86 is only a modest constant factor in transistor count but preserves access to the existing software ecosystem. The latter trumps the pennies per part the x86 decoders add.

Likewise with chip multiprocessors vs systolic arrays: making a core fully general and with proper cache coherant memory access isn't that expensive in transistors, and allows you to leverage existing multi-threaded code.

Systolic arrays still have a future in true embeded devices: radar processing is a good example.

Oh, and before you point to the AMD architecture as being Cell-like, it's not at all. Unified virtual memory instead of Cell's complex 2 level store. Cell requires the CPU to manage DMA's to the APU's, on Fusion you can just pass a pointer. CPU and APU instruction sets are entirely decoupled on Fusion. APU supports thread pre-emption.

In any case, the lesson here is obvious: design hardware in opposition to the existing software ecosystem in your industry, and you'll make something that is academically interesting but struggles to deliver value to end products.

<comment><USER4> The x86 vs RISC debate is a perfect example of how technological advances can confound seemingly simple tradeoffs. There's simply no such thing as a CISC processor anymore. All "x86" processors have RISC internals and use micro-op translation to present an x86 ISA at a software level. As you point out, the same sort of dynamics play out at every level. There's only so much advantage that simplified core designs get you, since the overhead for "legacy" support tends to be small.

It'll be interesting to see how Intel's x86 SoC development pans out. With the Atom they weren't really aiming for the SoC market and only recently have they actually bothered to try to do so. Even with their first generation stuff they've produced pretty competitive, to ARM, results, given Intel's research muscle and their FAB capacity it wouldn't be surprising to see a lot more x86-SoC based smartphones and tablets hitting the market in the coming years.

</comment></comment></comment><comment><USER12> I wish more people would care about Sony's record.

They initially officially supported Linux on the Playstation 3, but later decided not only to remove the feature from new models, but reach out through the cloud to _remove the feature from existing consoles_ [1] [2].

This is also the company that put rootkits on CD's [3].

[1] [https://news.ycombinator.com/item?id=5886509](https://news.ycombinator.com/item?id=5886509)

[2] [http://en.wikipedia.org/wiki/Otheros](http://en.wikipedia.org/wiki/Otheros)

[3] [http://en.wikipedia.org/wiki/Sony_BMG_copy_protection_rootki...](http://en.wikipedia.org/wiki/Sony_BMG_copy_protection_rootkit_scandal)

</comment><comment><USER2>
      It makes a lot of sense to just a build a piece of it first — but that piece needs
      to be representative. You can't just hack something together." He calls this
      prototype a "publishable first playable,"

A better explanation of MVP than most.

</comment><comment><USER13> So I'm clueless as I haven't been paying attention to this market since the PS4/XBox360 were released - does the PS4 not run PS3 titles? If so, does it have some emulation or is it new hardware sitting on top of the old Cell design?

<comment><USER8> I don't get this desire for backwards compatibility. Why would you want to play a really old game on a shiny new console?

If you really did, then pick up a used ps3 or 360 for about £50 and get the PS4 later!

<comment><USER14> Says a guy who obviously doesn't have children and who also doesn't own console games :)

I bought my kid the new Lego Batman II for PS3 in March for his birthday. We decided to upgrade to the PS4. He can't play this new game - that was recently released - on the PS4. It's a weird thing to not support backward compatibility IMO. It's a win for the developers/Sony but a loss for consumers. I have to now buy all new games and Lego Star Wars isn't going to be any better on PS4 than on PS3. Your question acts as though there should always be this "evolution" going on but I disagree. I like watching Daffy Duck from the 1940s - I don't like watching the Daffy Duck from the 1980s. Sometimes a game is "really good" and doesn't need revving - it just needs to be made available for the current gen console.

<comment><USER8> Firstly why are you getting rid of your PS3, secondly I have a 360, and a PS2 before that, PSX before etc etc I also have a XBone and PS4 pre ordered.

I trade in all my old games as I never re-play them, if I do it's normally after such a long time that I can download them on my phone or run them emulated as I'm sure will eventlally be possible on the PS4.

Supporting backwards compatibility could result in developers not bothering with the new hardware, soemthing that has happend a bit with the GBAdvanced and DS platforms.

<comment><USER14> Again, "Says the guy who obviously doesn't have children" haha

<comment><USER14> You don't see what difference it makes because you have no context. There are a lot of things I thought/did as a young man with no wife or children that I don't do today now that I have both. I can't tell whether you are being willfully dense (or "captious" as yesterday's word of the day taught us) or you just haven't taken the time to think from someone else's perspective.

<comment><USER8> Try making a valid point rather than saying I'm not considering your point of view.

Or I could just say, "Says a man who's insecure" or some other vague and assumed statement.

</comment></comment></comment></comment></comment></comment></comment><comment><USER15> Unified memory architecture! Should be some cool hybrid cpu/gpu algorithm possibilities. Currently the overhead of copying stuff between the two memories in CUDA prevents any fine-grained cooperation. I wonder how much gpgpu ability is exposed.

</comment><comment><USER16> They should have mentioned the number of titles at launch for xbox one. If ease of making games is such a big deal why aren't there any facts on how far behind their main competitor is.

<comment><USER17> Xbox One only launches with a couple more retail titles. PS4 launches with a dozen or so more PSN titles.

</comment></comment><comment><USER18> I want to know how much Sony payed Wired for that advertism... article.

</comment><comment><USER19> PS4 is just a PC stuck in one configuration, linked to a popular delivery system.

I don't get what the hype is about.

Yes, it's a pretty good configuration at a reasonable price. But that will only be the case for a few months. PCs will catch up very quickly and will become cheaper, and then much cheaper.

As somebody who loves games, I don't see a reason to buy PS4. I'd rather spend a bit more on a PC, and then upgrade it as I go.

The positive thing I see is the PS4 <-> PC game portability. No longer developers need to have to very different engines and codebases. That's why PS4 is a much better option than XBox One in my eyes.

<comment><USER20> > PS4 is just a PC stuck in one configuration, linked to a popular delivery > system.

You've belied the true strength of video game consoles. A single configuration means less testing work and a streamlined experience for consumers. Not everyone is willing to deal with graphics drivers and endless installers.

<comment><USER21> Which also leads to crazy optimization against the stable hardware. Just look at what PS3 and Xbox 360 are pushing out with ~512 MB RAM and 7+ year old hardware. It's pretty incredible.

</comment></comment></comment><comment><USER22> good article...</comment>


Saturated Reconstruction of a Volume of Neocortex - <AUTHOR> http://www.cell.com/cell/abstract/S0092-8674(15)00824-7

<comment><USER2> video abstract: [http://www.cell.com/cms/attachment/2035054472/2050360628/mmc...](http://www.cell.com/cms/attachment/2035054472/2050360628/mmc18.mp4)

</comment><comment><USER3> From the materials and methods:

"An anesthetized adult mouse was perfused transcardially with a fixative solution containing glutaraldehyde, paraformaldehyde, and CaCl2 in cacodylate buffer. The brain was removed and maintained overnight at 4°C in the same fixative solution."

I don't know much about neurobiology. But i know that in two other fields of cell biology - cell motility and vesicle trafficking - something that became clear in the last decade is that the way you fix samples for electron microscopy has a huge impact on what you see. Cells are made of highly dynamic structures that exist in fine-tuned environments; soaking them in formaldehyde and some random buffer salts is pretty much guaranteed to disrupt those environments, and let the structures drift away from the states they have in live cells over the time it takes to fix them, even if it's only fractions of a second.

The gold standard for fixation is now extremely fast freezing, achieved by plunging a sample into liquid nitrogen under very high pressure, so that the water solidifies as a glass rather than growing crystals, which would disrupt structures inside the cell:

[http://www.biotechniques.com/BiotechniquesJournal/2006/Augus...](http://www.biotechniques.com/BiotechniquesJournal/2006/August/High- Pressure-Freezing-Cellular-Tomography-and-Structural-Cell- Biology/biotechniques-40054.html)

In my old field, cell motility, when someone finally tried this, they found that a thing called the lamellipodium, which has been an object of intense study for decades, had a rather different structure to what everyone had thought:

[http://www.ncbi.nlm.nih.gov/pubmed/20418872](http://www.ncbi.nlm.nih.gov/pubmed/20418872)

As a result, it turns out that the prevailing model of how this thing worked was complete fantasy. Since numerous successful professors have built their careers on that model, this discovery has not yet really been taken on board by the field, but it's inevitable that it will.

Which is a very roundabout way of saying that when the authors of this brain paper write:

"For example, by tracing the trajectories of all excitatory axons and noting their juxtapositions, both synaptic and non-synaptic, with every dendritic spine we refute the idea that physical proximity is sufficient to predict synaptic connectivity (the so-called Peters' rule)."

I am skeptical, because they are looking at the positions of the spines and synapses in their formaldehyde-soaked sample, not live tissue, or tissue prepared in such a way as to preserve the structure of live tissue.

Still a cool paper though.</comment>


Understanding the fork system call in Unix - <AUTHOR> http://mohit.athwani.net/unix/understanding-the-fork-system-call-in-unix/ <comment><USER2> Question: What happens (and should happen) if a GUI app forks? Do/should the windows get duplicated? Do/should two apps control the same windows? Is the answer the same/should it be the same regardless of all the underlying stack (X/Wayland/Gnome/KDE/whatever)?

Edit: I really care about the "should" part too, not just what currently happens. I've been trying to think of semantics for forking that could work in these situations but I haven't been able to think of great solutions.

<comment><USER3> No, windows are not duplicated. Yes, two apps control the same windows. Yes, this answer is the same as underlying stack.

That solution is very obivious once you realize it is exactly the same as what happens with the terminal and network connections.

For example, after forking, both processes are still attached to the same terminal (what else can they do? It's not like they can make new terminals - what if it was an ssh connection). They better agree who gets to read/write, or user will get confused - in shell, the parent voluntarily stops accesing terminal until the child is done.

<comment><USER2> It's not clear to me if you can really just solve this like you can with the terminal case. The thing with a terminal is that it's insanely easy to fork streams -- you can just interleave the streams, and even without active cooperation between the processes you still get a behavior that has some semblance of semantic sense. But with a GUI system, you're not just dealing with a pipeline; you're dealing with a state machine. Do you really take a similar approach? When a window receives a message/event, which process responds? If multiple processes respond, which message/event gets sent and which gets discarded? If only one responds, does the same process also get the reply to the reply, or might the fork get the reply instead? You could interleave events randomly here too, but it seems like far less sensible of a solution than with the terminal case.

<comment><USER4> the Answer to most of your questions is that the GUI would quickly break after being forked.

</comment></comment></comment></comment><comment><USER5> It's worth noting that on Linux, the address space itself is copy-on-write, but the page tables _describing_ the address space are nevertheless copied eagerly, and this copying can take significant time. If you're going to be calling execve right after fork, you should be using vfork, not fork.

<comment><USER2> Why don't people just use the standardized posix_spawn() or popen() in the first place? Why fork then exec?

<comment><USER6> posix_spawn (at least in GNU/Linux) is a library function, not a syscall. Under the hood, it calls clone (which, like vfork, avoids copying page tables) and then execve.

The reason fork (or vfork, or clone) and exec need to be separate steps is because you may want to do some stuff in between the two steps. The most obvious example is redirection: when you run "grep foo < bar", the shell needs to set stdin to point to "bar" before it execs "grep".

<comment><USER2> Thanks but why don't people just use the portable posix_spawn when they can (which should be the vast majority of the time)? That it calls clone/execve underneath doesn't really answer my question...

<comment><USER6> As far as I know, there isn't any good reason not to. So indeed people should, if they can.

(IIRC, posix_spawn was introduced relatively recently, so most old software wouldn't use it).

<comment><USER7> I was trying to find a year on it and couldn't, but agree it seems newer.

FWIW, it's not required to be able to run any setup code in the child to do arbitrary setup. For instance, WinNT makes that very hard, but has a larger syscall interface to compensate, so it's actually more general. An alternate design of running all code in the parent can be made work if the kernel supports passing a pid handle to every syscall: [https://lwn.net/Articles/360747/](https://lwn.net/Articles/360747/)

On the other hand, this is perhaps a bit more complex in some ways? or at least just different.

<comment><USER8> > I was trying to find a year on it and couldn't, but agree it seems newer.

[http://man7.org/linux/man- pages/man3/posix_spawn.3.html#CONF...](http://man7.org/linux/man- pages/man3/posix_spawn.3.html#CONFORMING_TO) says POSIX.1-2001, so I'm guessing between 1998 and 2002 (according to [https://en.wikipedia.org/wiki/Single_UNIX_Specification#2001...](https://en.wikipedia.org/wiki/Single_UNIX_Specification#2001:_Single_UNIX_Specification_version_3,_POSIX:2001) it started development in 1998 and was released in 2002). That man page also says "since glibc 2.2", which according to Wikipedia was released November 2000.

</comment></comment></comment></comment></comment></comment></comment><comment><USER9> > So "cin", "cout" and "cerr" also known as stdin, stdout and stderr are > shared.

Note that these are different things: std::cin is a std::istream, std::cout and std::cerr are std::ostreams, and stdin, stdout, and stderr are FILE *s.

<comment><USER4> They clearly mean in a practical sense they have the same purpose, not that they're literally aliases.

</comment></comment><comment><USER10> Please don't use this code. fork can fail, and this doesn't handle it.

<comment><USER11> I wouldn't criticize anyone for posting code snippets for educational purposes without confounding the learner with all of the error checking. Pedagogy vs pedantry.

<comment><USER12> I think the number of people who will copy-paste from a website and not revisit it may be alarming. It is on those who publish snippets to make these things explicit. Maybe the following is enough:

        if (pid < 0) { /* TODO: handle error */ }

Reading the actual code I doubt it's just an oversight, the coding style used seems to lend strongly towards not thinking an error is possible:

        if ((pid = fork()) == 0)
        { //Child
            longTask();
        } else {
            children[i] = pid;
        }

<comment><USER11> > the coding style used seems to lend strongly towards not thinking an error > is possible

So does every tutorial which doesn't check the return from printf or check for errors from cout. Did you notice that the parent and child are both writing to the same file descriptor? Maybe the writer should add some words and tests in his code about the inherent race condition there. A true pedant would push this even further and teach their audience how to eliminate this problem with cross process mutexes or semaphores. Better be sure to check the error codes on those calls too.

I know arguing with a pedant is like wrestling with a pig, but honestly I'm more offended by the "#define N 2" than by the lack of error checking.

</comment></comment></comment></comment><comment><USER13> archive.org mirror: [https://web.archive.org/web/20190519000123/http://mohit.athw...](https://web.archive.org/web/20190519000123/http://mohit.athwani.net/unix/understanding- the-fork-system-call-in-unix/)

<comment><USER14> Thanks, the site itself can no longer fork ;)

<comment><USER15> Stick a fork in it. It's done.

</comment></comment></comment><comment><USER15> While we're on the topic of calling fork and overloading servers to the point that they can't establish database connections or serve web pages, I'd like to point out that forking another process is an astronomically EXPENSIVE and WASTEFUL way of performing simple arithmetic and string manipulation.

Please stop wasting electricity and time by writing shell scripts that fork processes to do ridiculously simple things like calling "bc" to add two numbers or "sed" to perform simple string manipulation, since your computer has a "mul" instruction that doesn't require millions of instructions and bytes of memory and disk accesses to perform.

It's like using Bitcoin to pay for a stick of gum.

[https://www.quora.com/How-much-energy-does-it-take-to- make-a...](https://www.quora.com/How-much-energy-does-it-take-to-make-a- Bitcoin-transaction)

>According to Digiconmist, each bitcoin transaction took 215 kWh. Whereas an average Indian household consume : 90 kWh per month. It sums up that, each bitcoin consumption can power a average indian household for 2.5 months probably. The average electricity cost in India is 5 rupees per kwh.

It's like rolling coal because you want to trigger the libs.

[https://www.youtube.com/watch?v=fkmLf5OXxz0](https://www.youtube.com/watch?v=fkmLf5OXxz0)

Stop and think before you write that shell script. It's not going to take you any more time to write it in Python, and then you won't be so shocked and surprised and totally fucked when you realize later that you need to add more features and make it more complicated than you originally though it would need to be in the first place.

It just boggles my mind that some people have such a hard time understanding how spectacularly inefficient shell scripts are, on top of how horrible to write, read, understand and maintain they are.

[https://news.ycombinator.com/item?id=19886164](https://news.ycombinator.com/item?id=19886164)

<comment><USER16> For many things shell scripts are the easiest and most expressive way to write them. And probably you don't know that human resources are more expensive than cpu cycles.

Sure, I love python, but if I want to find and filter some files nothing is easier to write than bash, so it's possible to have a quite big bash script even doing a good job and being well readable.

I'm honestly a little shocked that this doesn't seem to be common knowledge anymore and your post got upvoted so high.

My main language is Python btw.

<comment><USER15> What if one of your file names has a space in it? Most bash scripts will crash when that happens.

Please don't tell me never to use spaces in file names.

How many human resources are required to track down and fix why a bash script suddenly starts failing mysteriously, years after it was written, when somebody mistakenly dares to use a space in a file name?

That kind of problem never happens with Python scripts (including problems with file names including other punctuation and unicode characters), because Python simply represents file names as strings.

For a scripting language that was indented to manipulate file names all the time, bash sure fucked up big time.

[https://www.linuxjournal.com/article/10954](https://www.linuxjournal.com/article/10954)

>Work the Shell - Dealing with Spaces in Filenames

>[...] I've outlined three possible solution paths herein: modifying the IFS value, ensuring that you always quote filenames where referenced, and rewriting filenames internally to replace spaces with unlikely character sequences, reversing it on your way out of the script.

>By the way, have you ever tried using the find|xargs pair with filenames that have spaces? It's sufficiently complicated that modern versions of these two commands have special arguments to denote that spaces might appear as part of the filenames: find -print and xargs -0 (and typically, they're not the same flags, but that's another story).

>During the years I've been writing this column, I've more than once tripped up on this particular problem and received e-mail messages from readers sharing how a sample script tosses up its bits when a file with a space in its name appears. They're right.

>My defensive reaction is "dude, don't use spaces in filenames", but that's not really a good long-term solution, is it?

>What I'd like to do instead is open this up for discussion on the Linux Journal discussion boards: how do you solve this problem within your scripts? Or, do you just religiously avoid using spaces in your filenames?

>Dave Taylor has been hacking shell scripts for a really long time, 30 years. He's the author of the popular Wicked Cool Shell Scripts and can be found on Twitter as @DaveTaylor and more generally at www.DaveTaylorOnline.com.

(Dave wrote that 8 years ago, and there are still zero comments on it. Nobody has a good solution! Bash is just permanently fucked when it comes to file names.)

<comment><USER17> bash has handled spaces in filenames easily for a long time:

        #!/bin/bash
        # run this scri0t with 0 or more filename args
        for file in "$@" ; do
            do_something_with "${filename}"
        done

> Nobody has a good solution! Bash is just permanently fucked when it comes to > file name

From the man page bash(1):

        Special Parameters
           @  Expands to the positional parameters, starting from one.
              When the expansion occurs within double quotes,
              each parameter expands to a separate word.
              That is, "$@" is equivalent to "$1" "$2" ...

<comment><USER18> It's _possible_ to write bash that handles spaces in filenames properly, but it's really hard to do it consistently. Unless you test it then you've probably got it wrong.

Most people don't test their bash on spaces. Look at the dismissive commenter above who just things "nah why would people use spaces in filenames?". Do you think he quotes everything properly? No chance.

CMake is also really bad about this. Although it is arguable slightly better because it uses semicolons as list delimiters instead of spaces, and semicolons in filenames are going to be very uncommon. I would expect there isn't a single CMake project out there that works if you build it in a path containing a semicolon though!

<comment><USER15> To compound the problem, bash tends to attract the kind of care-free security- unconscious people who don't want to be bothered with going out of their way to handle unexpected "trivialities" like spaces in file names or carefully sanitizing user input or meticulously testing their code.

The same kind of lazy care-free people who love the convenience of PHP's "register_globals", because it "saves typing".

If they're too lazy to use something like Python in the first place, they're probably also too lazy to be conscientious and anal retentive enough to write and test bash scripts that handle spaces in file names properly, or do any kind of user input sanitization.

And they don't think twice about running their scripts as root, either. Or writing blog postings telling other people to copy and paste their code snippets into a root shell, or worse yet download and run them without auditing first, by piping curl into a root shell.

I recently had an Xcode project fail to build (blender, which uses cmake), because I was using a version of Xcode that had a space in its directory name (because I had foolishly added a space followed by the version number to the name "Xcode 9.4.1.app"). Of course that was because of some of the tools and custom build steps were calling out to bash. The problem wasn't in any of the source code or configuration files, it was in the file name of the tool itself! It took hours of frustration poring over machine generated project and makefiles to diagnose the problem from the obscure unhelpful error message, which I will never get back.

In the long term, isn't it more efficient of a lazy person's time to simply use a scripting language that just doesn't have these problems in the first place, and doesn't require you to preemptively bend over backwards and dodge silent invisible bullets all the time?

It's pretty ridiculous that a scripting language intended to be used to operate on files falls flat on its face and is so difficult to use when you have something as common and innocuous as files with spaces in their names (or worse yet, file names that begin with dashes -- think of the security implications of that: not something a lazy careless bash scripter would ever pause to reflect about)!

It really is an extremely common and unsolved problem. Notice how each "better answer" is actually worse than the last and comes with its own host of problems and edge cases and work-arounds:

[https://unix.stackexchange.com/questions/9496/looping- throug...](https://unix.stackexchange.com/questions/9496/looping-through- files-with-spaces-in-the-names)

[https://stackoverflow.com/questions/3967707/file-names- with-...](https://stackoverflow.com/questions/3967707/file-names-with-spaces- in-bash)

[https://www.cyberciti.biz/tips/handling-filenames-with- space...](https://www.cyberciti.biz/tips/handling-filenames-with-spaces-in- bash.html)

[https://www.tecmint.com/manage-linux-filenames-with- special-...](https://www.tecmint.com/manage-linux-filenames-with-special- characters/)

[https://www.hecticgeek.com/2014/02/spaces-file-names- command...](https://www.hecticgeek.com/2014/02/spaces-file-names-command- line/)

</comment></comment></comment></comment></comment></comment><comment><USER19> fork() explanations generally describe the api's, maybe talk a little about COW and memory protection... but I never see sufficient explanation of WHEN to use fork().</comment>


Event-Driven Architecture - <AUTHOR> https://herbertograca.com/2017/10/05/event-driven-architecture/ <comment><USER2> In my experience the most important feature of any event driven system should be to have a simple way to lookup all the listeners that exist and what events they're hooking into and in which exact order. As soon as you start having them all around the code it becomes a nightmare to follow the logic, especially if code has side-effects.

<comment><USER3> How do you do this with disparate systems? For example a ruby application that handles and emits events concurrently with a python one.

<comment><USER4> Centralized logging, with a track and trace ID that is passed around and logged. I have seen this work to great effect with a dynamic (force directed) based graph been built in real-time showing the flow of calls/messages between systems. Also provided timings and drilldowns to find processing issues and performance problems.

<comment><USER5> People I've worked with kinda-sorta understand the advantages of having a trace ID (aka context ID, correlation ID, etc), but don't code it into their systems. Or they do something like replace an incoming ID with their own, which negates it's value.

For folks who aren't familiar with the concept - at the initiation of any action (user button click, timer firing, automated job starting, etc.) a new ID is created then passed to every single method and external call. This allows you to trace that action as it wends it's way through your distributed systems.

</comment></comment></comment></comment><comment><USER6> My team just got finished re-writing a frontend JS app that went all-in on events for handling almost everything to a more declarative React app with more explicit dependencies. It still has some event bindings with a central store of state to re-render components, but they are isolated to a single, manageable mechanism.

Event-Driven architecture sounds like somewhat of a panacea with no worries about hard-coded or circular dependencies, more de-coupling with no hard contracts, etc. but in practice it ends up being your worst debugging nightmare. I would much rather have a hard dependency fail fast and loudly than trigger an event that goes off into the ether silently.

With events, most stack traces, call stacks, and flame graphs become useless dead ends. Tracing the flow of the program becomes a game of grepping the entire codebase for copy-and-pasted event names, trying to figure out everywhere the event is used, called, forwarded on to another event, etc. You can attach loggers, but if you go all-in on events, you will eventually end up with so many event calls and handlers that it becomes hard to tell signal from noise.

IMHO, there are way too many downsides to use events at the application architecture level. They are certainly useful for many other things in real applications (as the author states and warns), but not the basic nuts and bolts of your architecture.

TL;DR: The author is quite correct about his 'spaghetti code' warning that can happen with events everywhere.

<comment><USER7> The problem with this is that you're attempting to do an event-driven app that has a network layer inbetween and a language that has very little safety sorrounding it.

Event driven architectures are appropriate for services. Just not a JS based website.

</comment></comment><comment><USER8> The biggest problems I've run into with event-driven (microservices) architectures is that there is no built-in opportunity for any kind of application-level feedback, or even minimal synchronous data validation. Your queue may be up and accepting messages, but if you've sent bad data, or if nobody's listening, there's no ability to find that out without essentially reinventing HTTP or creating their own lower-overhead error channels -- an approach which leaves a lot open for mistakes over something well-understood like HTTP.

<comment><USER9> Why not do synchronous validation at the boundary with event-driven async architecture within the boundary?

<comment><USER10> That works OK up to a point, but if validity depends on any sort of state that might be changing concurrently then potentially it opens you up to problems with race conditions.

Just like locking shared state for thread synchronisation or operating on a shared filesystem, there are usually only two completely safe strategies. Assuming your underlying operations are guaranteed to be atomic but might fail, either you can do everything synchronously and report any failure immediately, or you can go all-in on asynchronicity, so even reporting success or failure is done by firing a message back asynchronously later.

If you're going with anything more exotic, you'll need a strategy for dealing with the intermediate states, for example something that looked like it was going to work but then didn't. That might mean something like doing just enough synchronously to guarantee you've got a record of what needs to happen as a result of the event, then returning a success indication, and then asynchronously following up on the other required actions later, with some sort of auditing and reconciliation processes to make sure that everything that should happen eventually does. In this sort of situation, maybe you would also be able to do enough synchronous validation up-front to know that your request will be able to succeed, even if the goalposts move during the process.

</comment></comment></comment><comment><USER11> Replay with side/external-effects is problematic, but it seems like you just need futures to handle this.

Each event that triggers external effects is bound to a future identifier. The replay actor then accumulates a map of these events. When encountering an event that represents resolving a future, that future is removed from the map. At the end of the replay, you're left with the list of futures that haven't been resolved.

At this point, you can trigger the side-effecting computation to try and resolve the futures.

</comment><comment><USER12> [http://www.kegel.com/c10k.html](http://www.kegel.com/c10k.html)

<comment><USER13> > _You can buy a 1000MHz machine with 2 gigabytes of RAM and an 1000Mbit /sec > Ethernet card for $1200 or so._

<comment><USER14> Even better, on applying this horsepower to serve web pages to 10,000 clients:

> It shouldn't take any more horsepower than that to take four kilobytes from > the disk and send them to the network once a second for each of twenty > thousand clients.

Four kilobytes. Apparently the average page size is now 2.3MB [1]. It's not hard to find popular sites that load much more than that.

[1] [https://www.wired.com/2016/04/average-webpage-now-size- origi...](https://www.wired.com/2016/04/average-webpage-now-size-original- doom/)

<comment><USER15> Which is pathetic and absolutely inexcusable.

The internet and computers keep getting faster, and instead of the web getting MORE responsive, thanks to jackoff web developers, it's getting SLOWER and SLOWER.

I'll never forget the first day as a teenager that we had cable internet finally offered in our neighborhood. Going from 56K it was pure heaven. We're running a (P2-era) Celeron 333 MHz and pages loaded INSTANTLY.

Now, I sit there with a connection 6-10 times faster than my teenage connection, a computer with 8 cores running at almost 4 GHZ and I have to wait for a page to load.

I just checked. ~5 seconds to load the front page of CNN. 5 seconds for Facebook. 7 seconds for GMAIL. (Not like I need to check my e-mail often, eh!) All those numbers are 3x or higher on my laptop.

I actually still use the HTML version of gmail even on my desktop. Why? Because it loads in less than a second. (I just got a time-to-load-page extension, yep. 0.52 seconds verses 6.5 seconds.)

<comment><USER16> I've taken to browsing with JS disabled by default (whitelisted for specific sites) and the speed/enjoyment trade-off is totally worth the occasional broken it oddly-laid-out page.

This is especially true in a HN/Reddit context where most links will be to articles.

</comment></comment></comment></comment></comment><comment><USER17> ok hands up who actually enjoyed MVVM architecture?

<comment><USER18> I do, but is that related to this article somehow?</comment></comment>