View on GitHub

gsoc-2021-report

Weekly Updates and Final Report for my GSOC Project on Socket Library for chapel-lang

Socket Library - Chapel

drawing drawing

Abstract

Chapel is a programming language designed for productive parallel computing at scale. It simplifies parallel programming through elegant parallel programming constructs. As Chapel can utilize a system to its fullest potential, it seems like one of the ideal solutions to handle millions of network requests.

Currently, we can do network programming by using C Interoperability, but those constructs are not intuitive and good enough for users to easily do their tasks.

My Project

My Google Summer of Code project with Chapel was focused on creating a standard “Socket Library”. This project aimed to ensure concurrent, parallel safe, and easy to use constructs for networking. The project was built on top of C System Calls, saving users from their complexity to perform even the most trivial tasks.

This blog post is for my final submission of the GSoC Project.

Under this project, the following three major parts needed to be managed:

  1. Getting review over design for the socket library from other developers.
  2. Adding and updating runtime functions that can then be used in Socket Module.
  3. Nonblocking but synchronous procedures that allow other tasks to run freely.
  4. Creating network constructs for UDP and TCP that align themselves except for the I/O differences.

Pull requests created in the period of GSoC:

PR Title Review Status Merge Status
Design: Socket Library Approved Draft
Socket Construct Additions Sys Module Approved Merged
File Descriptor Getter for file Approved Merged
Qthread Select Approved Merged
Update Addrinfo Constructs Approved Merged
Socket Library Pending Open

I’ll update the status of PRs as they get changed.

Work Done

Design

Even though my GSoC Proposal talked about how the Socket Module should look like its design was entirely based on Python and C System Calls which aren’t the best ones and don’t align well with how we wanted it to look for Chapel.

My initial task was to look over how other modern-day programming languages implement their Socket Modules. I was recommended to look over at Julia, Go, Python, D, etc. I made did my analysis and brought together a simple gist as suggested to me by my mentors.

Finally, after analyzing implementations of other languages and multiple design discussion sessions with Chapel developers, I made a design pull-request describing the API.

Changes to Runtime

The module that is storing most of the extern procs, records, and constants is the Sys standard module. There were several changes made to the module which were as follows:

All this was done as a part of the below PR and soon will be moved to Socket Module when it gets added in.

To treat socket connections like chapel file we needed access to their file descriptor for all the operations for this a minor addition was made in runtime to fetch the file descriptor. This allowed us to use Chapel I/O in the Socket Module which handles buffered I/O and keeps the I/O methods consistent across chapel modules.

Finally, to resolve Domain Name Service from user inputs like “https://summerofcode.withgoogle.com/” I made some fixes to getaddrinfo and constructs related to it whose old implementation had a few issues:

NonBlocking Procedures

The architecture for the socket library was decided to be synchronous but nonblocking as that’s how most chapel procedures work ( async is a possibility for the future ). If they need to block they will yield the main thread so that other tasks of the process can run without being blocked.

For this, I decided to use I/O multiplexing using select system calls where the procedure waits until it becomes ready which can mean it becomes readable, writable or a timeout occurred.

blocking.png

The issue was that calling in normal select will cause the pthread on which chapel qthreads are scheduled to block. Hence, to counter this qthreads library provides its own set of system calls that will block but not on the current pthread instead are transferred to another helper pthread where they do blocking.

The outcome was making use of qt_select inside of our sys_select call.

non_blocking.png

There were certain hurdles and PR remained stale for some time because we faced hurdles due to bugs in error informing inside of qthread’s library procedures, which were resolved by collaborating with qthread’s core team. The following is the issue that describes the bugs in detail.

Socket Module

The socket module was designed as stated in the design PR and had a lot of modifications being made to the exposed API as reviews were coming in.

The main intent was to hide the complexity associated with the C System Calls under custom procedures and records.

The major records in Socket Module that do all the heavy lifting include

Along the lines of Julia utility procedures were provided in the module to user which included bind, naggle, delayAck, getsockname, getpeername, setSockopt and getSockOpt.

The PR has been rebased and changes are being made to it since the finalization of the design for the Module. It consists of all the tests, documentation, and the module itself as well.

Currently, all the tests are passing and PR is under review before a major change to the internal architecture while the APIs exposed to users will remain the same.

Libevent Integration

Libevent exposes APIs that are more performant and handle more open file descriptors or connections than select call ever could. The reason being that libevent uses kernel methods that have a time complexity of O(1) unlike select which is O(N).

Libevent works using callbacks but we have to ensure to make it work in a non-blocking and synchronous manner. Integrating libevent was something that was never done in the chapel so it was a completely new experience for me.

The architecture can be best explained with diagrams, so here goes.

connect with event loop.png

The events are handled by the event loop which runs a callback whenever an event ( read/ write/ timeout ) occurs on the file. It writes back the event’s value to a sync variable (passed as an argument to the callback function) transitioning to full state and the procedure waiting on the sync variable is finally woken up.

event loop.png

Usage of Socket Module

A TCP Client in Chapel is as follows:

use Socket;
use Time;

proc main() {
  config const host:string = "chapel-lang.org", port:uint(16) = 80;
  const x = connect(host, port);
  const writer = x.writer();
  writer.writeln("hello world!");
  writer.close();
  x.close();
}

To serve a basic TCP Server using Socket Module will look as follows:

use Socket;

proc main() {
  var address = ipAddr.create("127.0.0.1", 8000, IPFamily.IPv4);
  var server = listen(address, backlog = 6000);
  writeln("Listening for connections on ", server.addr.host, ":", server.addr.port);
  defer server.close();

  while (true) {
    var conn = server.accept();
    const address = getpeername(conn);
    const writer = conn.writer();
    writer.writeln(address, " connected ");
    writer.close();
    conn.close();
  }
}

We can utilize chapel begin to demonstrate UDP connections in a single program. begin creates a new task or user-level thread the terminology might differ but it has a separate execution context from the main task/thread providing us capabilities for task parallelization.

use Socket;

proc main() throws {
  var address = ipAddr.ipv4(IPv4Localhost, 8111);
  var receiver = new udpSocket();
  bind(receiver, address);

  var sender = new udpSocket();

  var sent = b"hello world!";
  begin {
    var sentBytes = sender.send(sent, address);
  }
  var received:bytes;
  received = receiver.recv(sent.size);
  writeln(received);
}

Weekly Updates

Updates for all the weekly meetings that took place can be found on this notion site.

Future Work

Learning

Special Thanks

It was wonderful working with the Chapel community throughout the GSoC project. I would like to thank Michael, Krishna, and Ankush for solving my queries, debugging issues with me, giving constructive suggestions and guiding me through the program. Thanks to Brad, Lydia, Engin, Greg, Paul, and the members of the Chapel Community for helping with their suggestions.

I would like to thank Shivansh Saini, @Nishant Mittal, and @Ashish Kumar for motivating and guiding me in applying and getting through the whole program.

Final thanks to Google for organizing this amazing program. I feel GSoC made it easier for me to get started with open source contributions. It was a great lesson on how projects are built and maintained with great quality. I am excited to continue contributing to the open-source community

Thanks for reading :) and please share your thoughts. I always like to meet more enthusiastic people, so do reach out to me on Twitter or Linkedin to share your feedback or for any queries. I’d be more than happy to help and connect.