Live data from Hacker News

Ask HN: What's your "it's not stupid if it works" story?

news.ycombinator.com

201–210 of 510 posts

Re: Ask HN: What's your "it's not stupid if it works" story?

#201
post #169
post #167

Earlier quoted context omitted.

How did you make a Windows executable work on the web?

I imagine it ran server-side (on Windows).

Indeed. I think it's worth going a little deeper for those who perhaps aren't familiar with some of the underlying principles of the Web.

For starters, all the program does is receive requests (as text) over a TCP/IP connection. It replies over the same connection.

So writing a Web server in any language, on any OS is a trivial exercise. (Once you have the ability to read or write TCP/IP.

The program has to accept the input, calculate the output, and send the output.

If the input is just file names, then the program just reads the file and sends it. (Think static site).

The program may parse the file, and process it some more. It "interprets" code inside the file, executes it, and thus transforms the output. Think PHP.

In these cases a generic server fits the bill. Think Apache, IIS, nginx and so on.

The next level up are programs that are compiled. They generate the output on the fly, often with no, or little, disk interaction. This sort of program often uses a database, but might not. (An online Soduku game for example might do everything in memory.)

Again, any if the above can be built on any OS and written in any language with TCP support.

Re: Ask HN: What's your "it's not stupid if it works" story?

#202
post #150

Earlier quoted context omitted.

... how does doing a full string dict lookup take less time than just checking a few trailing characters in a trie? For indexing it's okay to be aggressive since you can check again for the actual matches.

> since you can check again for the actual matches. Can you explain this?

An aggressive stemmer might stem both "generic" and "general" to "gener".

Then if your query is "what documents contain 'generic'?", you look in the index for "gener" and then open each of those documents and check if it actually has "generic" using a stricter stemmer (that accepts generic{,s}, genericness{,es}, genericit{y,ies}, generically ... this is a bit of a bad example since they all have the prefix directly). The cost is acceptable as long as both words have about the same frequency so it doesn't affect the big O.

Of course if you have any decent kind of compute, you can hard-code exceptions before building the index (which does mean you have to rebuild the index if your exception list changes ... or at least, the part of the index for the specific part of the trie whose exception lists changed - you don't do a global lookup!) to do less work at query time. But regardless, you still have to do some of this at query time to handle nasty cases like lie/lay/laid (searching for "lie" should not return "laid" or vice versa, but "lay" should match both of the others) or do/does/doe (a more obviously unrelated example).

Re: Ask HN: What's your "it's not stupid if it works" story?

#203
post #131

I created the most popular Turkish social platform, Eksi Sozluk, using a single plaintext file as its content database back in 1999. It had taken me only three hours to get it up and running without any web frameworks or anything. It was just an EXE written in Delphi. The platform's still up albeit running on .NET/MySQL now and getting banned by Erdogan government for baseless or false reasons (like "national securit…

Crazy to see you! Some time ago, I was actually looking to add Eksi to Touchbase (www.touchbase.id) since several users reached out and wanted to add it alongside their other platforms to share on their profile, but we couldn't find out the URL convention for user profile feeds! It seemed to be " https://eksisozluk1999.com/{{username}}--{{7 digit value}}", but we couldn't find any rhyme or reason to the 7 digits. Are…

User profiles are actually stored like https://eksisozluk1999.com/biri/{{username}}. "/@{{username}}" also redirects to "/biri/{{username}}". You shouldn't need numbers at all. The numbers are only at the end of topic titles. They are title id's (sequential integers assigned when they're created) to disambiguate conflicting Latinized forms of Turkish words.

Re: Ask HN: What's your "it's not stupid if it works" story?

#204
All of these other anecdotes are (understandably) sysadmin or developer-related, though I have a couple very stupid ones that are completely physical and mechanical.

My first residential plumbing fix was a simple unclogging of a shower drain, which was accomplished by putting a couple inches of water in the tub and blasting repeatedly into the drain with a pneumatic cannon. The splatters hit the ceiling, but it was thoroughly unclogged after a few repetitions.

The second major one, was the sewer line at mom's place, which ended up being very bad clog that nasty industrial drain cleaner would not even touch. I capped every drain and vent in the entire house, and dumped two 30 gallon compressor tanks of air into the two toilet hookups. There was great and concerning watery rumbling from all through the house, but after a 30 seconds or so, the clog was blown into the septic and has not given her a single problem since then.

Re: Ask HN: What's your "it's not stupid if it works" story?

#205
post #131

I created the most popular Turkish social platform, Eksi Sozluk, using a single plaintext file as its content database back in 1999. It had taken me only three hours to get it up and running without any web frameworks or anything. It was just an EXE written in Delphi. The platform's still up albeit running on .NET/MySQL now and getting banned by Erdogan government for baseless or false reasons (like "national securit…

Is there a reason why they are not taking the 1999 version of the domain down?

Because the platform switched to it only last week, no other reason. It was on eksisozluk1923.com before that. The moment this new domain catches up on popularity, they would find an arbitrary reason to ban that too.

Re: Ask HN: What's your "it's not stupid if it works" story?

#206
In 2012, Intel had a site called esaa-members.com. It was supposed to be some type of authorized hardware catalog, with recipes for building computers out of known-to-be compatible parts. Anyways, there was a daily import of the hardware data, which was kicked off by a small Ruby script that downloaded some CSV file over SFTP. It was tiny, and all it did was put the CSV in a folder, to be processed by another script down the line. Occasionally though, there would be a network error, and it wouldn't write the file. When this happened, the next script that looked for the file wouldn't find it, and would send out an email alert.

That's when I discovered that you could write a GOTO statement in Ruby! I made a very minor addition to the beginning and end of the script, a label at the top, and a goto at the bottom for if the CSV file didn't exist. I had added my email to the list of alerts, and after that GOTO was added, I never saw another alert.

Re: Ask HN: What's your "it's not stupid if it works" story?

#207
post #150

15+ years ago, I was working on indexing gigabytes of text on a mobile CPU (before smart phones caused massive investment in such CPUs). Word normalization logic (e.g., sky/skies/sky's -> sky) was very slow, so I used a cache, which sped it up immensely. Conceptually the cache looked like {"sky": "sky", "skies": "sky", "sky's": "sky", "cats": "cat", ...}. I needed cache eviction logic as there was only 1 MB of RAM av…

... how does doing a full string dict lookup take less time than just checking a few trailing characters in a trie? For indexing it's okay to be aggressive since you can check again for the actual matches.

We used a JIT-less subset of Java 1.4 on that device. Hashing of word-length strings in the underlying optimized C code was extremely fast and CPU cache friendly (and came with the JVM). With the simple cache in place, indexing time was dominated by the libraries that extracted the text from the supported formats. So, in line with this Ask HN's topic, it was good enough. And less code to maintain. And easier for engineers after me to understand. A good tradeoff overall.

More technical details for the curious...

Earlier I had done a quick trie implementation for other purposes in that code, but abandoned it. The problem is that we had to index (and search) large amounts of content in many different languages, including Chinese and Japanese with full Unicode support. This means that there is such large potential fan-out / sparsity within the trie that you need faster lookups / denser storage at each node in the trie (a hash map or binary search or ...). In that situation, a trie can be much slower than a single hash map with short strings as keys. Especially in a JIT-less JVM (the same code had to run server-side, where native extensions weren't allowed). If we were only dealing with ASCII, then maybe. And there would also be more complexity to maintain for decades (you can still buy newer versions of the device today that are running the same indexing and search code).

All those languages were also the reason that normalization needed caching. In v1, we were English only. I hand rolled a "good enough" normalizer that was simple / fast enough to not need caching. In v2 we went international as described above. I wasn't capable of hand rolling anything beyond English. So we brought in Lucene's tokenizers/stemmers (including for English, which was much more accurate than mine). Many of the stemmers were written in Snowball and the resulting Java code was very slow on the device.

Re: Ask HN: What's your "it's not stupid if it works" story?

#208
...an awful one for posterity: an abomination of vim + awk as a proto-protocol plus UI editor.

Basically awk would match `/^FOO / { system("foo.exe $0") }`

...you could get pretty darned far with that mechanism, for near minimal amounts of code.

Any time you pressed "enter" on a line of text in vim, it'd get thrown through that awk script.

If a line matched a command matched in the awk file (think GET, POST, SEARCH, ADD, etc), it'd execute that awk block, which was often just calling over to another executable which did the searching, adding, etc.

The interesting thing about it was using it as a UI... you could basically "expand in place" any particular line... have commands return subsequent commands to pick from, etc.

Plus the ability to "undo" via vim commands and the fluency of effectively an ad-hoc REPL was a really liberating experience.

Re: Ask HN: What's your "it's not stupid if it works" story?

#209

We have a production service running for years that just mmaps an entire SSD and casts the pointer to the desired C++ data structure. That SSD doesn't even have a file system on it, instead it directly stores one monstrous struct array filled with data. There's also no recovery, if the SSD breaks you need to recover all data from a backup. But it works and it's mind-boggingly fast and cheap.

I've always wanted a Smalltalk VM that did this. Eternally persistent VM, without having to "save". It just "lives". Go ahead, map a 10GB or 100GB file to the VM and go at it. Imagine your entire email history (everyone seems to have large email histories) in the "email array", all as ST objects. Just as an example. Is that "good"? I dunno. But, simply, there is no impedance mismatch. There's no persistence layer, yo…

That is so wonderfully fascinating to me. You could just download a file into a variable and when that variable goes out of scope/has no more references it’d just be automatically “deleted”. Since there’s no longer a concrete “thing” called a file, you can organize them however you want and with whatever “metadata” you want by having a dict with the metadata you want and some convention like :file as the key that points to the body. Arbitrary indexes too; any number of data structures could all share a reference to the same variable.

Simple databases are just made up of collections of objects. Foreign key constraints? Just make the instance variable type a non-nullable type. Indexes? Lists of tuples that point to the objects. More complex databases and queries can provide a set of functions as an API. You can write queries in SQL or you can just provide a map/filter/reduce function with the predicate written in normal code. Graph databases too: you can just run Dijkstra’s algorithm or TSP or whatever directly on a rich persistent data structure.

Thanks for the neat idea to riff on. I like it! Thinking about it in practice makes me a little anxious, but the theory is beautiful.

Re: Ask HN: What's your "it's not stupid if it works" story?

#210
Not my idea or implementation.

Our startup built a plugin for Microsoft Outlook. It was successful, and customers wanted the same thing but for Outlook Express. Unfortunately, OE had no plugin architecture. But Windows has Windows hooks and DLL injection. So we were able to build a macro-like system that clicked here and dragged there and did what we needed it to. The only problem was that you could see all the actions happening on the screen. It worked perfectly, but the flickering looked awful.

At lunch, someone joked that we just had to convince OE users not to look at the screen while our product did its thing. We all laughed, then paused. We looked around at each other and said "no, that can't work."

That afternoon someone coded up a routine to screenshot the entire desktop, display the screenshot full-screen, do our GUI manipulations, wait for the event loop to drain so that we knew OE had updated, and then kill the full-screen overlay. Since the overlay was a screenshot of the screen, it shouldn't have been noticable.

It totally worked. The flickering was gone. We shipped the OE version with the overlay hiding the GUI updates. Users loved the product.

Post reply on HN