MCPcopy Index your code
hub / github.com/cloudius-systems/osv

github.com/cloudius-systems/osv @v0.57.0

Chat with this repo
repository ↗ · DeepWiki ↗ · release v0.57.0 ↗ · + Follow
19,466 symbols 57,544 edges 1,966 files 3,143 documented · 16%
What it actually does AI analysis from the code graph — generated when you open this
loading…
README

OSv was originally designed and implemented by Cloudius Systems (now ScyllaDB) however currently it is being maintained and enhanced by a small community of volunteers. If you are into systems programming or want to learn and help us improve OSv, then please contact us on OSv Google Group forum or feel free to pickup any good issues for newcomers. For details on how to format and send patches, please read this wiki (we do NOT accept pull requests).

OSv

OSv is an open-source versatile modular unikernel designed to run single unmodified Linux application securely as microVM on top of a hypervisor, when compared to traditional operating systems which were designed for a vast range of physical machines. Built from the ground up for effortless deployment and management of microservices and serverless apps, with superior performance.

OSv has been designed to run unmodified x86-64 and AArch64 Linux binaries as is, which effectively makes it a Linux binary compatible unikernel (for more details about Linux ABI compatibility please read this doc). In particular OSv can run many managed language runtimes including JVM, Python, Node.JS, Ruby, Erlang, and applications built on top of those runtimes. It can also run applications written in languages compiling directly to native machine code like C, C++, Golang and Rust as well as native images produced by GraalVM and WebAssembly/Wasmer.

OSv can boot as fast as ~5 ms on Firecracker using as low as 15 MB of memory. OSv can run on many hypervisors including QEMU/KVM, Firecracker, Cloud Hypervisor, Xen, VMWare, VirtualBox and Hyperkit as well as open clouds like AWS EC2, GCE and OpenStack.

For more information about OSv, see the main wiki page and http://osv.io/.

Building and Running Apps on OSv

In order to run an application on OSv, one needs to build an image by fusing OSv kernel, and the application files together. This, in high level can be achieved in two ways, either: - by using the shell script located at ./scripts/build that builds the kernel from sources and fuses it with application files, or - by using the capstan tool that uses pre-built kernel and combines it with application files to produce a final image.

If your intention is to try to run your app on OSv with the least effort possible, you should pursue the capstan route. For introduction please read this crash course. For more details about capstan please read this more detailed documentation. Pre-built OSv kernel files (ovs-loader.qemu) can be automatically downloaded by capstan from the OSv regular releases page or manually from the nightly releases repo.

If you are comfortable with make and GCC toolchain and want to try the latest OSv code, then you should read this part of the readme to guide you how to set up your development environment and build OSv kernel and application images.

Releases

We aim to release OSv 2-3 times a year. You can find the latest one on github along with number of published artifacts including kernel and some modules.

In addition, we have set up Travis-based CI/CD pipeline where each commit to the master and ipv6 branches triggers full build of the latest kernel and publishes some artifacts to the nightly releases repo. Each commit also triggers publishing of new Docker "build tool chain" images to the Docker hub.

Design

Good bit of the design of OSv is pretty well explained in the Components of OSv wiki page. You can find even more information in the original USENIX paper and its presentation.

In addition, you can find a lot of good information about design of specific OSv components on the main wiki page and http://osv.io/ and http://blog.osv.io/. Unfortunately, some of that information may be outdated (especially on http://osv.io/), so it is always best to ask on the mailing list if in doubt.

Metrics and Performance

There are no official up-to date performance metrics comparing OSv to other unikernels or Linux. In general OSv lags behind Linux in disk-I/O-intensive workloads partially due to coarse-grained locking in VFS around read/write operations as described in this issue. In network-I/O-intensive workloads, OSv should fare better (or at least used to as Linux has advanced a lot since) as shown with performance tests of Redis and Memcached. You can find some old "numbers" on the main wiki, http://osv.io/benchmarks and some papers listed at the bottom of this readme.

So OSv is probably not best suited to run MySQL or ElasticSearch, but should deliver pretty solid performance for general stateless applications like microservices or serverless (at least as some papers show).

