Saturday, May 26, 2018

What makes programming language popular

Everybody knows that there is no "best" programming language, just as there is no best car or best kind of cheese. For many years, since I got my first computer, I have been looking for a language that would suit me best and satisfy all my needs. I have one or two favourites, which I use most frequently when creating utilities for my own, so I guess those are my personal best. But in general, programming languages are just tools. They may be better or worse suited for the job, but the language itself is not your aim. What really matters is what you can create with it. When you compare iOS to Android, do you compare Objective C to Java? I know quite a few programmers who feel angry when they hear such opinions, and who spend whole days polishing their code. But, as Jamie Zawinski said: "It’s great to rewrite your code and make it cleaner and by the third time it’ll actually be pretty. But that’s not the point — you’re not here to write code; you’re here to ship products."

Speaking of products. If you have ever wondered what makes a programming language popular, the answer is simple: money. There are many great essays about language popularity (like this one by Paul Graham), but they are true only in theory. In practice, programming languages are products, just like any other software. Let me give you an example.

A few weeks ago a developer published on his company's blog an article describing his team's negative experience with Kotlin. It was just a list of problems they encountered and reasons why they decided not to use the language for their project. Within hours the post reached over a hundred comments. A huge amount of them were posted by one of Kotlin developers, working for JetBrains, a company behind Kotlin. It's quite understandable he tried to defend it, but he didn't stop at providing his arguments. He commented on every post that wasn't positive about Kotlin, even if it wasn't negative about it. It didn't seem a problem for the company that one of its employees spends a whole day writing tons of elaborate comments. Soon, other Kotlin advocates appeared. One of them suggested that the atricle's author is a moron, and then provided a link to his blog, where he boasts about giving talks on Kotlin conferences. Guess who sponsors those conferences.

All modern programming languages, which are popular, have powerful patrons. Swift is backed by Apple, Golang by Google, and Rust by Mozilla. JetBrains didn't create Kotlin just for fun, they admitted on their blog: "we expect Kotlin to drive the sales of IntelliJ IDEA". Social marketing is becoming main driving force for many companies, so they put a lot of effort and money in creating a positive picture of their products and reacting to anything that may damage it. New languages struggle to get attention, and it takes time before they gain wide adoption. Until this happens, they need an army of salesmen and supporters hoping to jump the train (and get a well paid job) when the language reaches its critical mass. So if you are thoughtless enough to criticize the product, you will instantly become a target for aggressive marketing counterstrikes.

About a month later, another post appeared on the same blog. This time another developer described his own way from C# to Java. This time, the post was commented twice. Conclusion? Nobody fights for old languages, because nobody has to. Oracle estimates that Java runs on 3 billion devices - loosing that market, if possible, would take ages. C# is now the primary programming language for Windows, and Microsoft still owns about 90% of desktop market share. ANSI C has been used as a core of all modern operating systems and device drivers. It is also the primary programming language for micro-controllers, for the same reason it was initially developed: weak CPU and low memory (try to run software written in any modern language on a chip with 2kB RAM - and for your information, Forth is not a modern language). PHP is popular because of dirty cheap LAMP hosting, and you can have your neighbour's kid set up a website with Wordpress, or online store with osCommerce, for peanuts.

So, how do you make programming language popular? First, you need a decent design. It doesn't have to be great, it just needs to be solid enough, so you can convince other people that it's worth using. Even COBOL was a decent language for its time. Second, you have to be a good salesman and sell your idea to a company which will agree to support it with its money. For this to happen, your language must generate some kind of profit - it can either introduce some clever language constructs that reduce development time, or produce efficient executables which use less server resources. Kotlin's selling points are null pointer safety and reduced boilerplate code. Your selling point may be, for example, a reduced resource usage in the cloud, so you will pay lower bills for Amazon Web Services, Microsoft Azure or Google Cloud Platform. It will not hurt if you know people who make important decisions within your company.

When all this happens, you have a good chance to succeed. Strong marketing among engineers - conferences, tutorials, free tools - backed by company funds, will help making the language popular. An army of fanboys will prove to everyone who disagrees that they are just too stupid to understand how awesome it is.

Because nowadays programming language is a product. Remember about it next time you pick up a new shiny one.

Sunday, May 20, 2018

Writing Google Cloud Functions in C

Serverless is a new hot topic in the IT world. As with every new technology, the idea was obvious in theory (easy way of migrating software without live migration of whole virtual machines), but very few people knew how to implement it in practice. Today we have AWS Lambda, Google Cloud Functions and Azure Functions, and will probably see many other in the near future.

