oldisim is a framework to support benchmarks that emulate Online Data- Intensive (OLDI) workloads.
OLDI workloads are user-facing workloads that mine massive datasets across many servers
- Strict Service Level Objectives (SLO): e.g. 99%-ile tail latency is 5ms
- High fan-out with large distributed state
- Extremely challenging to perform power management
Some examples are web search and social networking.
The following are the required to build oldisim from this repo.
Requirements:
- SCons compiler
- C++11 compatible compiler, e.g., g++ v.4.7.3 or later versions.
- Boost version 1.53 or higher (included).
- Cereal (included as a submodule).
Install the requirements with:
$ sudo apt-get install build-essential gengetopt libgoogle-perftools-dev
libunwind7-dev libevent-dev scons libboost-all-dev
To build oldisim, ensure that all submodules are available (git submodule update --init
) and run scons
in the root directory of the project.
If you need to create static libraries, put the following in a new file named custom.py in the project root:
RELEASE=1
STATICLINK=1
TCMALLOC=1
CXX='<PATH_TO_g++>'
LD='<PATH_TO_LD>'
AR='<PATH_TO_AR>'
NM='<PATH_TO_NM>'
CPPPATH=['/usr/include/', '<PATH_TO_BOOST_FILES>']
LIBPATH='/usr/lib/'
Note that you don’t need to build the boost library, as the dependency on lock free queues does not require a built libboost.
To speedup compilation, scons supports parallel compilation, e.g. scons -j12
to compile with 12 threads in parallel. There are two build modes,
release and debug. The default build mode is release.
debug mode may be specified by passing RELEASE=0
to scons
, e.g. scons RELEASE=0
.
The output of the builds will be put into <BUILD_MODE>/
There are several output directories in the build, corresponding to the different parts of oldisim.
- BUILD_MODE/oldisim contains the oldisim framework libraries
- BUILD_MODE/workloads contains the binaries of the workloads built
This benchmark emulates the fanout and request time distribution for web search. It models an example tree-based search topology. A user query is first processed by a front-end server, and eventually fanned out to a set of leaf nodes.
The search benchmark consists of four modules - RootNode, LeafNode, DriverNode, and LoadBalancer. Note that LoadBalancer is only needed when there exist more than one root.
To emulate a tree topology with M roots and N leafs, your cluster needs to have M machines to run RootNode, N machines to run LeafNode and one machine to run DriverNode.
If M is larger than 1, one more machine is needed to enable LoadBalancer.
Copy the binary (release/workloads/search/LeafNode) to all the machines allocated for LeafNode.
Run the following command:
$ PATH_TO_BINARY/LeafNode
Copy the binary (release/workloads/search/ParentNode) to all the machines allocated for RootNode.
Run the following command:
$ PATH_TO_BINARY/ParentNode --leaf=<LeafNode machine 1> ... --leaf=<LeafNode machine N>
Copy the binary (release/workloads/search/LoadBalancerNode) to the machine allocated for LoadBalancerNode.
Run the following command:
$ PATH_TO_BINARY/LoadBalancerNode --parent=<RootNode machine 1> ... --parent=<RootNode machine M>
Copy the binary (release/workloads/search/DriverNode) to the machine allocated for DriverNode.
Run the following command:
$ PATH_TO_BINARY/DriverNode --server=<RootNode machine 1> ... --server=<RootNode machine M>
You can run with the '--help' flag for more usage details.
Optionally you can run oldisim from the PerfKitBenchmarker using:
$ ./pkb.py --benchmarks=oldisim --cloud=[GCP|AZURE|AWS|...] ... --oldisim_num_leaves=[1|2|...|64] --oldisim_fanout=[1,2,...] --oldisim_latency_target=[1|2|...] --oldisim_latency_metric=[avg|50p|90p|95p|99p|99.9p]
$ ./pkb.py --project=<GCP project ID> --benchmarks=oldisim --machine_type=f1-micro --oldisim_num_leaves=4 --oldisim_fanout=1,2,3,4 --oldisim_latency_target=40 --oldisim_latency_metric=avg
$ ./pkb.py --cloud=AWS --benchmarks=oldisim --machine_type=t1.micro --oldisim_num_leaves=4 --oldisim_fanout=1,2,3,4 --oldisim_latency_target=40 --oldisim_latency_metric=avg
$ ./pkb.py --cloud=Azure --machine_type=ExtraSmall --benchmarks=oldisim --oldisim_num_leaves=4 --oldisim_fanout=1,2,3,4 --oldisim_latency_target=40 --oldisim_latency_metric=avg
Below is a sample output of oldisim running with 4 leaves.
Scaling efficiency of 1 leaves 1.0
Scaling efficiency of 2 leaves 0.92
Scaling efficiency of 3 leaves 0.89
Scaling efficiency of 4 leaves 0.88
The scaling efficiency of N leaves is calculated by dividing its QPS by the QPS with one leaf node. It measures the efficiency of scaling out to multiple nodes (or sharding). Sharding happens when we need to handle large data volumes (e.g. data cannot fit in one machine) and high query loads. It also helps to avoid a single point of failure.
Due to performance variation among machines, QPS with sharding is usually limited by the slowest node. This will cause a QPS loss comparing to the single node case. The goal of oldisim is to provide an accurate measurement for the scaling efficiency of sharding.