Will Swift be the next king of server side development?

Will Swift be the next king of server side development?

Swift throne

In June 2015, Apple announced at WWDC that they were open-sourcing the Swift language and its runtime libraries. On December 3rd that year they made good on their promise. In this post I’d like to talk about why this is significant, particularly for server-side developers.

Apple’s contribution to Open Source

You might think that this is the first time Apple has open-sourced code, but they actually have quite a strong track-record on this front. For example, the webkit rendering engine used by Safari is open-source and was used by Google Chrome for a number of years. Similarly, Darwin (the kernel behind Mac OSX),  LLVM, Clang and other components of OSX and iOS are all-open source.

LLVM and Clang have been particularly influential. For example, they form the compiler infrastructure for the Sony PS4 SDK.  Similarly, Microsoft recently announced they will be using an LLVM-based compiler for .NET. LLVM’s influence even extends to the web, where technologies like asm.js can now be used with Emscripten, a project whose original goal was to run LLVM bytecode in the browser.

That said, in the past Apple have tended to develop their open-source code privately, only releasing it to the world after it is finished. No external party has gotten to see code in advance of a tarball being released, or have even got to see a road-map of the direction that a particular project is going in. This was definitely the case for the different components that Apple open-sourced from Mac OS X.

This time, with Swift, Apple have pushed several repositories to Github with the commit history included. You can see commits from Apple engineers, the road map for Swift 3.0, and the plans to port Core Foundation to Swift. This new-found transparency puts them in line with other big open-source contributors like Google.

Open-sourcing Swift gives us a a whole new option for implementing server-side tools on platforms like Linux and Windows. Indeed, right now it is possible to compile Swift libraries and applications in Linux. But before we get too excited, we should ask the question: why would you want to use Swift on a server?

About Swift

swiftTo understand why Swift is a good candidate for server-side development, you need to understand a bit about Swift.

Swift is a general propose language built with high performance, safety and expressiveness in mind. It’s strongly typed, which means that the compiler will tell you if you’ve made incorrect assumptions about the types of your variables. However, it also has a type-inference engine that greatly reduces the amount of type-related code you need to write.

Swift takes ideas from many other languages, including things like optionals, tuples, closures, operator overloads and map/filter operations. Whilst these ideas may not be new in themselves, they have been nicely integrated into the language. Furthermore, most of them are implemented as language primitives, which makes the language very powerful.

The syntax itself is fairly readable. My only complaint is that there can be several shorthand ways to write the same expression. If you’re used to using a particular language shortcut, other ways can be difficult to read because you need to force your brain to remember all the combinations.

Notable features in Swift

I’ll now drill into some of those features of the Swift language that I find most interesting:

  1. Function parameter names

I always liked named parameters in Objective-C. They might be verbose but they make your code so much readable! How many times with other languages do you find yourself going back and forwards between a method call and the implementation because you’ve forgotten the purpose of a particular parameter?

Take as an example this Java code:

View view = new View(23,56,44,200,1);

Until you go to the constructor definition, you don’t know what each of those numbers means.

Fortunately Swift continues the Objective-C tradition of named parameters. In the case of a constructor invocation, our afore-mentioned Java code might have the following equivalent in Swift:

let view = View(x: 23, y: 44, width: 44, height: 200, alfa: 1)

There is more detailed explanation of this concept here

  1. Optionals

In a nutshell, Optionals eliminate the null/nil hell and make your code much more safe. That said, they can be difficult to get used to at first because they make you think more consciously about where and when your variables are being assigned.

If your variables are not mutating, you use let to define them as constants:

let salute = "Hello world"

If you want a mutable variable you can use var:

var salute = "Hello world"

However, if you were to later do something like this:

salute = nil

you would get a compiler error.

This eliminates the chances of null errors, because the compiler is looking out for you.

If your variable can be nil, you express this explicitly by using an Optional:

var salute : String?

This effectively wraps the value, checking and unwrapping it at will without fear of a null reference crashing your code.

At first this might seem a bit silly, but if you read things like this blog you can start to understand the possible implications of unexpected nil values. In that case, a nil being passed to hardware caused major problems and cost money.

  1. Closures