Google Cloud is a technology I currently work with, and Google Cloud Functions are a very handy tool. If you just need to create a simple RESTful service, you don't have to write a backend application and set up a Kubernetes cluster to run it. All you need to do is to write a piece of code which handles a request and sends a response, and the Cloud Functions will take care of all the dirty work. They free you from the burden of deploying, monitoring, scaling and load balancing your application. You can focus entirely on writing software.

As always, the comfort comes at a price. Currently the only programming language supported by Cloud Functions is JavaScript. Does it mean that you cannot use a library written in another language? If you have a nice piece of C code and want to use it, are you doomed to manually build an infrastructure based on Compute Engine instances with Linux and Apache? Fortunately, the answer is no.

A few years ago in my post about JavaScript I described Emscripten, a C/C++ to JavaScript compiler. It has matured since, and it can produce a very good and stable code. Let me show you an example of how it can be used to create a Cloud Function from an ANSI C code.

Let's start with a simple program to display current time and date:
#include <stdio.h>
#include <time.h>

const char *now() {
  time_t t = time(NULL);
  return ctime(&t);
}

int main() {
  printf("%s\n", now());
  return 0;
}
Now let's convert it to JavaScript using Emscripten:
emcc -O2 -o main.js main.c
and run it with Node.js:
node main.js
To make our program run with Cloud Functions we need to make a separate file (I called it extern.c) containing only now() function:
#include <stdio.h>
#include <time.h>
#include "emscripten.h"

EMSCRIPTEN_KEEPALIVE
const char *now() {
  time_t t = time(NULL);
  return ctime(&t);
}
As you can see, there are some changes to the original source code:
- there is no main() function
- there is additional #include "emscripten.h" directive
- the now() function is prefixed with EMSCRIPTEN_KEEPALIVE. It tells the compiler that the code is in use and should not be removed during compilation (the optimizer tries to identify and remove dead code).

Let's build an external library from our code:
emcc -O1 -s 'EXTRA_EXPORTED_RUNTIME_METHODS=["ccall", "cwrap"]' -o extern.js extern.c
This creates a module extern.js, which can be included into a Node.js application:
var module = require('./extern.js');
var now = module.cwrap('now', 'string', []);

console.log(now());
Module.cwrap returns a function wrapper, which calls our code exported from C. The first argument is the name of the C function, the second one is the type returned by the function, and the third one contains the list of the argument types passed to it.

A word of warning: When using Node.js, you can use ccall instead of cwrap, as described in Emscripten documentation. The difference is that ccall doesn't return a function, but a scalar value, so you will log it with console.log(now) instead of console.log(now()). However, ccall will not work correctly with current version of Google Cloud Functions - module.ccall('now', 'string', []) will always return the time when the Cloud Function was created instead of current one. Also, don't use optimization levels higher than O1 when compiling external modules with Emscripten.

Because Google Cloud Functions are powered by Node.js, it is very easy to convert our Node.js application into a Cloud Function:
var module = require('./extern.js');
var now = module.cwrap('now', 'string', []);

exports.time = (req, res) => {
  res.send(now());
}
Save the code above as index.js and put it into a zip file together with extern.js (you can find an example file here). Now go to Google Cloud Platform panel, choose "Cloud Functions" and click "Create function". Change the default function name to "time". Leave memory allocation settings unchanged. 256MB may seem an overkill, but changing it to a lower value may actually add a performance penalty to your application. Underneath the Cloud Functions there are still virtual instances running, and low-memory virtual machines get less CPU time. Set the trigger type to "HTTP trigger" - it means that the function will be run on demand when an http request comes. Pay attention to the URL field - it's the address you can use to call your function. Choose "ZIP upload" as the source of the code. You will need a Bucket as a temporary upload storage - you can create it through the "Storage" menu in Google Cloud Platform panel. Finally, when asked about function to execute, enter "time":
Creating a function takes a while. When it's ready, you can go to the URL which was displayed when the function was created (for example https://us-central1-myproject.cloudfunctions.net/time) and you should see the current time in response.

