Use mmap with care - <AUTHOR> https://www.sublimetext.com/blog/articles/use-mmap-with-care <comment><USER2> The first serious bug I ever dealt with professionally was a result of the hazards of mmap(). This was 1995, and I was working on AIX with a system that used a series of shared memory buffers for IPC. It was originally written with shmat(), and on AIX (at least in those days), shmat was limited to three shared segments, so we had a lot of performance-wrecking blocking going on while waiting for the buffers to be cleared.

My first being original-idea development was rewriting with mmap so I could use an arbitrary (and programmable) number of buffers, tuning blocking against memory consumption, with logging to track performance for tuning. It was very cool. Worked great!

Until it went to production.

In production, it crashed every time it ran, shortly after starting up. Since we were doing seasonal production, backing out my change also backed out other necessary changes. It was very embarrassing and frustrating. Worse, I could not replicate the problem in testing! It only happened on the prod servers. And, as a wet behind the ears junior programmer, everyone assumed I'd just screwed up and was too dumb to understand how.

So I wrote a test program, divorced from our regular code, to test mmap() itself. Turned out that it ran fine on dev/test servers, but on the prod servers, it would randomly overwrite 1k memory pages with nulls. Yeah. Once i convinced the senior engineers and my manager, I got to report an OS bug to IBM. Who were like "What's wrong with your code, really?" I wound up sending them my C test code and the compiled executable, along with results.

It turned out the bug was caused by the order in which OS patches had been applied on the servers.

One of the first rules in the marvelous book _The Pragmatic Programmer_ is "Select() isn't broken". Yeah, but sometimes it is.

And if a junior programmer came to me today reporting a bug in OS memory management, my first response would be "What's wrong with your code, really?"

<comment><USER3> Yeah. It's sometimes hard to remember just How Bad software was even in living memory. These days, we all just assume that the basics all work and are surprised to see bugs, which we vote up to the top of HN. But it wasn't always like that, things just failed in crazy ways, at all levels of the stack.

At the start of the dotcom boom, a server uptime measured in months was considered notable, and the idea of a client system lasting a week between some failure or voodoo reboot was laughable. Now... I dunno, when was the last time I bounced my phone? Genuinely can't remember.

<comment><USER4> Yep, this is part of the reason why it drives me crazy when people say the '90s were the heyday of computing. Computers were _awful_ back then.

<comment><USER5> I think they still have a point. It was the heyday of computing precisely _because_ they were awful; there was always something to work on or improve. Fixing bugs in operating systems offered clear improvements to the livelihoods of thousands or millions.

It's no longer that easy now. Most critical things don't suck that hard anymore, so it's hard to find a way to feel special, or feel like it's a special time to be a part of.

Even in startup land most work done is "build this website" or "build this app" \- what the software does could be cool and easy enough to get passionate about, but the hope that "we're going to use this code to revolutionize the entire world for the better" that was omnipresent in '90s hacker culture has pretty much been murdered by the sins of Facebook and others in Big Tech. Now it's "what can I do to make sure the stuff I work on hurts the least amount of people as possible?"

<comment><USER6> On the flip side, while OpenSSH may be great and high quality now, and wasn't in the '90s, in the '90s people used telnet on the public Internet, and telnet worked.[1]

IOW: It wasn't basic tech _and_ great opportunity at the same time.

Today you can work on immature things like OpenBSD's MPLS implementation and who knows, maybe in 20 years people will say that back in 2019 there were so many things that could be improved about that basic tech! (cue replies anti- labelswitching dweebs)

[1] Not me, I used ssh since before OpenSSH.

<comment><USER7> Telnet and rlogin were both very common. I remember installing ssh on my Slackware Linux box back in 1996. I had to build it from source... fun times!

</comment></comment></comment></comment></comment></comment><comment><USER8> Even without NFS, using mmap requires being real careful about signals - SIGBUS can be raised any time the underlying file operation fails, including because someone else truncated the file, or because the underlying storage had an error (disk error, removed media, network storage). And, as this post so eloquently illustrates (and through my personal experience), handling SIGBUS/SIGSEGV cleanly in a multithreaded program on POSIX is incredibly painful.

Honestly, pread is just a much better solution for 90% of use cases, and it works for large files on 32-bit systems (mmap does not!). If you're doing largely sequential things, fread/fseek often work remarkably well as they handle all the caching for you.

mmap tends to shine performance-wise if you need random access to a file but access certain parts of the file frequently (for example, accessing the index in a header + contents of the file), because the page cache is literally designed for this type of usage. But the performance improvement is rarely worth the technical complexity.

<comment><USER9> Alternatively one can run a separated process that does mmap and runs the calculations or whatever that needs to access the file as quickly as possible and do the the straightforward recovery in the parent process when the child process dies. The drawback is the need to some form of RPC, but there a lot of libraries to do that without much hustle.

<comment><USER10> You can do that with a MAP_ANONYMOUS | MAP_SHARED mapping too: that kind of mapping is writable by both parent and child, but isn't backed by a disk file and so can't be truncated or surprise-removed. The article's points about mmap infelicity applies mostly to mappings of disk files. Anonymous mappings don't have the same problems.

<comment><USER11> Anonymous mappings are backed by swap and may be overcommitted, it's still possible to catch signals in a wide variety of circumstances

There is probably enough evidence in this thread to use it as a reference for why typical apps should avoid mmap whenever possible -- it's clear almost nobody fully understands it

<comment><USER12> > Anonymous mappings are backed by swap and may be overcommitted,

So is normal memory. Many allocators today even use mmap internally.

<comment><USER10> All* allocation is mmap, really. All mmap does is dedicate a region of address space to some kind of backing storage. The particular kind of backing storage makes all the difference. The problem is that people colloquially use "mmap" to mean "mmap of a conventional disk file" and don't mean all the other kinds of mmap out there, so discussions can become confusing.

* Ther's sbrk too, but it's just a fancy legacy path that amounts to the same thing as anonymous mmap

</comment></comment></comment></comment></comment></comment><comment><USER13> Honestly, this reads like a thorough indictment of signals in user space.

* Signal handlers are process global * Signal handlers need to be re-entrant safe

Re-entrancy is painful but can be done, but process-global signal handlers means that pulling in a totally unrelated library can break your code. Moreover, it makes the combined use of certain libraries straight-up impossible. Similarly, it means that the use of library precludes you from using certain features.

Combined, this means that the use of signal handlers is simply toxic. Which makes them an anti-feature. It feels to me like having the restrictions of kernel-space, with all of the downsides of user-space.

Are there any plans in linux to replace signals?

<comment><USER14> The real issue is that people are using threads for things that processes were originally intended for. Having one thread for the UI, one thread for network code, one thread for program logic, etc. is actually a mis-use of threads in POSIX-land. POSIX is designed for you to use multiple processes where in Windows you would use multiple threads. This gets you a lot of robust interprocess communication mechanisms and also memory isolation on systems with an MMU. It also had performance implications on the state of the art hardware at the time, which is why threads were invented. And finally it requires you to expand your usage of the operating system.

Being multi-process would solve the issues with a process-global signal handler because there would no longer be a question of which thread generated the signal.

<comment><USER13> This seems like an ivory tower argument, people shouldn't want shared mutable state, so anyone suffering is doing so at their own hand.

At the same time, shared mutable state, specifically a fully shared and transparent (ignoring caches) address space is the least effort way to take advantage of multi-core CPUs. Hence, people will be using it. There is essentially no getting around that, and there are even some reasons for wanting it.

Being multi-process would solve a lot of issues, but so would settling on a single convention for endianness, rewriting C++ to use unique_ and shared_ptr where applicable, and many other nice to haves.

At the end of the day, the easiest road is going to be taken more often. If that happens road is lined with bandits and barely visible traps, that is a problem. No matter how often you tell people not to take that road, and climb a slippery mountain path instead.

</comment></comment></comment><comment><USER15> The mistake here is using longjmp / siglongjmp. This is a possible way to handle SIGBUS, but in practice it will be intractable in larger programs written in C or C++. The compiler is generally free to move loads and stores around, and you might be completely blindsided by how the compiler has reordered your memory operations once you add side effects to one of the operations. Theoretically, if accessing a memory location can siglongjmp out then at least the memory location should be volatile.

A better way to handle SIGBUS is to just map zeroes over the offending pages using MAP_FIXED and then setting a flag. After every operation that works on a file, you check the flag.

<comment><USER16> This sounds interesting. Do you know of an example that does this?

So if I have multiple threads reading the same mmap'd file, I use si_addr in the signal handler to know which page to call MAP_FIXED on?

<comment><USER15> I don't know an open-source example off the top of my head. But that's the gist of it… you keep an array somewhere with all the address ranges mapped. If you get SIGBUS, find the corresponding map, replace it with zeroes, and mark it as having an error. If there is no corresponding map, uninstall the signal handler and return—the thread will SIGBUS immediately after return and the default action will kill the process.