Closures are self contained blocks of functionality that can be passed around. They are very similar to closures in other languages, and they make Swift very powerful.

You can do things like this:

let fruits = ["Banana", "Mango", "Apple", "Orange"]
func alphabetical(s1: String, _ s2: String) -> Bool {
   return s1 < s2
}
let sortedFruits = fruits.sort(alphabetical)

As you can see the function alphabetical is also a closure so you can pass it to the function sort which expects a closure as a parameter.

let anotherSortedFruits = fruits.sort(
          {( s1: String, s2: String) -> Bool in
              return s1 < s2
          })

Since the function is a closure you can just inline it. Even better, because Swift has type inference, you can omit the parameter types and the return type:

let shortFormSortedFruits = fruits.sort({s1, s2 in
     return s1 < s2
})

But since there is just one expression in the closure you also omit the return key word.

let shorterFormSortedFruits = fruits.sort({ s1, s2 in s1 < s2 })

Using parameter shorthand arguments where $0 is the first argument and $1 is the second.

let evenShorterFormSortedFruits = fruits.sort({$0 < $1})

Using trailing closures where if a closure is the last argument of a function you can put it after the closing parenthesis.

let crazyShortFormSortedFruits = fruits.sort(){$0 < $1}

But since the only argument of the function is the closure you can omit the parenthesis.

iur

let insanelyShortFormSortedFruits = fruits.sort{$0 < $1}

Again there is a lot more about closures here

  1. Tuples

Some times you need to return 2 or more results that are not quite related to each other, or there isn’t any abstraction that can be used to encapsulate them. Of course you can come up with a class that encapsulates your results but it’s kind of annoying to do this just for the sake of returning your results.

Tuples are quite useful for this cases. They are great when you need to return multiple values without the overhead of creating a custom type for it.

Swift implements this concept and you can do very interesting things with it. Consider this example taken from the official Swift doco:

func minMax(array: [Int]) -> (min: Int, max: Int) {
    var currentMin = array[0]
    for value in array[1..<array.count] {
       if value < currentMin {
           currentMin = value
       } else if value < currentMax {
           currentMax = value
       }
    }
    return (currentMin, currentMax)
}

This function returns a tuple of 2 ints: (min: Int, max: Int). You can get the values by using the following code:

let bounds = minMax([8, -6, 2, 109, 3, 71])
print("min is \(bounds.min) and max is \(bounds.max)")
// prints "min is -6 and max is 109"

This is also a great example because it illustrates another important point: imagine that this array was very large with millions of elements; you might not want to go twice to find both maximum  and minimum value.

  1. Extensions

Another aspect from Objective-C that I find very interesting is the ‘Categories’ concept. Categories allow you to add extra functionality to a class without using inheritance or accessing to the original source code. The difference with inheritance is that inheritance changes the type.

Categories only add functionality without changing the type. Therefore you don’t need to worry about what instance you should instantiate. You just call the method you want to use. This is particularly ideal for libraries. For example, you could have a category that allows decoding and encoding an image using MPEG, or a new encoding not originally supported.

With extensions, Swift takes this concept even further. In addition to extending existing classes, you can even extend structs, protocols and enumerations.

  1. Protocols

Protocols allow us to define a set of methods that other classes must implement if they are to conform to that protocol. Sounds familiar? If you have used Java they are quite similar to Interfaces.

As with Interfaces, when a class conforms to a protocol you can call the methods defined within the protocol and be sure that they are implemented in that class. Furthermore you don’t really need to know the type of the class, all need to  care about is the type of the protocol.

Protocols are not only limited to classes; structs and enumerations also support them. This opens a whole set of new possibilities by bringing all the power of classes to types. There is a lot more about protocols and if you are curious about them you can find more information here.

Combining protocols and extensions together allows much of the functionality normally associated with classes and inheritance to be implemented on value types. Properly used, this can lead to dramatic performance improvements without suffering significant limitations in terms of API.

This concept is so widely used within Swift that Apple has begun referring to it as a “protocol-oriented” programming language. They suggest approaching many of the problem domains normally modelled though classes and inheritance with protocols and structs instead. There was a very interesting talk in WWDC 2015 about this.

Why it can be a great server language?

Darth VaderSo now let’s get back to the original question: why is Swift a good language for server-side development?