Kernel Size

At this moment (as of July 2021) the size of the uncompressed OSv kernel (kernel.elf artifact) is around 6.7 MB (the compressed is ~ 2.7 MB). This is not that small comparing to Linux kernel and quite large comparing to other unikernels. However, bear in mind that OSv kernel (being unikernel) provides subset of functionality of the following Linux libraries (see their approximate size on Linux host): - libresolv.so.2 (100 K) - libc.so.6 (2 MB) - libm.so.6 (1.4 MB) - ld-linux-x86-64.so.2 (184 K) - libpthread.so.0 (156 K) - libdl.so.2 (20 K) - librt.so.1 (40 K) - libstdc++.so.6 (2 MB) - libaio.so.1 (16 K) - libxenstore.so.3.0 (32 K) - libcrypt.so.1 (44 K)

The equivalent static version of libstdc++.so.6 is actually linked --whole-archive so that any C++ apps can run without having to add libstdc++.so.6 to the image (whether it needs it or not). Finally, OSv kernel comes with ZFS implementation which in theory later can be extracted as a separate library. The point of this is to illustrate that comparing OSv kernel size to Linux kernel size does not quite make sense.

Boot Time

OSv, with Read-Only FS and networking off, can boot as fast as ~5 ms on Firecracker and even faster around ~3 ms on QEMU with the microvm machine. However, in general the boot time will depend on many factors like hypervisor including settings of individual para-virtual devices, filesystem (ZFS, ROFS, RAMFS or Virtio-FS) and some boot parameters. Please note that by default OSv images get built with ZFS filesystem.

For example, the boot time of ZFS image on Firecracker is ~40 ms and regular QEMU ~200 ms these days. Also, newer versions of QEMU (>=4.0) are typically faster to boot. Booting on QEMU in PVH/HVM mode (aka direct kernel boot, enabled by -k option of run.py) should always be faster as OSv is directly invoked in 64-bit long mode. Please see this Wiki for the brief review of the boot methods OSv supports.

Finally, some boot parameters passed to the kernel may affect the boot time: - --console serial - this disables VGA console that is slow to initialize and can shave off 60-70 ms on QEMU - --nopci - this disables enumeration of PCI devices especially if we know none are present (QEMU with microvm or Firecracker) and can shave off 10-20 ms - --redirect=/tmp/out - writing to the console can impact the performance quite severely (30-40%) if application logs a lot, so redirecting standard output and error to a file might speed up performance quite a lot

You can always see boot time breakdown by adding --bootchart parameter:

./scripts/run.py -e '--bootchart /hello'
OSv v0.54.0-197-g1f0df4e4
eth0: 192.168.122.15
    disk read (real mode): 25.85ms, (+25.85ms)
    uncompress lzloader.elf: 45.11ms, (+19.26ms)
    TLS initialization: 45.72ms, (+0.61ms)
    .init functions: 47.61ms, (+1.89ms)
    SMP launched: 48.08ms, (+0.47ms)
    VFS initialized: 50.99ms, (+2.91ms)
    Network initialized: 51.12ms, (+0.14ms)
    pvpanic done: 51.25ms, (+0.13ms)
    pci enumerated: 61.55ms, (+10.29ms)
    drivers probe: 61.55ms, (+0.00ms)
    drivers loaded: 135.91ms, (+74.36ms)
    ROFS mounted: 136.98ms, (+1.07ms)
    Total time: 138.16ms, (+1.18ms)
Cmdline: /hello
Hello from C code

Memory Utilization

OSv needs at least 15 M of memory to run a hello world app. Even though it is half of what it was 2 years ago, it is still quite a lot comparing to other unikernels. We are planning to further lower this number by reducing size of the kernel, adding self-tuning logic to L1/L2 memory pools and making application threads use lazily allocated stacks.

Testing

OSv comes with around 140 unit tests that get executed upon every commit and run on ScyllaDB servers. There are also number of extra tests located under tests/ sub-tree that are not automated at this point.

You can run unit tests in number of ways:

./scripts/build check                  # Create ZFS test image and run all tests on QEMU

