International Journal of Science and Engineering Applications
Volume 13-Issue 03, 30 - 35, 2024, ISSN:- 2319 - 7560
DOI:10.7753/IJSEA1303.1007
www.ijsea.com 31
managing low-level implementation – work with sockets,
generating connections, and connection-specific events. For
each connection, the server calls the application once - after
that, the application takes care of the connection’s event
messages as they happen and produces events back when
necessary.
While the general design is similar to WSGI, it has a very
distinct attribute - ASGI applications are asynchronous
callables. While WSGI only allows an application to receive a
single input stream and return a single result before finishing
connection, ASGI lets applications receive and send
asynchronous event messages as long as the connection is
alive.
The protocol server specifies the following interface for client
applications (such as web frameworks): it’s a coroutine
callable (a Python object that implements the __call__
method) that takes three arguments:
'scope' - a dictionary that contains connection scope
information. It’s guaranteed to contain a 'type' key that defines
the connection protocol. It could be 'http', 'websocket', or any
other [4].
'receive' - an awaitable callable, it yields new information
(event) when it becomes available. It could be an HTTP body
or a new WebSocket message sent by the client.
'send' - an awaitable callable, that takes an event as an
argument. Event content is defined by the protocol, it could be
an HTTP response body or WebSocket message.
An important part of ASGI is its compatibility with WSGI.
ASGI servers can host WSGI-based applications by wrapping
them through a translation layer that converts ASGI interface
into WSGI and back.
1.4 WSGI Limitations
While Python is widely used in web development, it has a
limitation that dramatically limits its potential performance -
the Global Interpreter Lock (GIL). The GIL is a part of
CPython's memory management mechanic, it’s a global mutex
that doesn’t allow native threads to execute Python bytecode
simultaneously. CPython is the most popular implementation
of a Python interpreter, directly supported by the Python
foundation. This lock was put in place because CPython's
memory management is not thread-safe. Since GIL prevents
bytecode from running simultaneously in multiple threads on
multiple CPU cores it can lead to performance bottlenecks in
multi-threaded applications, undermining the potential
benefits of parallelism on multi-core processors.
Outside of Python, the most popular design option for web
servers to run multiple requests simultaneously is by having
multiple workers, where most commonly, workers are native
threads that run simultaneously in the same memory space
and allow web servers to handle requests concurrently without
major impact caused by need in interprocess
communication[8]. Another weak spot of WSGI is that its
design is not suited for non-blocking IO calls. While many
WSGI web servers utilize non-blocking IO internally (see
uWSGI), generally, WSGI design prohibits applications from
yielding control to the web server while they await for non-
blocking operations to finish. Thus, it is usually impossible to
handle other requests in the same worker while the application
waits for non-blocking API calls to complete. It could be
mitigated by using Gevent, which patches IO calls and
replaces them with non-blocking versions. It comes with a
cost, since Gevent can’t patch all of the IO calls, especially
made in unsupported packages, additionally, not many WSGI
servers support Gevent. With the GIL in place and given
WSGI's constraints, the most popular option to support
running multiple requests simultaneously is to run web servers
with multiple processes, which is significantly more resource-
expensive than running them using threads.
ASGI solves this issue by utilizing Python coroutines and
allowing its implementations & applications to take advantage
of advanced features such as non-blocking IO. By using a
non-blocking API, web servers can handle hundreds or
thousands of simultaneous connections/requests, which is
challenging for WSGI-based applications. The very design of
ASGI forces developers to utilize coroutines.
1.5 Objective
Currently there are many implementations of ASGI protocol
servers, 3 most popular (according to their rating on
Github.com) are:
uvicorn - the most widely used ASGI web server, currently
supports only the HTTP/1.1 and WebSockets protocols[5].
daphne - is one of the first ASGI implementations. It was
developed for the Django project, specifically for Django
channels.
hypercorn - ASGI web server, that supports HTTP/1, HTTP/2
and WebSockets (over HTTP/1 and HTTP/2) protocols.
Each web server evaluated in this research fully supports the
ASGI protocol and offers integration capabilities with ASGI
web applications. Presently, there exists an absence of
definitive guidance for developers regarding the selection
among these distinct ASGI implementations. This study is
designed to methodically investigate the differences among
the three principal ASGI servers—focusing on a
comprehensive evaluation employing quantitative
performance metrics alongside qualitative feature analysis.
The aim is to equip software engineers, software architects,
and solution architects with definitive guidelines delineating
the advantages and limitations inherent in each option. By
elucidating the strengths and weaknesses of each server, this
study intends to aid in the selection of the most suitable server
for specific applications, thereby enhancing the efficiency,
reliability, and overall user experience in web application
development.
2. RELATED LITERATURE
The topic of measuring software performance, and
specifically web servers, is well studied. For example,
Radhakrishnan and John [9] researched a difference between
serving static and dynamic data by web servers in a controlled
environment. In their 2011 work, Abbas and Kumar study the
performance of Web Servers as perceived by clients. They
focused on 2 scenarios: when there is no data flow between
Web Server and client, and when there is a data flow from
web server to client [10].
Ehrlich, Hariharan, Reeser and Mei (2001) proposed an end-
to-end performance model for Web-servers in distributing
computing and predictions produced by the model matched
the performance measured in the test environment.