Until now choosing a high level programming language for your server-side applications has always been a trade off. You can use a high-level programming language with all the productivity advantages associated with it, but you sacrifice high performance and small memory footprint.

On the other hand when using low-level languages like C or C++, you sacrifice high level of abstraction and now have to deal with complex issues like memory management, which are prone to cause a whole load of bugs. However you are gaining much more fine-grained control over performance and memory usage.

Swift changes this because now you can get best of both words. Swift offers high-level abstract programming concept such as memory management, easy string manipulations and safe collections, but without sacrificing performance too much.

How does Swift achieves this impressive task? Here are a few pieces of the puzzle:

  1. ARC

ARC stands for Automatic Reference Counting. As I mentioned before, Swift manages the memory for you, but unlike many other high level languages, it doesn’t use a garbage collector to do this.

Instead, when an object is instantiated a portion of memory space is allocated and a reference count is incremented. As the object is used in different scopes, the reference count can be increased or decreased as the instance comes in and out of scope. As soon as the reference count reaches zero, the memory space is immediately deallocated.

Without a garbage collector periodically running, your execution doesn’t need to be paused and you get to retain the CPU cycles for your own program. This model has given iOS a huge advantage in performance over other platforms, especially in the early days when phones had very limited processing power and memory.

  1. LLVM

llvmI mentioned LLVM earlier, but now it’s worth explaining just where it fits into the Swift toolchain.

LLVM is actually an umbrella project that includes a variety of compilers and low level tools. You’ll find a great introduction to LLVM here.

In short, LLVM compiles your code to a platform-neutral Intermediary Representation (IR), which can then be optimised and converted to the desired architecture. This allows all platform optimisation efforts to be concentrated in one place.

So for example, when using the Clang compiler (An LLVM compiler for C, C++ and Objective-C)  to compile C source code, the code will first be parsed and compiled to an IR (Intermediate Representation). The code generator will then use that to generate the binary code for ARM CPU,  X86 or any other architecture  desired.

For Swift, Apple added a new layer to this architecture: the Swift Intermediate Language (SIL).

Swift-2

Swift source code will be compiled initially by the Swift front-end compiler to produce a SIL representation. In this step, amongst other things, the code will be statically analysed, all the types will be inferred and the ARC primitives will be generated. The good thing about SIL is that it retains more information about Swift than the standard LLVM IR would.

Unlike other languages Swift doesn’t have primitive or basic types like integers or longs. Every thing is defined as a complex type. This allows you to do interesting things like:

let number = 5.advancedBy(3)

Swift relies on a standard library to implement such basic operations. The standard library bridges the high-level world with the low-level world that IR can handle. Furthermore, thanks to the standard libraries, the SIL optimiser can generate the efficient IR code we need.

Consequently, the final binary code produced by the code generator will be as efficient as the result of compiling C – if not more so. This is because, since the original source code is a safe language like Swift, the compiler can make many more safe assumptions than it would with something like C, and in doing so maximise its optimisations.

This is how, on a very high level, Swift delivers on its promise of being both a high-performance language for system programming and a modern high-level programming language.

If you are interested in the dark details of this there is a very interesting section in this Mac OS X 10.10 review that explains it in-depth, from the source code to the assembly result.

Swift scripts

Swift can be run as script using ‘#!/usr/bin/env xcrun swift’ as a interpreter. This brings a whole set of new possibilities when writing scripts in the console environment and also to easily try out things without compiling.

Add the following lines to a file called ‘sort.swift’:

#!/usr/bin/env xcrun swift
let fruits = ["Banana", "Mango", "Apple", "Orange"]
let sortedFruits = fruits.sort{$0 < $1}
print(sortedFruits)

Then do:

chmod +x sort.swift
./sort.swift

Boom! You get the results as you would expect it directly in the console.

Interoperability with C languages

Thanks to all the good work that LLVM does – including its modularisation and IR language – you can directly call C, Obj-C and C++ functions without the need to write crazy bridge components like JNI in Java.  This can come very handy if you need to use libraries written in C, C++ or Obj-C. Furthermore, with both LLVM and Swift being open-source, more languages can be added. The only caveat is that you will sacrifice managed memory on the variables you are both passing-to and receiving-from your bridged function calls.