./scripts/build check fs=rofs          # Create ROFS test image and run all tests on QEMU

./scripts/build image=tests && \       # Create ZFS test image and run all tests on Firecracker
./scripts/test.py -p firecracker

./scripts/build image=tests && \       # Create ZFS test image and run all tests on QEMU
./scripts/test.py -p qemu_microvm      # with microvm machine

In addition, there is an Automated Testing Framework that can be used to run around 30 real apps, some of them under stress using ab or wrk tools. The intention is to catch any regressions that might be missed by unit tests.

Finally, one can use Docker files to test OSv on different Linux distribution.

Setting up Development Environment

OSv can only be built on a 64-bit x86 and ARM Linux distribution. Please note that this means the "x86_64" or "amd64" version for 64-bit x86 and "aarch64" or "arm64" version for ARM respectively.

In order to build OSv kernel you need a physical or virtual machine with Linux distribution on it and GCC toolchain and all necessary packages and libraries OSv build process depends on. The fastest way to set it up is to use the Docker files that OSv comes with. You can use them to build your own Docker image and then start it in order to build OSv kernel or run an app on OSv inside of it. Please note that the main docker file depends on pre-built base Docker images for Ubuntu or Fedora that get published to DockerHub upon every commit. This should speed up building the final images as all necessary packages are installed as part of the base images.

Alternatively, you can manually clone OSv repo and use setup.py to install all required packages and libraries, as long as it supports your Linux distribution, and you have both git and python 3 installed on your machine:

git clone https://github.com/cloudius-systems/osv.git
cd osv && git submodule update --init --recursive
./scripts/setup.py

The setup.py recognizes and installs packages for number of Linux distributions including Fedora, Ubuntu, Debian, LinuxMint and RedHat ones (Scientific Linux, NauLinux, CentOS Linux, Red Hat Enterprise Linux, Oracle Linux). Please note that we actively maintain and te

Extension points exported contracts — how you extend this code

Test (Interface)
(no doc) [56 implementers]
modules/java-mgmt/cloudius/src/main/java/com/cloudius/cli/tests/Test.java
JvmFactory (Interface)
(no doc) [2 implementers]
modules/java-base/runjava-common/src/main/java/io/osv/RunJvmAppHelper.java
IStty (Interface)
(no doc) [2 implementers]
modules/java-mgmt/cloudius/src/main/java/com/cloudius/util/IStty.java
Initializer (Interface)
(no doc) [1 implementers]
modules/java-base/runjava-isolated/src/main/java/io/osv/util/LazilyInitialized.java

Core symbols most depended-on inside this repo

assert
called by 992
tests/tst-queue-mpsc.cc
mutex_exit
called by 762
bsd/cddl/contrib/opensolaris/lib/libzpool/common/kernel.c
mutex_enter
called by 557
bsd/cddl/contrib/opensolaris/lib/libzpool/common/kernel.c
free
called by 421
bsd/sys/sys/malloc.h
nvlist_free
called by 379
bsd/sys/cddl/contrib/opensolaris/common/nvpair/nvpair.c
print
called by 325
tests/tst-printf.cc
close
called by 304
fs/vfs/main.cc
size
called by 248
core/mmu.cc

Shape

Function 9,693
Class 5,642
Method 3,811
Enum 315
Interface 5

Languages

C++65%
C27%
Python5%
Java2%

Modules by API surface

core/mmu.cc212 symbols
scripts/loader.py185 symbols
bsd/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_ioctl.c171 symbols
bsd/sys/cddl/contrib/opensolaris/common/nvpair/nvpair.c162 symbols
bsd/cddl/contrib/opensolaris/cmd/ztest/ztest.c148 symbols
bsd/cddl/contrib/opensolaris/cmd/zfs/zfs_main.c138 symbols
core/mempool.cc135 symbols
include/osv/sched.hh128 symbols
fs/vfs/main.cc123 symbols
bsd/sys/net/if.cc117 symbols
bsd/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/arc.c115 symbols
libc/pthread.cc112 symbols

For agents

$ claude mcp add osv \
  -- python -m otcore.mcp_server <graph>

⬇ download graph artifact