You can call the Cloud Functions from a website with AJAX. What I mean is that for example you can create a page displaying a simple clock, which will refresh every second (remember to change the url https://us-central1-myproject.cloudfunctions.net/time to yours):
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html;charset=UTF-8"> 
<script src="jquery.min.js"></script>
<script>
$(document).ready(function() {
  setInterval(function() {
    $.ajax({
      url: 'https://us-central1-myproject.cloudfunctions.net/time',
      method: 'GET',
      crossDomain: true,
      success: function(data) {
        $('#time').text(data);
      }
    });
  }, 1000);
});
</script>
</head>
<body>
<p id="time"></p>
</body>
</html>
This alone, however, will not work, due to cross-origin protection mechanisms. In short, a web browser will not allow AJAX request from your website to an endpoint located in a different domain, if it does not explicitly allow it. To fix it, you need to add Access-Control-Allow-Origin response headers to index.js:
var module = require('./extern.js');
var now = module.cwrap('now', 'string', []);

exports.time = (req, res) => {
  res.set('Access-Control-Allow-Origin', 'http://www.mypage.com');
  res.set('Access-Control-Allow-Methods', 'GET');
  res.send(now());
}
Replace http://www.mypage.com with the domain name of your website where the clock page is located.

Sunday, April 8, 2018

Using Raspbery Pi 3 as wireless client router

The title may seem confusing, but it covers a specific use case: you have a machine with ethernet port only, and you want to connect it to a wifi network. For whatever reason, you can't, or don't want, use a wireless card with your computer. As for me, I have Amiga 500 with Plipbox, and Rapberry Pi B+ with RISC OS 5, and both can be connected to the Internet - but using a few meters long network cable, lying on the floor, to reach a cable TV router is far from what I'd call a comfortable solution.

The Internet is full of recepies of how to use Raspberry Pi 3 as a wireless access point, but I wanted to use it the other way round. I wanted it to be a wireless client, and at the same time act as a router, so I could connect my ethernet-only hardware to the Internet through it. Sadly, I couldn't find any sensible description, so I finally figured it out myself. It's not an ideal solution, and it uses static addresses instead of DHCP, but it's fairly simple, and it works for me. If you have a better one, feel free to point to it in the comments.
My recipie works with Debian 9 (a.k.a. Raspbian Stretch) with desktop. Take note that it may not work with other Linux versions. I assume that you know how to install it on SD card and how to run it, so I'll go straight to the network setup.

First, you need to configure Raspberry Pi to connect to the wifi network. Turn it on and wait for the system to load. Now click on the wifi icon located on the dock and choose your network. Enter the network password and wait until the connection becomes established. You can check if everything works correctly by pinging google.com or some other address.

Now you need to edit a few system files. They are only writeable by the user "root" so you can either use a console editor, like vim or nano, with the "sudo" command, or run "gksu gedit" from the desktop. I prefer the first method, so I'll use this one.

First, you need to disable dhcp for the ethernet interface. It's because Raspberry Pi is meant to work as a client and so it will try to reconfigure the ethernet port everytime it discovers a network cable has been attached to it. So do:
sudo nano /etc/dhcpcd.conf
and add the following line at the end of the file:
denyinterfaces eth0
Next, you need to enable packet forwarding between the network interfaces. To do this, uncomment the following line in /etc/sysctl.conf:
net.ipv4.ip_forward=1
Finally, you need to configure routing. I use 10.0.0.0/24 for my network, but you can use any non-routable addresses for this. So, add the following lines to /etc/rc.local before "exit 0":
ifconfig eth0 10.0.0.1 netmask 255.255.255.0 up
iptables -t nat -A POSTROUTING -s 10.0.0.0/24 -j MASQUERADE
iptables -A FORWARD -s 10.0.0.0/24 -j ACCEPT
The first line sets up the IP address and netmask for the ethernet port. The second one enables packet translation, which means that the network packets will be able to get from the 10.0.0.0/24 network to the outside world. The last rule allows those packets to pass through the built-in firewall.

Now reboot the Raspberry Pi. After a while it will connect to the wifi network (you can say when it is when the yellow LED on the board stops binking), and it will allow clients to use its ethernet port as a gateway.

I will not describe client configuration in detail, because it differs very much among operating systems. I'll just give you the parameters you need to enter to make the client work:
1) IP address: anything between 10.0.0.2 and 10.0.0.254. If you use more than one device (for example connected through a switch) rememer that each one of them needs its own unique IP address.
2) Netmask: 255.255.255.0
3) Gateway: 10.0.0.1
4) DNS servers: use 8.8.8.8 as primary and 8.8.4.4 as secondary. Alternatively, you can use your home router's IP address (e.g. 192.168.1.1) or your ISP provider's DNS hosts - if you know what they are.