</comment></comment></comment><comment><USER17> Really cool talk by Bryan Cantrill about the joys of mmap in a "simple" use- case: [https://m.youtube.com/watch?v=vm1GJMp0QN4#](https://m.youtube.com/watch?v=vm1GJMp0QN4#)

<comment><USER18> Such a great talk - thanks a lot! Here is the direct link as it is the last of the lightning talks: [https://www.youtube.com/watch?time_continue=2462&v=vm1GJMp0Q...](https://www.youtube.com/watch?time_continue=2462&v=vm1GJMp0QN4)

</comment></comment><comment><USER19> Things are so much better if you are not writing apps for general public (mine are trading-related). You can tell your few clients — make sure that the access to mmapped file is exclusive — and get away with it.

And yes, mmap is the awesomest thing out there.

<comment><USER20> I've moved away from mmap for trading in favor of a separate write thread.

While mmap is fast, the combination of factors that can make it decide to stall your thread while it commits to disk is difficult to manage from an operational standpoint. A slight misconfiguration is all it takes to introduce a rare and hard to notice multi-millisecond delay.

Whereas with a spinlocked sized-reserved vector, the fail state performance is however long it takes to allocate more space which is on the level of microseconds. You do pay 50-150ns for that spinlock though.

<comment><USER21> Or better yet, mmap in a read-write-thread?

<comment><USER20> Ya sure, go nuts on the other thread. It's not critical to trading. I normally fprintf all sorts of time stamps, log level info, and handle formatting over there.

Just make sure you put it on another core to protect your cache.

But if you want mmap, you do you.

</comment></comment></comment></comment><comment> ben-schaaf Author here, if anyone has any questions in relation to me or Sublime HQ please feel free to ask.

<comment><USER22> "In hindsight it's difficult to justify using mmap over pread"

This needs a stronger justification. mmap allows reading and writing large data structures without copying, which can be a huge benefit depending on the use case.

<comment> ben-schaaf Using pread would have been more work from the start but provides a more robust solution and doesn't have problems on Windows. I would argue that the incrementaly built mmap based solution is strictly worse, thus difficult to justify doing again.

<comment><USER22> "strictly worse" despite no-copy memory access? Again, this needs proof.

<comment> ben-schaaf Strictly worse because it requires more work to maintain and write new code, there's no guarantee we haven't missed any access points in our codebase so it is less robust, still locks files while in use on Windows and requires maintaining patches to Breakpad. Performance is not an issue here, the program working correctly is, and doing so in the long run is strictly worse than mmap.

<comment><USER23> Do you have a list of these strictly-better things to do and a plan on when to implement them? Do you let them pile up? Mostly asking about your decision- making process.

<comment> ben-schaaf I'm not sure what you mean. The blog post discusses solutions to all the problems I listed. They wouldn't have been problems using pread, which has a straight forward implementation.

</comment></comment></comment></comment></comment></comment></comment><comment><USER24> The other big problem with mmap is what happens when your file changes out from under you. This seems to be mostly for git packfiles, which I think can be treated as immutable by convention, but that's not strongly enforced anywhere. For reading, eg, program source files, I think mmap is hugely problematic.

I've been arguing for a long time that operating systems should provide read only snapshots of files as a primitive, but that's a pretty big ask; it's especially hard to do when the file system is network-mounted. There are a couple of copy-on-write filesystems on Linux (btrfs and ZFS if memory serves) which can do this locally, but it's not mainstream.

<comment><USER25> You can assume that git packfiles are immutable. They may disappear from under you as a repack happens, but they will not be changed.

They even have a name like pack-<SHA-1>.pack where that <SHA-1> is a SHA-1 of the contents of the pack (minus the last 20 bytes, the checksum SHA-1 is also part of the pack itself).

<comment><USER26> True for this workload, _iff_ you assume the filesystem and/or media protects you from corruption (it probably doesn't). I would guess OP is commenting on mmap IO in general, rather than TFA's specific git use case.

</comment></comment></comment><comment><USER20> I feel like this is kind of a dumb design.

You want to abstract two different kinds of file reader: an mmap reader and a regular reader. (And I would add a gz reader, personally).

Then by inspecting the properties of the file, you can determine if it is local when opening, and if so, mmap the file.

I say this because if the file is coming via the network or a FAT32 partition you're not going to save much time with mmap relative to the read speed anyways.

<comment><USER27> But now you have two completely independent code paths. Both of which will need to go through the same maturation phase that the ST folks evidently went through with mmap. And if the code needs to evolve for other reasons, potentially both of these paths will need some love too.

Seems like the worst choice in a situation like this!

<comment><USER28> Butler Lampson talks about the general concept of an overlay in operating system design. It's a slightly different case, on the surface, but the possible application in this case is that if mmap fails, you probably _should_ have a fallback code path that tries to access the file normally.

That's obviously not going to work for all applications. But it's something you consciously have to do anyway if mmap may not be available (e.g. when working across the network). The OS design should make it easy to move up and down in this hierarchy of access methods, but the application programmer still needs to know which "level" of access they have to the file.

There's work to be done here in improving the design of the OS interface. That would lift part of the the burden of maintaining multiple paths in the application code.

[https://www.youtube.com/watch?v=TRLJ6XdmgnA&t=11m35s](https://www.youtube.com/watch?v=TRLJ6XdmgnA&t=11m35s)

slides: [https://bwlampson.site/Slides/Hints%20and%20principles%20(HL...](https://bwlampson.site/Slides/Hints%20and%20principles%20\(HLF%202015\).pdf)

see also: [https://ocw.mit.edu/courses/electrical-engineering-and- compu...](https://ocw.mit.edu/courses/electrical-engineering-and-computer- science/6-826-principles-of-computer-systems-spring-2002/lecture-notes/30.pdf)

</comment></comment></comment><comment><USER10> There's also the matter of taking an implicit "system call" (via page fault) the first time your program touches a page that hasn't yet been faulted. This old myth that mmap is the fast and efficient way to do IO just won't die. mmap does have perfectly legitimate use cases (e.g., reducing anonymous commit charge) but you should try to make regular reads work first.

 _That said_ , there's nothing wrong with mmap or SIGBUS error reporting in concept. I think I've said it before, but you can think of mmap of a disk file as basically adding a temporary dedicated swap file to the system, with all the pages backed by that "swap file" already "swapped" out unless already cached. Sometimes that's exactly what you want!

The author's signal handler registration difficulties come from the POSIX signal API being awful, not from the idea that catching CPU traps is somehow bad. It's possible to do much better than sigaction(2). I wrote up a detailed proposal for improvement in [1].

When I ran [1] by the glibc people, though, the response from them was pretty stark and unwarranted hostility toward any use of signals at all, even in perfectly legitimate scenarios, like mmap SIGBUS or certain kinds of important JVM-style pointer check [2] optimizations. It's this "we won't change anything anywhere despite our views being out of step with real user needs" attitude that's responsible for a lot of weird friction in the Unix API surface.

Practically every program mmaps disk files has trouble recovering from IO errors. If it were easier for multiple components in a process to share responsibility for handling a signal, we'd more often get subtleties like this right. A better signal API will improve the user experience. Tilting at signal-shaped windmills won't.

[1] [https://www.facebook.com/notes/daniel-colascione/toward- shar...](https://www.facebook.com/notes/daniel-colascione/toward-shareable- posix-signals/10157129032641102/)

[2] Relying on CPU traps lets you perform certain checks for free. Why write "if (myptr != nullptr) var = _myptr " when you can just write "var = _myptr" and handle the SIGSEGV when myptr ends up being nullptr? The latter option is zero-overhead in the non-nullptr case. It's also much more complicated, but if you're a VM, and you generate _millions_ and _millions_ of these "if (myptr != nullptr)" checks in JITed code, the size and speed win of eliminating the check starts to justify the complexity.

<comment><USER29> > This old myth that mmap is the fast and efficient way to do IO just won't > die.

Well... because it's not a myth in all cases?

        $ time rg zqzqzqzq OpenSubtitles2016.raw.en --mmap

        real    1.167
        user    0.815
        sys     0.349
        maxmem  9473 MB
        faults  0

        $ time rg zqzqzqzq OpenSubtitles2016.raw.en --no-mmap

        real    1.748
        user    0.506
        sys     1.239
        maxmem  9 MB
        faults  0

The OP's adventures with mmap mirror my own, which is why ripgrep includes this in its man page:

        > ripgrep may abort unexpectedly when using
        > default settings if it searches a file that
        > is simultaneously truncated. This behavior
        > can be avoided by passing the --no-mmap flag
        > which will forcefully disable the use of
        > memory maps in all cases.

mmap has its problems. But _on Linux_ for a simple sequential read of a large file, it generally does measurably better than standard `read` calls. ripgrep doesn't even bother with madvise.

Changing the workload can dramatically alter these conclusions. For example, on a checkout of the Linux kernel:

        $ time rg zqzqzqzq --mmap

        real    1.661
        user    1.603
        sys     3.128
        maxmem  41 MB
        faults  0

        $ time rg zqzqzqzq --no-mmap

        real    0.126
        user    0.702
        sys     0.586
        maxmem  20 MB
        faults  0

Performance of mmap can also vary depending on platform as well.

FWIW, I do generally disagree with your broader point, but it's important to understand that there's actually good reason to believe that using mmaps can be faster in some circumstances.

<comment><USER30> It's not a myth at all, mmap is faster, you save on straight copies of data and the sys-calls to do it. It should be faster in nearly all circumstances, faster by at least a copy. In exchange you pick up a lot of complexity dealing with faults and you potentially put stress on the VM system. If you are doing to 'O' part of I/O then mmap starts to be really complex, fast. rg is kind of a special case, it's not writing, it's going to do mostly (maybe only, I assume it backtracks on matches) sequential reads of mostly static files, it's really the easy case, its not clear that madvise would help and your brand is speed so saving on those copies is worth it. What might be interesting, on certain memory constrained systems you can slide a smaller map space through the file rather than mapping the whole thing; it's been a while since I looked at it all but mapping the smaller pieces gives huge hints to the vmm and it would probably slow down rg incrementally but speed up overall system performance.

<comment><USER29> Yes... _I_ know it's not a myth. :-) I was responding to someone who was saying that it was a myth.

> It should be faster in nearly all circumstances

As my previous comment showed, that's definitely not true. If you're searching a whole bunch of small files in a short period of time, then it appears that the overhead of memory mapping leads to a significant performance regression when compared to standard `read` calls.

> it's really the easy case

I know. :-) That's why ripgrep has both modes. It chooses between them based on the predicted workload. It uses memory maps automatically if it's searching a file or two, but otherwise falls back to standard read calls.

Moreover, if ripgrep aborts once in a while because of a SIGBUS, then it's usually not a big deal. It's fairly rare for it to happen. And if it does happen to you a lot or you never want it to happen, then you just need to `alias rg="rg --no-mmap"`.

<comment><USER30> I love ripgrep, btw, great work.

I was pondering this some more in the shower, the mmap for rg case is also sort of naturally cache oblivious, copies will consume hardware cache for the write and while there is a ton of hardware for cache on modern hardware, it's a noticeable cost on some tests. If you're searching through something big, then it'd be like doubling hardware cache which is probably really noticeable on smaller devices.

The small files case is interesting, copying the data is faster than patching up the page table tree, I bet there is a strong correlation to the hardware cache size vs the average file size in that case. The files probably need to be N pages in size for it to be worth it, might be an interesting heuristic to use.

</comment></comment></comment></comment></comment><comment><USER31> And that's just for reading. Writing, especially if you want to be sure when the writes hit the backing file, or in what order, or if you run out of disk space, is another kettle of problems.

I wonder how Multics dealt with all this, since AIUI in that system everything was effectively an mmapped file.

<comment><USER32> Did Multics have anything like NFS? Everything is easier if your kernel has control of the underlying device.

<comment><USER33> Well the problematic example given in the article was NTFS where the whole filesystem can disappear, but the problem applied to local files too, eg if their size is changed by another process.

<comment><USER32> Where did you see mention of NTFS? I was referring to "As it turns out, the ticket comes from someone using a networked drive."

<comment><USER33> Sorry, it was a typo, I meant NFS or more generally some type of networked drive.

</comment></comment></comment></comment></comment><comment><USER34> > Using setjmp and longjmping from a signal handler is actually unsafe. It > seems to cause undefined behaviour, especially on MacOS.

Have you considered making a dispatch_source_t of type DISPATCH_SOURCE_TYPE_SIGNAL and handling all signals in a dispatch queue, instead of trying do figure out what kind of behavior is legal in a signal handler?

> If a library such as Breakpad registers for Mach exception messages, and > handles those, it will prevent signals from being fired. This is of course > at odds with our signal handling. The only workaround we've found so far > involves patching Breakpad to not handle SIGBUS.

Would it be possible to install your own handler before Breakpad does?

<comment> ben-schaaf > Have you considered making a dispatch_source_t

I think that would have been considerably more work than finding the SO answer that says you need to use sigsetjmp, and would probably still conflict with Breakpad ;)

> Would it be possible to install your own handler before Breakpad does?

I may be wrong, but I think you can only register one exception handler per "task" (process), so Breakpad would override ours.

<comment><USER35> When you install a mach exception handler you can get the port of the previous exception handler, which you can use to forward the messages your newly installed exception handler receives. Of course (as with all raw mach APIs) it is poorly documented and error prone.

<comment><USER34> Interestingly, it seems like Breakpad does a task_get/set_exception_ports dance instead of using task_swap_exception_ports: [https://chromium.googlesource.com/breakpad/breakpad/+/refs/h...](https://chromium.googlesource.com/breakpad/breakpad/+/refs/heads/master/src/client/mac/handler/exception_handler.cc#675). Doesn't this break if someone registers a handler between the two lines?

</comment></comment></comment></comment><comment><USER36> Note that some BSDs have a MAP_ZERO flag which makes invalid accesses read zeros instead of triggering SIGBUS.

<comment><USER26> Which ones? I don't see it in manual pages for any of the ones I know about (Free, Net, Open, Dragonfly).

</comment></comment><comment><USER37> Oh I see you didn't get to caveat 5: you can't read anything more complicated than raw bytes, i.e. chars, because of unaligned memory access errors. Let's say you mmap a file and do something like this:

      char *fileContents=...mmap etc...;
      int headerOffset=*(int*)fileContents;
      int *someListOfNumbers=(int*)(fileContents+headerOffset);
      int importantSum=
        someListOfNumbers[0] +
        someListOfNumbers[1] +
        someListOfNumbers[2] +
        someListOfNumbers[3];

If headerOffset is not a multiple of 4, bad things will happen. On x86 you'll get away with it... Unless you were summing many more ints and the compiler decides to use aligned SSE loads for speed[1]. On ARM you'll get a SIGBUS just for trying to read unaligned ints (IIRC). You can fix that by wrapping your ints or whatever you're trying to read in a packed struct, but it is yet another thing to keep in mind.

[1] [http://pzemtsov.github.io/2016/11/06/bug-story-alignment- on-...](http://pzemtsov.github.io/2016/11/06/bug-story-alignment-on-x86.html)

<comment><USER16> You should not directly use structs for data serialization. If you end up having to support a big endian platform, your structure orders will change, not to mention potential packing issues as you said.

[https://commandcenter.blogspot.com/2012/04/byte-order- fallac...](https://commandcenter.blogspot.com/2012/04/byte-order- fallacy.html?m=1)

<comment><USER38> Wasting a good performance optimization on the rare chance that you might one day have to support a different endian architecture is IMO a poor tradeoff. The number of big-endian machines in use today is continually shrinking, and the number that are active on a heterogeneous network is even smaller.

In LMDB we simply document "don't use this with remote filesystems" and avoid the issue - if you're never sharing files with other machines, there's never a question of mixed endian accessors.

<comment><USER16> I still think you shouldn't be directly sending structs over the wire or to disk. The alternatives are so much better - SQLite or Cap'n Proto.

I'm a bit shell shocked from supporting both big and little endian in structs from previous jobs. I've had nightmare situations with it twice. I do embedded systems and while little endian is winning there too, you still have legacy things like the LEON (SPARC) that is big endian. I've heard lots of network embedded hardware is big endian too for obvious reasons.

<comment><USER39> To disk is probably a bad idea but over the wire has some legitimate applications. Being reliant on same endian systems can be alright if for example you're building a distributed computing system where the same binary will be executed on a bunch of systems and all you're doing is sharing computation results between those instances. You do get unrivaled serialization speed that way. Timely Dataflow [1] works that way by default, but it also has an option for "real" serialization if that is required. Admittedly that's a fairly specific application but it's real and sometimes it's a good tradeoff.

[1] [https://github.com/TimelyDataflow/timely- dataflow](https://github.com/TimelyDataflow/timely-dataflow)

<comment><USER16> Yeah that's true for the distributed application you mentioned with the wire. Certainly advantages there, especially when you control all the nodes.

I hate seeing the fields of a communication protocol listed in two structs - an ifdef BIG_ENDIAN and LITTLE_ENDIAN. They will invariably be inconsistent, someone will change something in little but not big, or even worse, update one incorrectly and not test it.

</comment></comment></comment></comment></comment></comment><comment><USER40> Now I'm curious how Vim deals with large files. I'm assuming the went the pread route.

<comment><USER13> Vim needs to do a lot more special stuff, because it has to handle random insertions and deletions. Doing those things to a file (mmaped or otherwise) requires moving all data after the edit.

If I recall correctly, vim/vi uses a linked list of 'chunks' that is dynamically merged. For long files I would expect some form of lazy loading of chunks.

<comment><USER41> That's right. The key data structure is the rope: [https://en.wikipedia.org/wiki/Rope_(data_structure)](https://en.wikipedia.org/wiki/Rope_\(data_structure\))

<comment><USER40> Nice! I thought xi was the only editor that used ropes.

</comment></comment></comment></comment><comment><USER42> It would be really nice if there was a POSIX equivalent to Foundation's NSDataReadingMappedIfSafe, which uses mmap() when the file isn't backed by NFS and falls back to read() when unsafe or not worth it.

<comment><USER43> Is there a way for a process to know what kind of filesystem something lives on, or is this just a developer-provided clue?

<comment><USER44> getmntent(3)

</comment></comment></comment><comment><USER45> I've successfully used mmap() a few times in the last few years... Luckily for me the use cases I've had weren't really subject to the same problems I've since read about here and elsewhere:

1) I'm always mmap()ing the whole file (and the files are power of 2 sized). 2) The files I'm mapping are stored on file systems I control (and so are never on NFS). 3) In one case, my use of mmap() is limited to read only.

<comment><USER46> mmap seems to be specifically designed to trigger the differences between NFS and Unix file system semantics.

<comment><USER26> Really any networked or distributed filesystem will struggle to implement mmap semantics well.

</comment></comment></comment><comment><USER47> The problem here was wanting to parse a large file at all. You need to be able to do a) online parsing (so you don't need to read the whole file into memory _first_ ), b) stream parse (so you don't need to build a parsed representation of the whole thing before you can do anything).

</comment><comment><USER48> How widely-used code laying on mmap (LMDB maybe being one of the prominent cases) rolls?

</comment><comment><USER49> Or you could stream parse the file. eg. parse it one chunk at a time.

<comment><USER34> That's what they were doing before?

<comment><USER50> Before they were reading the whole file into memory and parsing it. Now, they are using mmap to read parts of the file into memory when they are used. If you're only doing a single linear pass through a file there is a third option; you could read part of the file in a single chunk at a time, parse that chunk, then read the next part of the file into the same chunk of memory.

I don't know enough about the process being discussed here to know whether it needs to do lookups at random offsets in the file, but iff it doesn't then the chunked read solution could be a simpler way to reduce memory usage.

</comment></comment></comment><comment><USER51> TRWTF is Breakpad, trying to deal with the process crashing from within the process itself. Even requires PTRACE to work.

</comment><comment><USER26> I'd go a step further and broadly recommend not using mmap to access files, unless there's a _really_ good overriding reason. (E.g., if the file is some sort of special virtual device/filesystem that by nature cannot have errors.)

Mmap is not good for writing to files — pages may be persisted to disk in arbitrary order, which makes it harder for filesystems to coalesce adjacent writes into fewer larger (and faster) IOs. (This is still an issue on SSDs, although not as bad as on HDDs.) This is a performance issue and can result in bad file layout (making future reads slower).

As this article describes, the mmap() model sort of assumes no errors happen. This breaks when files are truncated, even on local POSIX filesystems, and you get SIGBUS. It can also break if files disappear, such as a failing media or removed USB stick, or network filesystem. It doesn't mesh well with distributed filesystems either, for obvious reasons. If a page is to be writeable, you must take an exclusive data lock on that page's region across your distributed filesystem (and read access requires a shared data lock, to prevent corruption from concurrent writers). What if you lose quorum / availability?

TFA's trick to use thread-specific longjmps around specific virtual memory accesses probably works out ok on POSIX platforms[1] but it requires wrapping _all_ of your mmap'd regions carefully. You can't just cast portions to a struct and access directly, except in small critical regions protected by the sigsetjmp. And as they point out, SIGBUS is global — it can conflict with error catchers (mentioned in TFA) but also can be raised for reasons other than mmap IO failure, such as attempting to access a non-canonical virtual address, and thus a long-lived global handler may mask other bugs. (Also, if you mmap many files and install a single long-lived handler in a multi- threaded program, it can become difficult to determine which file-access raised the signal.)

rtorrent, for example, used to have a ton of reports of SIGBUS due to mmap'd file access failure. I don't know if they've addressed that in some way (perhaps by simply masking SIBGUS) or continue to ignore it.

TFA claims pread was about 2/3 as fast as mmap'd access; some slightly clever application-specific use of caching, prefetch, or larger IOs might help eliminate that gap by reducing syscall overhead and/or disk wait. The best thing about pread/pwrite is they return have error reporting in the interface, and you can actually check that your IO did what you wanted.

[1]: [http://man7.org/linux/man-pages/man7/signal- safety.7.html](http://man7.org/linux/man-pages/man7/signal-safety.7.html) :

        If a signal handler interrupts the execution of an unsafe
        function, and the handler terminates via a call to longjmp(3) or
        siglongjmp(3) and the program subsequently calls an unsafe
        function, then the behavior of the program is undefined.

</comment><comment><USER52> Really well-written, easy to follow piece.

</comment><comment><USER53> I feel like you should use some kind of library for this instead of handling it all yourself.

<comment> ben-schaaf A library for mmap would have not helped with any of the Windows or Breakpad issues. It would have also been more work up-front than mmap, since none of the problems of mmap were known to us at the time.

</comment></comment><comment><USER54> That one is amazing...!</comment>


The steadily disappearing American car - <AUTHOR> https://www.cnbc.com/2018/04/06/the-steadily-disappearing-american-car.html <comment><USER2> I see plenty of cars on the road. They are Toyota's and Honda's.

I love how American companies are justifying weak sales as the economy and not their complete failure to make a compelling vehicle in the sedan space.

<comment><USER3> They've been making compelling vehicles but no one cares because everyone is still scarred by 70s-90s quality. Would you even test drive a Buick if you were in the market for a Toyota or Honda?

Also, there are far more American cars on the road in the Midwest compared to the urban coasts, so your observation should include geographic location.

<comment><USER2> My wife owned a Chevy Malibu (mid 2000s) when we met and it was complete garbage from the tired design to the terrible build quality.

I've sat in more recent American cars and they are the same way still. Even flagship cars like the mustang and corvette have rattles and plastic heavy interiors.

They haven't shaken off the reputation because they are still crap.

<comment><USER4> Honda's and Toyota's are full of rattling plastic as well.

<comment><USER5> Yeah well plastic is cheap, but I haven't driven a relatively modern toyota/honda/nissan with interior rattles (including my '98 toyota)

</comment></comment></comment></comment></comment><comment><USER6> Am I missing the statistics for foreign auto makers? Maybe people just don't like American made cars?

</comment><comment><USER7> Headline: "The steadily disappearing American car"

Story: "People aren't buying Sedans anymore"

Title seems a bit clickbait to me.

<comment><USER8> Headline: "The steadily disappearing American car"

Story: "People aren't buying Sedans anymore"

Reality: "People arent buying US Sedans anymore, because US automakers keep pumping trucks"

</comment></comment><comment><USER9> I've heard this said, that Tesla made a big mistake making a sedan Model 3 instead of a cross over suv.

Made the wrong car.

<comment><USER10> Nope. "SUV"s are more expensive, less efficient (and look worse imo). _They have demand for model 3._ A fat one will be next.

<comment><USER11> I think bankruptcy will be next. Not sarcasm.

<comment><USER12> Tesla and Ford are the only major current American automakers who haven't filed for bankruptcy, right?

</comment></comment></comment></comment><comment><USER13> An domestic vehicle is as much a statement about nationalism and trade policy as anything else. Those politics are highly corelated with low population density, and therefore large vehicles. It makes complete sense that most small urban vehicles would be imports, while most exurban SUVs are domestic.

</comment><comment><USER14> and here I want a smaller car.

I'd actually like a small SUV for the practicality, but I just don't really like them.

</comment><comment><USER15> F150 is a class of its own.

</comment><comment><USER16> I rented a US built sedan a while back. I remember being amused at the huge panel gaps, cheap plastic everywhere giving off a strong chemical odour, and the fact the thing carried on rocking on its super soft suspension noticeably after you came to a halt. I cannot fathom why anyone would buy something like that rather than a BMW for example if the prices were similar, bar extreme patriotism.

<comment><USER14> > rather than a BMW for example if the prices were similar

They aren't.</comment></comment>


Mild intoxication can actually boost creative problem solving - <AUTHOR> http://www.inc.com/jessica-stillman/go-ahead-have-a-beer-at-the-office.html

<comment><USER2> I think I've come up with some crazy far out ideas in a mild state of intoxication that I've made realty the next day. It takes down the "That's impossible" wall.</comment>


SOAP vs REST: The war between simplicity and standards - <AUTHOR> http://devcentral.f5.com/weblogs/macvittie/archive/2008/12/05/soap-vs-rest-the-war-between-simplicity-and-standards.aspx

<comment><USER2> It's kind of hard to produce a calm response to this article but i will try my best.

For one thing, SOAP (an envelope) cannot be compared to an architectural style. A better correspondence might be:

Architectural Styles: REST vs. RPC

Protocol Stacks: RESTful HTTP, ATOM etc. vs. WS-*

Envelopes: HTTP headers(?) vs. SOAP

For another thing, claiming that ws-* is standards based while REST is not is plainly false. Whereas ws-* includes 50+ not wholy compatible specs, REST is based on few but well corelated specs (XML, HTML, URI, HTTP). The number of spec-pages produced is completely irrelevant. In fact, like lines of code, may be counter-productive. A better measurement may be 'interoperability produced'. On this test, the benefits of REST shine in large distributed systems such as, say, the web.

</comment><comment><USER3> The article seemed a bit weak, since depending on the problem set the choice is either apples and oranges or completely moot. Saying that HTTP + JSON is going to throw your developers for a loop is a bit embarrassing. The "hard" part is always in the data model itself, inside the container, which isn't magically solved by a given transport or serialization approach.

I've been the client to a few SOAP services which were "standard" but which contained object representations implemented by people who probably learned XML while severely inebriated and chose their tags vs. attributes using some Post-Its and a dart board.

<comment><USER4> Can you suggest some resources that provide guidelines for choosing tags/attributes?

<comment><USER3> Hm. I've never used any. The issues I ran into were along the lines of SOAP output with XML structures that alternated within the same document using attributes or child nodes for properties of the object (likely, the overall response was a result of two different programmers' output and they didn't compare notes).

There were also some instances of things like a parent having a child node and the child having a name sub-node instead of a name attribute on the child, where the parent had a name attribute. I realize there are no inviolable rules about when to use an attribute versus a tag, but what I ran into was inconsistency within a single response object. My point above was that the envelope is a standard, but the contents can be poorly designed and is domain- specific--the same is also true for REST.

<comment><USER4> My understanding of the standards around SOAP, the ws-* ones, is that the don't promise standardization of the payload. The aim is to provide standards for integration, and those are useful, because tooling and infrastructure around the services can be reused. SOAP standards are there to simplify integration, they say nothing about the payload (other then maybe it having to be xml)

</comment></comment></comment></comment><comment><USER5> Looking at the poll on that site I'm obviously pissing against the wind, but if you have a decent web-framework exposing your services standarized using SOAP involves absolutely no extra effort. None.

I can see lots of people disagree and I might even be in the minority here on HN, but I think REST is to SOA what PHP is to the web: Quick to learn, simple to get up and running, but half-assed and non-standardized and thus bound to get messy.

<comment><USER6> Yes, I'm afraid you are. SOAP is out of control. You can tell how bad it is getting since it was originally named "Simple" which even back in the day was a misnomer. The fact that all mention or pretence of it being simple has gone out the window is symptom.

Here's a particularly egregious example of a SOAP structure I'm familiar with but I must stress I did not design:

<?xml version="1.0" encoding="UTF-8"?> <SOAP-ENV:Envelope xmlns:SOAP- ENV="<http://schemas.xmlsoap.org/soap/envelope/>"> <SOAP-ENV:Body> <MarkLastPhotoInRollResponse xmlns="<http://localhost/api/soap/eyefilm>" /> </SOAP-ENV:Body> </SOAP-ENV:Envelope>

That's what? More than a hundred bytes of data to encode what can only be described as one byte of payload? Insanity.

REST has some good points to make. There's a lot of importance in not trying to impose excess state in applications that are primarily going to be used over HTTP talking to traditional web servers. However, the best thing about REST is that it doesn't say _anything_ about how the data ought to be encoded.

Of course people can abuse this by using pointless and stupid formats like JSON, but hey if you don't want your application to have reasonable performance, it isn't my problem.

Those of us who still have to worry about CPU cycles and RAM and the cost bandwidth realise that you can define data formats that have useful properties like streamability, that is to say you can define parsers with the semantics /Either read this structure now if you have enough data, or call me back when you do have enough so I can parse it then./ A property I consider paramount in any asynchronous application that uses the network, but is completely lacking in XML. That also gives you the option to skip structures without parsing them, which is helpful. Then there are issues like widths of integers, which people are inclined to forget about when using modern scripting languages. Of course, this all comes back to bite people when they try to use a horrid language like PHP which secretly actually has a fixed width for its integers, but neglects to tell you what it is and has no syntax that lets you choose to be signed or unsigned. _sigh_</comment></comment>


Where to get a cost effective 500GB of durable cloud storage? - <AUTHOR>

I am consolidating my personal backup strategy and am looking for the best deal in durable offsite storage.
The best deal I've found so far is Amazon EBS mounted on a spot priced micro EC2, which is about $55 / month in total for 500GB.
Given the cost of raw HDD storage, I'm sure I can do a lot better than this.
What good alternatives do others use?
NB1: I have OSX and Linux servers to backup
NB2: Backblaze would be awesome, but it doesn't support Linux or have an API yet. <comment><USER2> I just lease a dedicated atom based server from interserver with a 1.5 TB sata drive in it. It comes to $49/month.

I end up using it for lots of other stuff like a vpn host so that I have an american IP when overseas, a small web server for personal projects, an always on VOIP switchbox to route from one number to all my cell phones, and a git host with gitolite for code.

For backup, I just use a bunch of rsync scripts that dump onto the big disk.

IMHO, everyone should have a personal server in some datacenter somewhere.

<comment><AUTHOR> That's a great idea! Not quite durable storage but I do see they offer a second HDD for an extra $20.

</comment></comment><comment><USER3> Amazon S3 with reduced redundancy will cost about $45.00 per month plus the cost of the initial data transfer in. EC2 with a reserved Linux micro instance and 500 GB of EBS storage will cost more at about $60.00 plus the cost of the initial data transfer in.

A couple of months agao, I went through the same research as you and it is hard to beat S3 storage costs and ease of use. My requirements are more modest at about 100 GB per month though.

There is a handy Amazon calculator here: <http://calculator.s3.amazonaws.com/calc5.html>

<comment><AUTHOR> Thanks. Yeah I use EC2 for other things, and you're right. Reduced redundancy S3 is at least as good as a RAID1 dedicated server, possibly even better[1].

 _1\. Amazon S3 standard storage is designed to provide 99.999999999% durability and to sustain the concurrent loss of data in two facilities, while RRS is designed to provide 99.99% durability and to sustain the loss of data in a single facility._

</comment></comment><comment><USER4> Rackspace Cloud Files.

<comment><AUTHOR> At 15c/GB/mo Rackspace Cloud is the most expensive option at $75/month</comment></comment>


Employee or independent contractor (good technical overview) - <AUTHOR> http://www.mofo.com/files/Uploads/Images/100326ELC.pdf

<comment><USER2> Here is a good article with tax advice for individuals:

<http://www.biztaxtalk.com/node/3#ruIC>

</comment><comment><USER2> Hey Joel, how about a legal and tax Stack Exchange by state? This is the type of material I would expert to find in there.</comment>


How our startup Textingly POWNED the Libyan War - <AUTHOR> http://daviddundas.com/post/4495476612/how-our-startup-powned-the-libyan-war

<comment><USER2> I may just be over-sensitive, but this post seems a little too cavalier about the Libyan crisis to me. In addition, I had the impression that this piece might be about some kind of "hack" for humanitarian purposes, or something like Google's work to help people in Japan to connect after the earthquake and tsunami.

I am no stranger to writing somewhat more compelling titles to blog posts, but I feel like this attempt has misfired.</comment>


Ask HN: Uber Fare Adjustment Rip Off - <AUTHOR> This week we flew into France. When we got to the airport, we took an Uber to our AirBnB, which was supposed to cost $17.38. Later in the day, we got an email saying our fare was "corrected" by adding $3.26 "du prix de la course", which I believe means traffic.
The only thing was, there wasn't traffic. Our trip was supposed to take 16 minutes and actually took 16 minutes.
I googled around and it looks like Uber drivers are systematically requesting fare adjustments in order to increase their overall earnings.
Now...my issue with this is not the money or even that fare adjustments exist. Riders should pay for unexpected traffic and should probably pay more for Uber overall. My issue is that Uber is not supposed to be a shady taxi service. I don't want to get to the end of my trip and find out it's 20% more than I was promised for absolutely no reason.
Has this happened to anyone else? <comment><USER2> This sort of thing happens from time to time. Just send a dispute and move on, I've never heard of a dispute being denied.

</comment><comment><USER3> Haven't happened to me ever, but then I've never used Uber in France.

Is there anything you can do in the app like raise a dispute, etc?

If not, for 3.26$ I'd just let it go and leave a 1-star review to the driver. Such a review can cost the driver a lot more than 3,26$ so it's actually some sweet revenge.

<comment><USER4> Problem with that approach - it absolutely does not change anything and does not protect you from having that happening again and again.

</comment></comment><comment><USER5> I did, took an Uber in Bangkok and there are occasional highway tolls, which I paid the driver 50 baht (~$2) cash for on the spot. I guess he forgot or decided to get a little extra cause he adjusted the fare to include it after. Simply filed a ticket and got reimbursed.

</comment><comment><USER6> What did Uber say when you opened a ticket with them?</comment>


Impact JavaScript Game Engine for iOS - <AUTHOR> http://www.phoboslab.org/log/2010/10/impact-for-ios

<comment><USER2> "The JavaScriptCore Framework is still private on iOS. So as it is now, I won't be allowed to distribute the game in the AppStore. But my understanding is, that if I bundle my own copy of the JavaScriptCore Framework (which is part of WebKit and thus freely available) with my game, I should be on the safe side."

This is true. You _can_ compile Javascript Core and include it in your app. I have done this previously as an experiment.

However, there is one HUGE drawback in doing so: no compiled/jitted javascript code is possible.

This is because iOS applications are not allowed to create executable code in the heap or on the stack, so there is no way for JavaScriptCore to compile to native code when it is running as part of a third party application.

So unfortunately there is no good way to get this going at the same speed that you get when linking against the private framework.

Sad. This is also a major problem for other scripting languages. They all can only run in interpreted mode. Which might be good enough but is never the best you can get.

<comment><USER3> Yep, I hit this roadblock too. For my similar project I ended up using a non- jit version of Spidermonkey for embedded Javascript. Interpreted performance is pretty poor in comparison to jit though, and I ended up moving to a much higher level Javascript API to share between canvas and native implementations. It runs at 60 fps on 2nd gen hardware now with moderate (1 - 2 hundred sprites).

<comment><USER4> Just thinking out loud:

I wonder how feasible it would be to pre-compile the Javascript to machine code before distributing it? Maybe someone determined enough could probably hack one of the existing JIT engines to emit executable machine code to a file?

<comment><USER3> For a restricted subset of Javascript it wouldn't be that hard.

I'm not sure that solves the iphone problem though - I don't think it's kosher to use non c/c++/objc code. A Javascript to C compiler would work fine, though. That would be quite a bit more work, though.

[Edit]As pointed out below, it might well be ok. I guess you'd have to somehow get the generated machine code into a static library and link it with your application. That might work.

<comment><USER5> It's kosher now, as of Apple's recent changes to their developer agreements.

</comment></comment></comment></comment></comment><comment><USER6> Summary: Technology demo wherein the author takes a Javascript game, runs it as an App (no browser) using OpenGL instead of <canvas> and the Javascript interpreter already in the iPhone for the drawing and gets 60fps.

• The Javascript interpreter interface used is considered private and thus the app can not be distributed in the store.

• There is a history of private to public interface transitions, so perhaps…

• It suggests you could have all the game code be common between a web and a higher performance app version of a game.

• No word in the article about what percent speedup this represents.

<comment><AUTHOR> The speedup is substantial, at least in this case. Biolab Disaster has to draw lots of small 8x8 pixel squares (about 500 for each frame) to produce the background map - which seems to be awfully slow in the iOS browser.

Running in the browser, I had about 10 frames per second as noted in my previous blog post: <http://www.phoboslab.org/log/2010/09/biolab-disaster>

</comment></comment><comment><USER7> So it sounds like the source code for game is written in pure javascript (utilizing any special APIs calls provided by Impact). This javascript src is packaged using the Impact Game Engine which creates a Obj-C wrapper around the javascript. When the Game is loaded on an iOS device and run, the Obj-C wrapper (implemented by Impact) executes the javascript src via JavascriptCore.

It sounds like this is basically a Canvas to OpenGL translation layer.

Can only the Canvas object be leveraged when creating games/apps with this? Or could a "account creation" screen be created leveraging HTML elements like forms (I would assume not since its sounds like its executed outside of Safari, and the translation provided is from Canvas > OpenGL)

<comment><USER8> Yah, the original game is all in pure javascript written to the canvas. I have been poking around with making canvas apps and a few weeks ago I grabbed the source and spent a few hours reading through all of it. Good stuff. If the author wasn't in Poland (corporate doesn't have an office there) I would try to hire him.

</comment></comment><comment><USER9> There's a lot of interest in the mobile and JavaScript communities for a JavaScript engine you can distribute on iOS. Games are one thing, but with this you could take cross-platform, natively packaged web apps to a whole new level.

<comment><USER10> Sort of like an even more native Titanium Appcelerator? < <http://appcelerator.com> >

<comment><USER9> Exactly, or like PhoneGap. For example, you could write an Appcelerator or PhoneGap app and call into native code from a JavaScript bridge. Right now, each native API needs to be explicitly wrapped by Appcelerator or PhoneGap.

</comment></comment></comment><comment><USER11> Can someone summarize the impact (no pun intended) of this?

<comment><USER12> Make multimedia software, generally games, for iPhone/iPod Touch/iPad using javascript and html5 canvas and make it run almost as fast as a native version.

<comment><USER13> It _is_ a native app: it uses JavaScriptCore and all Canvas calls are rendered using OpenGL. The implications are that if you write a game for Impact engine you can generate an iOS native app.

<comment><USER14> It's not quite that simple, though, from the sound of it - the author said he had to 'reimplement' all the canvas calls to use OGL. Fine if you're familiar with it, but for those people who just want to bash out a Javascript game without having to worry about the engine, they might have trouble.

<comment><AUTHOR> So far I only reimplemented those Canvas API functions needed for the game; the most important one being .drawImage().

What I mean by "reimplement", is providing a .drawImage function for JavaScript that works in the same way as it does in the browser, but uses OpenGL-ES behind the scenes. This reimplementation is done in native Objective C.

The changes I had to make to Impact (the "HTML5" engine) are concerned with the loading of images, scaling, input and getting a reference to the canvas element and its drawing context. But I guess I could provide a dummy "document" and "getElementById" function, so that you can just write some JavaScript using Canvas and run it in the browser and on the iPhone unchanged.

Note that this whole idea isn't exactly new: <http://www.youtube.com/watch?v=0UN2iYrZmEY></comment></comment></comment></comment></comment>


Ask HN: Do you use a self hosted private registry? - <AUTHOR> If you do which one and why? <comment><AUTHOR> I'm the founder at Distelli and I'm trying to get an idea if folks use self hosted private registries and if so why? Or is the overwhelming usage in the cloud (ECR, GCR etc).

If you do use a self hosted what led you to that decision (and which one).

</comment><comment><USER2> I pay for quay. ECR is horrible in my opinion. It dosen't even support v2 yetand you need an api request to create the repository before you can push to it. Been meaning to try GCR</comment>


Major Report Prompts Warnings That the Arctic Is Unraveling - <AUTHOR> https://www.scientificamerican.com/article/major-report-prompts-warnings-that-the-arctic-is-unraveling1/ <comment><USER2> A new Canadian naval base is being constructed in Nanisivik, Nunavut I was reading about the Alert base and saw info on the new base at Nanisivik.

The new base is almost right in line with the Northwest Passage so I assume it's meant to police it just in time for the big melt.

</comment><comment><USER3> On one hand, Russia may soon finally have year-round maritime access that can't easily be blocked by other powers. On the other hand, will it still be able to count on its winters to shut out invaders?

I wonder what all of this will portend.

<comment><USER4> They do have 1000s of miles of pacific coastline. I wonder why they don't develop that more militarily?

Everyone seems to ignore it.

<comment><USER5> Russia's Far East is basically colonies that never decolonized. Most of Russia is situated in its Europe, and its hinterlands have notable density only along roughly the region of the Trans-Siberian Railroad once you get past around the Irtysh River (western tributary of the Ob). Even past Lake Baikal, Vladivostok, Khabarovsk, and Yakutsk are virtually the only cities.

Vladivostok was developed heavily, as Russia's only ice-free ocean port, but most of the rest of that region is far too sparsely populated. It's telling that, in modern times, Russia is quite paranoid that China is planning an invasion and takeover of that area.

</comment></comment></comment><comment><USER6> We have climate deniers, and we have another group of people who don't want to spend money to solve the problem; probably the Republican party. Global warming simply isn't a priority.

More important problems than global warming. Skip to minute 6:

[https://www.ted.com/talks/bjorn_lomborg_sets_global_prioriti...](https://www.ted.com/talks/bjorn_lomborg_sets_global_priorities)

<comment><USER7> Right, but they also want to _spend_ money to accelerate the problem. With just a dozen years of subsidy, we're now at a point where unsubsidized the solar and wind industries do better than the still heavily subsidized fossil fuel industry for everything but the midsized high-output applications (e.g., trucks & shipping) and some specific industrial cases.

The first would could do commensurate good by spending its enormous resources accelerating the reliance on renewable resources. So this argument against Kyoto (which is indeed a proposal that is more a gesture than a solution) is basically used to dismiss other things.

For example, Trump's proposed to wipe out the EV tax credit (please don't, I want my tax credit!) in the US. It'd reclaim less than a billion dollars but substantially deter the uptake of EV cars.

Similarly, the US is facing a grim truth that even it cannot maintain its entire massive infrastructure in the face of modern economic challenges. Renewable resource generation offers an alternative, distributed power grid. Between this and modern manufacturing techniques, we see a glimpse of a future where socialists, centralists and anarchists all see a world resembling more of what they want, with regional control and generation of power resources and control over economics, but a framework left in place for a top down government to govern things that are advantageous overall (central planning for scarce resources & conservation, rights and health care, etc).

Resistance to the topic on the grounds that Kyoto is bad is over-applied to all attempts to grapple with climate change, even when they actually have huge positive effects only tangentially related.

<comment><USER6> "Trump's proposed to wipe out the EV tax credit (please don't, I want my tax credit!) in the US. It'd reclaim less than a billion dollars but substantially deter the uptake of EV cars"

Hmmm. I guess you don't understand that many Republicans don't like the idea of government subsidies. If it comes down to subsidies, we aren't going to solve the problem, according to this economist:

[https://youtu.be/pQSGuC9GF70](https://youtu.be/pQSGuC9GF70)

<comment><USER7> Republicans have no problem subsidizing industries that they like.

What they dislike is competition. Weirdly, the Democrats morphed into a weirdly lightweight party on regulation of markets and the Republicans continue to grow towards something that incrementally becomes a planned economy.

And let's just reiterate: less than a decade of subsidizing renewables kicked it over an economic hump and we've accelerated it to the point where it's actually radically changing first world economies. So anyone saying that subsidies "don't solve problems" is clearly using a different definition of "solve", "problem", and maybe even "doesn't."

<comment><USER8> >Republicans continue to grow towards something that incrementally becomes a planned economy.

This is worth repeating twice, in case people missed it. The irony would be funny if it weren't so damn catastrophic.

<comment><USER9> There is no irony. They just wanted the centrally-planned oligarchy to be privately owned.

<comment><USER8> Maybe I was unclear: the irony is in the fact that the Republican party loves to appeal to the communist boogyman, all the while vying for a planned economy (albeit at the hands of private actors).

This is ironic because much of their apparent hatred for socialism/communism stems from the idea that these lead to planned (i.e. non-free) economies.

</comment></comment></comment></comment></comment></comment></comment><comment><USER10> [http://realmode.com/glaciers.html](http://realmode.com/glaciers.html)

</comment><comment><USER11> > Air-temperature data from 2000 to 2014 show that parts of the Arctic are now > 3 deg C warmer as compared to the 1971-2000 baseline.

29 years constitutes a baseline.

<comment><USER12> You have to put zero somewhere. "Baseline" does not imply normality or desirability.

<comment><USER11> > "Baseline" does not imply normality or desirability.

I agree with you that it does not. However, the article (and climate reporting in general) implies that it does.

<comment><USER12> I thought they usually used "pre-industrial" as the "normal" level for things like temperature and atmospheric CO2.

<comment><USER11> "They" is quite vague. But let's run with it for a moment...

Was the temperature and CO2 level stable before the Industrial Revolution?</comment></comment></comment></comment></comment>


Ask HN: What would you like to know about typing biometrics? - <AUTHOR> Hi! I was wondering what would you like to know about (or around) the field of typing biometrics (also known as keystroke dynamics). <comment><USER2> How can this technology, and the data it collects, be used against individuals for purposes such as discrimination? For example, against slower types could be discriminated against.

Do you see this being a centralized service such as through Google so that a profile can follow a user from company to company as well as offline. How do you see that centralization impacting anonymity on the internet? Along those lines, how long has the NSA been using this on us?

</comment><comment><USER3> I would like to know how typing biometrics handles injuries that affect my typing pattern such as breaking an arm or a finger.

<comment><AUTHOR> Does this article answer your question, or would you want to know something more? [https://blog.typingdna.com/what-if-your-typing-pattern- chang...](https://blog.typingdna.com/what-if-your-typing-pattern-changes/)

<comment><USER2> So if I switch between single hand typing and two hand typing, I would have to use a different/secondary authentication method?

<comment><AUTHOR> If the typing pattern is disproportionately different (as it may be the case between switching from single to two hand typing), you would need a fall-back or risk not being authenticated. Or, you could retry typing as you would usually do during an authentication.

<comment><USER2> So if there are scenarios where you need a fall back, why not just use the fall back?</comment></comment></comment></comment></comment>


Tell HN: Skype on web does not support Firefox - <AUTHOR> The Skype for web -> https://web.skype.com/ does not support Firefox. Urges the user to use Microsoft Edge or Chrome. <comment><USER3> The worst is that just changing the user agent makes everything work.

<comment><USER4> Are we back to the "built for Netscape 4.7" days?

Sites shouldn't support browsers, but standards. By all means check if a browser supports a certain standard, and provide an error message for browsers that are too far behind, but don't ban them simply for having the wrong user agent.

<comment><USER5> I think so. A solution to this might be to croudsource an extension which changes the User Agent on known good apps (where changing it _just works_ but they've decided not to let you use it).

<comment><USER6> > known good apps

Correction: known bad apps (where changing it just works but they've decided not to let you use it).

I consider it very shameful behavior, sabotaging the internet.

<comment><USER5> Well I meant it as 'apps that work good' when changing the UA string.

But you are right.

<comment><USER6> I kinda got you, just think that they do not deserve the word "good" at this point :)

</comment></comment></comment></comment></comment></comment><comment><USER7> You can expect to see more and more of this as most of the world converges on the Chromium browser base. There is very little incentive for these companies to test for Firefox. Device users have spoken. They do not bother to change the defaults that come with their devices (Chrome, Edge, Safari) and do not really care about the deeper aspects of privacy or control or FOSS. At most they care about blocking ads, which is not a compelling reason to switch.

<comment><USER8> Getting rid of ads IS a compelling reason to switch. People will switch if the default is better. They dont want to get a new browser, pick and install an ad blocker, then configure that stuff.

People will stop at the slightest uncertainty. I bet if there was a one-click to install firefox with ad-blocker and some other stuff enabled by default people would start switching.

Installing, extensions, configuration, those are sysadmin function, not stuff Joe public wants to do no matter how easy the developers think they are.

<comment><USER9> >I bet if there was a one-click to install firefox with ad-blocker and some other stuff enabled by default people would start switching.

Check out Brave, been getting my friends to switch as it has a built in blocker that is even more verbose than ublock. Works on mobile as well which helps them save data and load websites faster.

[https://brave.com/](https://brave.com/)

<comment><USER10> > has a built in blocker that is even more verbose than ublock

I don't understand this sentence. What does "more verbose" mean?

<comment><USER9> I guess what I meant was that it shows you a lot of details of what trackers are being blocked with individual switches for cookies/scripts etc, which is nice for users who may not be as tech literate.

[https://imgur.com/a/REAStmy](https://imgur.com/a/REAStmy)

</comment></comment></comment></comment></comment><comment><USER11> "Urges the user to use Microsoft Edge or Chrome."

Meaning "Chrome only" is the strategy here (since Edge, mshtml.dll, as unique rendering engine will disappear).

Welcome back to the past - have seen this all before in the late 90s.

<comment><USER12> Suddenly it's okay to develop for just one browser again. Even though browsers are lot more standardized now than they were before, it's still okay to do it. Bizarre.

</comment></comment><comment><USER13> LinkedIn too behaves strangely on Firefox/Ubuntu. Endless login loop, even if all add-ons are disabled. I'm surprised that such popular websites treat Firefox so poorly.

<comment><USER14> Fellow Firefox/Ubuntu user here. Are you blocking Captchas somehow? This is usually my problem (and specifically very recently with LinkedIn, hence the comment).

<comment><USER13> I don't think I have changed anything related to captchas, at least not intentionally.

I see a lot of "Request to access cookies or storage on [https://www.linkedin.com/](https://www.linkedin.com/) was blocked because of custom cookie permission." in console.

However, my Preferences > Content Blocking is set to "Standard"; no add-ons are enabled; not a private window. I have DNS-over-HTTPS enabled. There are no linkedin-related entries in about:config.

<comment><USER15> The list of cookie exceptions (deny or allow) isn't stored in about:config. Try these steps?

[https://developer.mozilla.org/en- US/docs/Mozilla/Firefox/Pri...](https://developer.mozilla.org/en- US/docs/Mozilla/Firefox/Privacy/Storage_access_policy/Errors/CookieBlockedByPermission)

</comment></comment></comment></comment><comment><USER16> Skype has been truly rubbish lately anyway. I generally use free whatsapp calls over my paid skype credits because it's such a stark quality difference.

No idea what they're doing but it's terrible.

</comment><comment><USER17> Also, Skype for Business is being replaced with Microsoft Teams. Bold prediction : Skype has less than five years of life left.

<comment><USER18> You wager they'll shut down the consumer facing portion too? It's a fairly decent brand. Although I guess with VoIP so ubiquitously free (WhatsApp, etc) I'm not sure how they monetize these days...

<comment><USER19> It's a well-known brand but Microsoft have dragged it through the mud since they acquired it and among those I know it now has a reputation for being extremely unreliable. They might want to retire it rather than fight to rehabilitate its image.

<comment><USER18> True, on second thought, I found myself saying let's Skype soon and end up using some other app during facetime...

</comment></comment></comment></comment><comment><USER20> Original Skype for Web developer here. I was part of the launch team who built the first version for this product in 2014[1]. Back then we supported Chrome, IE 9+, Safari and Firefox. Already we had internal debates to support Opera, but the decision was to focus on the largest browsers.

For each browser, we had to add support in our standalone plugin, that was (and still is) required to install for audio/video calls. There was a small maintenance cost per browser, which was a bigger one whenever changes to the plug-in were made.

I left Skype/Microsoft a long time ago and Microsoft announced in March they will drop support for Firefox[2]. I can only speculate, but it's likely due to not wanting to pay the maintenance cost of this product on an ongoing basis.

 _Not directly related story from building Skype for Web:_ a big internal battle those days was us vs the Edge team. We wanted Edge to ship the Skype plugin as default, making calls seamless for Edge users, not needing to install a plugin (we saw large drops in adoption due to this plugin). Chrome already did exactly this with Hangouts back in the day and we saw it as them eating our lunch.

This was at the time of Steve Balmer's Microsoft, where collaboration between different orgs was difficult and facing strong political headwind. We got nowhere with the Edge team, who wanted no dependencies and prioritised performance above anything like this - and also wanted to hit their own KPIs, which had nothing to do with Skype users preferring to use Edge.

We reasoned, pleaded, argued, steamed, shouted names and even used the "C" argument ("but... but... but... even Chrome does it!"). No avail. So a separate plugin install it was, giving people zero incentive to use a Microsoft browser for a Microsoft product. The Edge team were pleased they did not have to cater for another dependency and their roadmap remained unchanged. We were frustrated and had little doubt which brodwser will keep gaining market share - being certain it will not be IE/Edge.

 _Other not directly related story_ : a few years ago I wrote in detail my take on why Skype failed, here on HN. Read it on this thread: [https://news.ycombinator.com/item?id=10927600](https://news.ycombinator.com/item?id=10927600)

[1] [https://www.google.co.uk/amp/s/www.theverge.com/platform/amp...](https://www.google.co.uk/amp/s/www.theverge.com/platform/amp/2014/11/14/7219779/skype- for-web-beta-launch) [2] [https://arstechnica.com/gadgets/2019/03/microsofts- new-skype...](https://arstechnica.com/gadgets/2019/03/microsofts-new-skype- for-web-client-an-early-taste-of-the-browser-monoculture/)

<comment><USER5> > no dependencies and prioritised performance above anything

Edge was in a weird position where it somehow looked fast but _felt_ sluggish. A real shame it didn't work out though.

<comment><USER21> It was sluggish and hung for no reason. It was super bare boned and still slow. So, if I installed the same number of extensions as I have on Firefox, it would grind to a halt. I guess that's what we get when they prioritize looks or design over functionality.

The most annoying part for me was updates. They supposedly created Edge as a browser decoupled from the OS unlike Internet Explorer. They claimed that with Edge, they would be able to iterate quickly with regular updates - <USER2> Chrome.

Yet, for 4 years, updating edge required a major OS update AFAIK.

</comment></comment></comment><comment><USER22> I gave up on Skype a long long time ago. Aside from the dumpster fires of their clients, their attempts to manage the spam/bot problem make legitimate use nearly impossible because they keep disabling "new, lightly used" accounts.

</comment><comment><USER23> Instead of switching the browser. I switch the app. In this example I stopped using skype. Whoever wanted to contact me on skype, I simply say that I don't have an account there. Let's meet somewhere else.

</comment><comment><USER24> Jitsi Meet supports Firefox.

[https://jitsi.org/jitsi-meet/](https://jitsi.org/jitsi-meet/)

<comment><USER25> Looks cool. How does jitsi make money?

</comment></comment><comment><USER26> Tweeted them about this, their response: "Request/vote for this feature on our community site", with the following link: [https://skype.uservoice.com/forums/914527-welcome-to- skype-i...](https://skype.uservoice.com/forums/914527-welcome-to-skype- ideas/suggestions/36658774-preview-firefox-support)

<comment><USER27> I don't know what "Preview" is but it sounds more specific than supporting Skype for Web in Firefox overall. There are a number of other UserVoice ideas about Firefox support. Microsoft should consolidate the ones that are essentially saying the same thing.

[https://skype.uservoice.com/forums/914527-welcome-to- skype-i...](https://skype.uservoice.com/forums/914527-welcome-to-skype- ideas?query=firefox)

</comment></comment><comment><USER28> Also not supported in Safari. That's fine, I wasn't going to use Skype anyway.

<comment><USER29> That's a larger problem since Safari has a larger userbase. Mozilla is generally at 5% Safari has been at 7-8%. Collectively, Microsoft is fine with losing potentially 12%

<comment><USER30> Yeah but to support safari, you need a way to test your web application with it.

The only way to do that is to buy a Mac. That's why a lot of sites don't support it.

<comment><USER28> I think Microsoft can afford it. I heard at some point they were Apple's largest corporate client for Macintoshes.

</comment></comment></comment></comment><comment><USER31> If it only support chrome and derivatives, it should be called Skype on Chrome not Skype on Web

</comment><comment><USER32> I remember reading about this in the early 00's when msn.com and some other MS websites did the same. Changing the UA made the site work just fine.

History repeating itself.

</comment><comment><USER33> Yeah, it's pretty lame these days when web apps don't bother to go the extra mile. The text chat feature still works so maybe they'll add video support soon? Honestly I'd rather use Skype in the browser instead of installing it. It's nice to have that stuff alongside webmail and office apps. I'm also an avid Firefox user and won't switch from them. Mozilla has done amazing work advancing web technology.

</comment><comment><USER34> You can spoof your UA and it'll work, at least for audio, and maybe video, IIRC. Not really an answer though I know.

</comment><comment><USER35> I use this - [https://mybrowseraddon.com/custom-useragent- string.html](https://mybrowseraddon.com/custom-useragent-string.html) \- to fake Chrome UA and it works. You only need it faking your UA to open the web version of Skype then you can change it back.

</comment><comment><USER36> Can someone explain me why Skype needs a plugin to be installed to use it over the web? WebRTC/Sip.js works pretty well these times across all (major) browsers I think?

</comment><comment><USER37> This is really annoying because Skype video inside a Windows VM basically doesn't work. Encoding/decoding probably falls back to software and is much too slow.

</comment><comment><USER38> who is using skype anyway?

<comment><USER39> Skype has 300 million monthly active users [https://techcrunch.com/2019/06/05/skype-publicly-launches- sc...](https://techcrunch.com/2019/06/05/skype-publicly-launches-screen- sharing-on-ios-and-android/)

</comment></comment><comment><USER40> Would be interested to know how successful they are at switching people to Edge (not just with this, but in general).

<comment><USER14> I recently had to use Windows 10 for some .NET work and found it really surprising that it nags so much when changing the default browser. Not just in the control panel prompt, but repeatedly afterwards via notifications and even on the login screen.

Hint: Your OS shouldn't do this. It should stay out of your way and honour your choices.

<comment><USER41> The Windows login screen does other startling things, too. I have also seen it display sneaky advertising for Netflix.

</comment></comment></comment><comment><USER42> Thanks for the info!

</comment><comment><USER43> Same thing with GoToMetting

</comment><comment><USER44> It's happening!

</comment><comment><USER25> OT, but check out the comments in the code. It doesn't instill confidence:

        // Adjusts the position of the given element
        WebDeveloper.Common.adjustElementPosition =
           function(element, xPosition, yPosition, offset)
        {
          // If the element is set
          if(element)
          {
            var contentWindow = WebDeveloper.Common.getContentWindow();
            var innerHeight   = contentWindow.innerHeight;
            var innerWidth    = contentWindow.innerWidth;
            var offsetHeight  = element.offsetHeight;
            var offsetWidth   = element.offsetWidth;
            var offsetX       = contentWindow.pageXOffset;
            var offsetY       = contentWindow.pageYOffset;

            // If the x position is less than 0
            if(xPosition < 0)
            {
              xPosition = 0;
            }

            // If the y position is less than 0
            if(yPosition < 0)
            {
              yPosition = 0;
            }

            // If the element will fit at the x position
            if(xPosition + offsetWidth + offset + 5 < innerWidth + offsetX)
            {
              element.style.left = xPosition + offset + "px";
            }
            else
            {
              element.style.left = innerWidth + offsetX - offsetWidth - offset + "px";
            }

<comment><USER45> one may snicker at the redundancy of the "is less than 0" pair and so son, but I'm grateful for "if the element will fit at the x position." It puts into words what isn't obvious from the code.

<comment><USER25> Fair enough. But if they are going to do that, wouldn't a comment about what the positions are in each case (especially the case where it doesn't fit) be helpful?

        // If it fits, put it there.  If not, align to the right side

or whatever.</comment></comment></comment>


Wired Bacteria Form Nature's Power Grid - <AUTHOR> https://www.nytimes.com/2019/07/01/science/bacteria-microbes-electricity.html <comment><USER2> For some reason this makes me think these bacteria or the mechanism behind them are the biological precursors to neurons.

<comment><USER3> You want Micheal Levin's work:

E.g. "What Bodies Think About: Bioelectric Computation Beyond the Nervous System as Inspiration for New Machine Learning Platforms"

[https://media.neurips.cc/Conferences/NIPS2018/Slides/Levin_b...](https://media.neurips.cc/Conferences/NIPS2018/Slides/Levin_bioelectric_computation.pdf)

"What Bodies Think About: Bioelectric Computation Outside the Nervous System - NeurIPS 2018"

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

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

</comment></comment><comment><USER4> Two thoughts:

1) A lot of unscientific tribal belief systems inherit the existence of a networked planet. Perhaps at one point there was a scientific understanding of this, sometime before 6,000 BC which seems to be our cutoff from older knowledge.

2) If there was alien life here, I could see many circumstances where they are intentionally ignoring humans or not prioritizing interaction with us. We wouldnt know and just assume theyd want to interact with us and that we would be able to detect and differentiate them, it seems more likely that populating and surveying underwater and subterranean earth would be more fruitful and more interesting.

<comment><USER5> I don't understand why you are being downvoted. You clearly marked your post as unscientific, and the idea is interesting.

<comment><USER4> thanks, sometimes the consensus behavior is a vendetta against something I said in another thread on a different article</comment></comment></comment>


The Future Of Better-Designed Enterprise Software - <AUTHOR> http://www.fastcompany.com/1805277/what-enterprise-software-should-crib-from-facebook-amazon

<comment><AUTHOR> My startup (CubeVibe) was mentioned in this article on the changes coming to enterprise software. I know enterprise software is considered boring by the TechCrunch masses, but I think it's pretty exciting. And you know there is a lot of room for improvement if you've ever worked with (any) enterprise software.</comment>


So, if not Electron apps, then what? - <AUTHOR> I'm trying to get some data on building a cross platform desktop app. It's to help devs in my company by giving a GUI for few tasks. But I don't want to suck up their RAM. What are the other alternatives that come close to electron in terms of productivity while consuming low memory? <comment><USER2> Tk is pretty fast. It has bindings in multiple languages, though I'd suggest TCL. There is a starkit idea floating around, where people package a binary for each platform along with any other dependencies. It is much lighter than electron.

edit: to be clear, one clickable thing that works on mac, windows, linux, and... maybe arm? there is an androwish, but I haven't tried it.

</comment><comment><USER3> Tbh I'm surprised React Native hasn't been brought to Desktop yet. It solves the problem with nice compromises imo, and gives a great native experience in the ui layer.

<comment><USER4> People are trying

      https://github.com/Microsoft/react-native-windows
      https://github.com/ptmt/react-native-macos
      https://github.com/status-im/react-native-desktop

But without top-level standardisation effort it will not work.

</comment></comment><comment><USER5> Qt, Gtk, Tk, wxWidgets, Delphi (whatever the open source one is). All have pros and cons depending on your needs but you should be able to throw something pretty serviceable together pretty quickly. The biggest catch for most is the reliance on c/c++, but if you want to be lean on memory then you probably want this anyway.

Some of these are heavyweight, others are just wrappers for the native libraries.

If this is a dev tool I wouldn't rule out a curses based TUI app either.

<comment><USER6> > curses based TUI app I really love these

</comment></comment><comment><USER7> FreePascal with Lazarus. You can create native apps (including mobile apps) all with one Object Pascal code base. If you want a commercial product and are on Windows you could always use Delphi as well.

</comment><comment><USER8> JavaFX, especially when used with Kotlin and TornadoFX, is really nice.

We're now at the point where you can bundle your app, JVM pieces needed, into a single distributable for each platform. With Graal and whatever else on the horizon there might even be just plain compiled-to-native options coming too.

If you don't like the JVM ecosystem I think QT also has potential but it seems much more difficult and labor intensive to create a decent application.

</comment><comment><USER9> Nothing really. If you don't want to sacrifice productivity then you go the electron way. Java/Swing has horrible UI/UX and doosen't offer any real benefits on RAM. QT is good if you are willing to pay for the licensing costs for commercial use or you open source your app. Everything else that is cross platform works, until it dosen't. Good luck debugging gtk on windows.

If you can spare the resources, create per platform apps. If not, then electron is your only headache less option.

<comment><USER5> > QT is good if you are willing to pay for the licensing costs for commercial > use or you open source your app.

Qt is LGPL, you can use it commercially for free.

It sounds like this is for an internal app they don't plan to distribute, so even the GPL would be fine and not require them to open source it.

</comment></comment><comment><USER10> The idea of using web views for the UI is valid IMO. The problem is that Electron brings a ton of metal with it (Chrome + Node).

A solution is to create your own Electron by creating the UI with HTML/CSS/JS and using the OS native APIs for the window and "back end" code.

Depending on your use case it might be feasible to do that yourself, or use a project like NodeKit.

[https://nodekit.io/](https://nodekit.io/)

</comment><comment><USER11> What does the app do? How much RAM do the company machines have?

Personally, I'd take the hate about Electron here with a huge pinch of salt. RAM isn't expensive, developer machines tend to have a lot of RAM and you're only wanting to launch a single app. A minimal Electron app takes about 100MB of memory which isn't much if you've got e.g. 8GB of RAM.

</comment><comment><USER12> How about this?

[https://github.com/zserge/webview](https://github.com/zserge/webview)

C/C++/Golang webview. Build your UI in html/js and offload any heavy tasks to compiled languages. There's also a rust binding on github.

The sample app shows what you can do

</comment><comment><USER13> I use TornadoFX daily and its a joy to use.

<comment><USER14> This looks great, thanks for bringing it to my attention!

</comment></comment><comment><USER15> Depending on what you're trying to do, Xojo might be a good choice: [https://www.xojo.com/products/desktop.php](https://www.xojo.com/products/desktop.php)

Others have mentioned Qt/QML, another solid choice.

</comment><comment><USER16> Love2D with a GUI (lua): [https://love2d.org/](https://love2d.org/)

miniSpere (js): [http://www.spheredev.org/](http://www.spheredev.org/)

</comment><comment><USER17> Why not a web app?

</comment><comment><USER18> What's the financial ROI effort spent to "save Ram" on developer's computers versus just adding hardware capacity to those same computers? The ROI should include productivity gained lost based on delivery schedule, the costs of ongoing app maintenance, the cost of finding developers in whatever alternative to electron is chosen, the value in terms of security and bug fixes that a mainstream project like Electron provides, and the economic value of having RAM on developer computers available for other business productive purposes. My gut assumption is that $200 of RAM upgrades across 50 developers is probably cheaper, but I could be mistaken. Good luck.

<comment><USER19> Not everyone can upgrade their RAM without switching to new hardware, and the company's probably not going to invest in that across their entire dev team just to accommodate one new internal app unless it's truly mission-critical. And heck, Mac laptops _still_ max out at 16GB.

And it's not just RAM. Electron rendering is slowwwww.

<comment><USER18> I don't disagree that there may be a hardware upgrade. My point is that without running numbers increasing development, maintenance, and risk in order to "save RAM" is dogma not engineering. Rendering speed is just one consideration. That's why Slack.

<comment><USER19> That may be. But there's also no point in building something at all if your target audience's hardware won't run it or if it'll slow those machines to a crawl. There's a decent chance that the OP has no power over the pursestrings that would need to be opened for a hardware upgrade.

</comment></comment></comment></comment><comment><USER20> If it's for devs just stick a small server and thin HTML front end in a Docker container. Or just give them a CLI, I prefer CLI's over a GUI most times anyway.

</comment><comment><USER21> If one is down with React, this project has promise:

[https://proton-native.js.org](https://proton-native.js.org)

<comment><USER22> Looks interesting. Anyone tried this?

</comment></comment><comment><USER23> Seriously? Are your devs running MS-DOC with 640k of RAM? If not then don't worry about it.

</comment><comment><USER24> A Java/Swing application would be easy to maintain long term, even decades from now.

</comment><comment><USER25> Spending on the requirements, possibly Python and TKinter?

</comment><comment><USER26> native apps.

<comment><AUTHOR> I'm asking for productivity. I want to develop for 3 platforms and I don't have a lot of time!

<comment><USER27> I think that .NET Core have a stable UI kit.

Else, my favourite solutions are Kotlin/TornadoFX/Java/JavaFX.

<comment><USER28> > I think that .NET Core have a stable UI kit.

It does, Avalonia: [https://github.com/AvaloniaUI/Avalonia](https://github.com/AvaloniaUI/Avalonia) It looks like a pretty promising project.

There was another one I believe I saw on HN a while ago but I can't seem to find it.

<comment><USER7> Avalonia is not stable and is in beta. I would not use it for production.</comment></comment></comment></comment></comment>