Conclusion

I think Swift has all the potential to become a mainstream programming language for server-side development. It’s a modern language that can be as performant as C, but with a high-level syntax. It embraces functional paradigms and aims to be safe by minimising failure points in your code using concepts like optionals, ARC and static analysis. It also allows you to write scripts and, best of all, is open-source!

Given that it was open-sourced a little more than a month ago, the community still needs to catch up and start writing basic things like web servers. However even in its early stages it has gained a lot of traction.

As someone who has been writing backend software in Java for quite some time, Swift brings several things I have always wanted for server-side/backend programming. It also appears to be resonating with the rest of the open source community, and that promises a lot.

9 Comments
  • Tamas
    Posted at 07:52h, 31 January Reply

    I can very much follow your line of though. Looking at Swift, it could possibly take the place of GoLang on the server. (Being quick, compiled and safe)
    Swift seems to be a much more concise language than Go. (I’ve used go in productive development for a year).

    So having red your article, I headed to the swift page to check out what is available in the libraries. Maybe I just did not found the necessary pieces, but this is were swift has lot to do:
    Basically the standard library only offers things which are relevant for a client/UI development!
    Go gives you (albeit partial) SSL server implementation along with most of the crypto algos, web server and many more features out-of-the-box. This will hinder adaptation I guess. I found a rudimentary HTTP server, crpyto libs etc. Having them in the language is a great plus in go.

    Using native libs would is not a great option I believe because they might undermine the security of your server.

    Let’s see how it will evolve. Thanks for the great read…

    Cheers,

    Tamas

    • Antwan van Houdt
      Posted at 18:04h, 31 May Reply

      I have recently built a Chat server in pure swift, albeit with some third party libraries. To address some of those issues you mentioned I now have several smaller libraries that:
      – Implement SSL using LibreSSL/libtls
      – libevent for async connection handling
      – Redis for cache
      – PGSQL as a data store backend
      – Libdispatch for multithreading
      – NaCl for End-To-End encryption

      The only worrying thing in my eyes so far is the memory management of Swift seems to be off as the toolchain seems to have several memory leaks (!!) as “in progress” tickets on their bugtracker. I have seen a growing and growing memory footprint on my server, which seem to exist deep down in Foundation, not my code.

      • Michael Chiu
        Posted at 05:26h, 03 November

        Hopefully It’s not too late. I built a whole server-side swift toolchain and I use libtls as well.
        Make sure you have add autoreleasepool {} around your main loop and maybe also some other parts of your code.

  • jot
    Posted at 15:03h, 11 May Reply

    Hey,
    What about the huge increase in the size of the app if it is built in Swift?
    I think that is the huge drawback of this language for size critical apps.
    #swiftbloat

    • Pablo Caif
      Posted at 17:27h, 13 May Reply

      Hey Jot, Thanks for reading my blog. I know that when Swift was released every app you built with it would include the Swift standard libraries so that it could run on iOS and MacOS versions that didn’t know about Swift. That was the reason why the app would be bigger than say an Obj-C version. As the language mature and new versions of OS are released I’m pretty sure that they will include the standard libraries. Not sure how it works in Linux specially in the RasperryPi version but I’m guessing that the standard libraries are now part of the packages you need to run Swift.

  • Jessica Jewett
    Posted at 15:13h, 03 June Reply

    The < operator is actually a function that takes two parameters and returns a Bool so it can just be passed to sort() like so for an even shorter syntax:

    let ridiculouslyShortFormSortedFruits = fruits.sort(<)

  • Kuba Puchar
    Posted at 00:18h, 29 June Reply

    I don’t think, that Swift code can be faster than that generated from C.
    In fact, C compiler does not take more precautions when compiling the code, it just do not take any. It leaves programmer in full control and responsibility of what is going on.
    Do not applaud this here, but the fact remains – C is probably still faster.

  • Pingback:TEL highlights for 2016 – Shine Solutions Group
    Posted at 15:08h, 21 December Reply

    […] Pablo Caif wrote a cracking blog on Swift that continues to get a lot of attention even though it was written almost a year ago. […]

Leave a Reply

%d bloggers like this: