├── dmclock-targets.cmake ├── .gitignore ├── COPYING ├── sim ├── CMakeLists.txt ├── dmc_sim_100th.conf ├── src │ ├── test_ssched.cc │ ├── ssched │ │ ├── ssched_recs.h │ │ ├── ssched_client.h │ │ └── ssched_server.h │ ├── CMakeLists.txt │ ├── test_dmclock.cc │ ├── test_dmclock.h │ ├── test_ssched.h │ ├── str_list.cc │ ├── ConfUtils.h │ ├── sim_recs.h │ ├── str_list.h │ ├── config.h │ ├── config.cc │ ├── test_ssched_main.cc │ ├── sim_server.h │ ├── sim_client.h │ ├── test_dmclock_main.cc │ ├── simulate.h │ └── ConfUtils.cc └── dmc_sim_example.conf ├── .travis.yml ├── src ├── CMakeLists.txt ├── dmclock_util.cc ├── dmclock_util.h ├── dmclock_recs.h └── dmclock_client.h ├── support ├── src │ ├── debug.h │ ├── run_every.cc │ ├── run_every.h │ ├── profile.h │ ├── heap.h │ ├── intrusive_heap.h │ └── indirect_intrusive_heap.h └── test │ ├── CMakeLists.txt │ ├── test_intrusive_heap.cc │ └── test_ind_intru_heap.cc ├── benchmark ├── run.sh ├── configs │ ├── dmc_sim_100_100.conf │ └── dmc_sim_8_6.conf ├── plot_gen.sh ├── data_gen.sh ├── README.md └── data_parser.py ├── dmclock-config.cmake.in ├── test ├── CMakeLists.txt ├── dmcPrCtl.h ├── test_test_client.cc └── test_dmclock_client.cc ├── CMakeLists.txt ├── README.md └── cmake └── modules └── BuildGTest.cmake /dmclock-targets.cmake: -------------------------------------------------------------------------------- 1 | export(PACKAGE dmclock) 2 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | *~ 2 | *.dSYM 3 | *.o 4 | build* 5 | cscope.* 6 | -------------------------------------------------------------------------------- /COPYING: -------------------------------------------------------------------------------- 1 | Files: * 2 | Copyright: (C) 2016-2018 by Red Hat Inc. 3 | License: LGPL2.1 (see COPYING-LGPL2.1) 4 | -------------------------------------------------------------------------------- /sim/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | set(K_WAY_HEAP "" CACHE STRING "K_WAY_HEAP") 2 | 3 | if(K_WAY_HEAP) 4 | if(K_WAY_HEAP LESS 2) 5 | message(FATAL_ERROR "K_WAY_HEAP value should be at least 2") 6 | else() 7 | set(CMAKE_CXX_SIM_FLAGS "-DK_WAY_HEAP=${K_WAY_HEAP}") 8 | endif() 9 | endif() 10 | 11 | add_subdirectory(src) 12 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: cpp 2 | cache: ccache 3 | dist: focal 4 | sudo: false 5 | branches: 6 | only: 7 | - master 8 | os: 9 | - linux 10 | compiler: 11 | - clang 12 | - gcc 13 | addons: 14 | apt: 15 | packages: 16 | - cmake 17 | - libgtest-dev 18 | - libboost-dev 19 | before_script: 20 | - mkdir build 21 | - cd build 22 | script: 23 | - cmake .. 24 | - cmake --build . -- -j2 && ctest -V -j2 25 | env: 26 | global: 27 | - LANG="en_US.UTF-8" 28 | -------------------------------------------------------------------------------- /src/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | set(dmc_srcs dmclock_util.cc ../support/src/run_every.cc) 2 | 3 | add_library(dmclock STATIC ${dmc_srcs}) 4 | add_library(dmclock::dmclock ALIAS dmclock) 5 | 6 | target_compile_options(dmclock PRIVATE 7 | "-Wno-write-strings" "-Wall") 8 | target_include_directories(dmclock PUBLIC 9 | $ 10 | $) 11 | 12 | target_link_libraries(dmclock 13 | PUBLIC Boost::boost 14 | PRIVATE Threads::Threads) 15 | -------------------------------------------------------------------------------- /support/src/debug.h: -------------------------------------------------------------------------------- 1 | // -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*- 2 | // vim: ts=8 sw=2 smarttab 3 | 4 | /* 5 | * Copyright (C) 2016 Red Hat Inc. 6 | * 7 | * Author: J. Eric Ivancich 8 | * 9 | * This is free software; you can redistribute it and/or modify it 10 | * under the terms of the GNU Lesser General Public License version 11 | * 2.1, as published by the Free Software Foundation. See file 12 | * COPYING. 13 | */ 14 | 15 | 16 | #pragma once 17 | 18 | 19 | #include 20 | 21 | 22 | inline void debugger() { 23 | raise(SIGCONT); 24 | } 25 | -------------------------------------------------------------------------------- /benchmark/run.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # default value 4 | k_way=3 #11 5 | repeat=2 #5 6 | 7 | output_file="" 8 | if [ "$1" != "" ]; then 9 | output_file="$1" 10 | else 11 | echo "Please provide the name of the output file" 12 | exit 13 | fi 14 | 15 | echo "generating file ${output_file}" 16 | sh data_gen.sh ${output_file} ${k_way} ${repeat} 17 | 18 | echo "converting ${output_file} to ${output_file}.dat" 19 | python data_parser.py ${output_file} 20 | 21 | echo "now generating bar-chart" 22 | #gnuplot -e 'output_file=value' plot_gen.gnuplot 23 | sh plot_gen.sh ${output_file} ${k_way} 24 | echo "done! check ${output_file}.pdf" 25 | -------------------------------------------------------------------------------- /dmclock-config.cmake.in: -------------------------------------------------------------------------------- 1 | # - Config file for the FooBar package 2 | # It defines the following variables 3 | # DMCLOCK_INCLUDE_DIRS - include directories for FooBar 4 | # DMCLOCK_LIBRARIES - libraries to link against 5 | 6 | # Compute paths 7 | get_filename_component(DMCLOCK_CMAKE_DIR "${CMAKE_CURRENT_LIST_FILE}" PATH) 8 | set(DMCLOCK_INCLUDE_DIRS "${DMCLOCK_CMAKE_DIR}/src") 9 | # set(DMCLOCK_INCLUDE_DIRS "@CONF_INCLUDE_DIRS@") 10 | 11 | # Our library dependencies (contains definitions for IMPORTED targets) 12 | if(NOT TARGET dmclock AND NOT dmclock_BINARY_DIR) 13 | include("${DMCLOCK_CMAKE_DIR}/dmclock-targets.cmake") 14 | endif() 15 | 16 | # These are IMPORTED targets created by FooBarTargets.cmake 17 | set(DMCLOCK_LIBRARIES dmclock) 18 | -------------------------------------------------------------------------------- /benchmark/configs/dmc_sim_100_100.conf: -------------------------------------------------------------------------------- 1 | [global] 2 | server_groups = 1 3 | client_groups = 2 4 | server_random_selection = true 5 | server_soft_limit = true 6 | 7 | [server.0] 8 | server_count = 100 9 | server_iops = 160 10 | 11 | [client.0] 12 | client_count = 99 13 | client_wait = 0 14 | client_total_ops = 10000 15 | client_server_select_range = 100 16 | client_iops_goal = 200 17 | client_outstanding_ops = 32 18 | client_reservation = 100.0 19 | client_limit = 0.0 20 | client_weight = 1.0 21 | 22 | [client.1] 23 | client_count = 1 24 | client_wait = 10 25 | client_total_ops = 10000 26 | client_server_select_range = 100 27 | client_iops_goal = 200 28 | client_outstanding_ops = 32 29 | client_reservation = 100.0 30 | client_limit = 0.0 31 | client_weight = 1.0 32 | -------------------------------------------------------------------------------- /sim/dmc_sim_100th.conf: -------------------------------------------------------------------------------- 1 | [global] 2 | server_groups = 1 3 | client_groups = 2 4 | server_random_selection = true 5 | server_soft_limit = true 6 | 7 | [client.0] 8 | client_count = 99 9 | client_wait = 0 10 | client_total_ops = 1000 11 | client_server_select_range = 10 12 | client_iops_goal = 50 13 | client_outstanding_ops = 100 14 | client_reservation = 20.0 15 | client_limit = 60.0 16 | client_weight = 1.0 17 | 18 | [client.1] 19 | client_count = 1 20 | client_wait = 10 21 | client_total_ops = 1000 22 | client_server_select_range = 10 23 | client_iops_goal = 50 24 | client_outstanding_ops = 100 25 | client_reservation = 20.0 26 | client_limit = 60.0 27 | client_weight = 1.0 28 | 29 | [server.0] 30 | server_count = 100 31 | server_iops = 40 32 | server_threads = 1 33 | -------------------------------------------------------------------------------- /support/test/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | include_directories(../src) 2 | 3 | set(local_flags "-Wall -pthread") 4 | 5 | # dmclock does not use intrusive heap (but it does use indirect 6 | # intrusive heap), so we won't use this code 7 | if(false) 8 | set(srcs 9 | test_intrusive_heap.cc) 10 | add_executable(test_intru_heap test_intrusive_heap.cc) 11 | set_source_files_properties(${srcs} 12 | PROPERTIES 13 | COMPILE_FLAGS "${local_flags}") 14 | endif(false) 15 | 16 | set(test_srcs test_indirect_intrusive_heap.cc) 17 | 18 | set_source_files_properties(${test_srcs} 19 | PROPERTIES 20 | COMPILE_FLAGS "${local_flags}" 21 | ) 22 | 23 | add_executable(dmclock-data-struct-tests ${test_srcs}) 24 | 25 | target_link_libraries(dmclock-data-struct-tests 26 | LINK_PRIVATE GTest::GTest GTest::Main Threads::Threads) 27 | -------------------------------------------------------------------------------- /src/dmclock_util.cc: -------------------------------------------------------------------------------- 1 | // -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*- 2 | // vim: ts=8 sw=2 smarttab 3 | 4 | /* 5 | * Copyright (C) 2017 Red Hat Inc. 6 | * 7 | * Author: J. Eric Ivancich 8 | * 9 | * This is free software; you can redistribute it and/or modify it 10 | * under the terms of the GNU Lesser General Public License version 11 | * 2.1, as published by the Free Software Foundation. See file 12 | * COPYING. 13 | */ 14 | 15 | 16 | #include 17 | 18 | #include 19 | #include 20 | 21 | #include "dmclock_util.h" 22 | 23 | 24 | std::string crimson::dmclock::format_time(const Time& time, unsigned modulo) { 25 | long subtract = long(time / modulo) * modulo; 26 | std::stringstream ss; 27 | ss << std::fixed << std::setprecision(4) << (time - subtract); 28 | return ss.str(); 29 | } 30 | 31 | 32 | void crimson::dmclock::debugger() { 33 | #ifndef _WIN32 34 | raise(SIGCONT); 35 | #else 36 | DebugBreak(); 37 | #endif 38 | } 39 | -------------------------------------------------------------------------------- /benchmark/configs/dmc_sim_8_6.conf: -------------------------------------------------------------------------------- 1 | [global] 2 | server_groups = 1 3 | client_groups = 3 4 | server_random_selection = true 5 | server_soft_limit = true 6 | 7 | [client.0] 8 | client_count = 2 9 | client_wait = 0 10 | client_total_ops = 1000 11 | client_server_select_range = 8 12 | client_iops_goal = 200 13 | client_outstanding_ops = 32 14 | client_reservation = 0.0 15 | client_limit = 0.0 16 | client_weight = 1.0 17 | 18 | [client.1] 19 | client_count = 2 20 | client_wait = 5 21 | client_total_ops = 1000 22 | client_server_select_range = 8 23 | client_iops_goal = 200 24 | client_outstanding_ops = 32 25 | client_reservation = 20.0 26 | client_limit = 40.0 27 | client_weight = 1.0 28 | 29 | [client.2] 30 | client_count = 2 31 | client_wait = 10 32 | client_total_ops = 1000 33 | client_server_select_range = 8 34 | client_iops_goal = 200 35 | client_outstanding_ops = 32 36 | client_reservation = 0.0 37 | client_limit = 50.0 38 | client_weight = 2.0 39 | 40 | 41 | [server.0] 42 | server_count = 8 43 | server_iops = 160 44 | -------------------------------------------------------------------------------- /test/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | include(CheckIncludeFileCXX) 2 | check_include_file_cxx("sys/prctl.h" HAVE_SYS_PRCTL_H) 3 | 4 | set(support_srcs ../sim/src/test_dmclock.cc) 5 | set(test_srcs 6 | test_test_client.cc 7 | test_dmclock_server.cc 8 | test_dmclock_client.cc 9 | ) 10 | 11 | set_source_files_properties(${core_srcs} ${test_srcs} 12 | PROPERTIES 13 | COMPILE_FLAGS "${local_flags}" 14 | ) 15 | 16 | add_executable(dmclock-tests ${test_srcs} ${support_srcs}) 17 | if(HAVE_SYS_PRCTL_H) 18 | target_compile_definitions(dmclock-tests PRIVATE "HAVE_SYS_PRCTL_H") 19 | endif() 20 | target_include_directories(dmclock-tests PRIVATE 21 | ../sim/src ${CMAKE_CURRENT_BINARY_DIR}) 22 | target_include_directories(dmclock-tests PRIVATE SYSTEM 23 | "${GTEST_INCLUDE_DIRS}") 24 | 25 | target_link_libraries(dmclock-tests LINK_PRIVATE 26 | dmclock 27 | Threads::Threads 28 | GTest::GTest 29 | GTest::Main) 30 | 31 | add_test(NAME dmclock-tests 32 | COMMAND $) 33 | add_test(NAME dmclock-data-struct-tests 34 | COMMAND $) 35 | -------------------------------------------------------------------------------- /sim/src/test_ssched.cc: -------------------------------------------------------------------------------- 1 | // -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*- 2 | // vim: ts=8 sw=2 smarttab 3 | 4 | /* 5 | * Copyright (C) 2016 Red Hat Inc. 6 | * 7 | * Author: J. Eric Ivancich 8 | * 9 | * This is free software; you can redistribute it and/or modify it 10 | * under the terms of the GNU Lesser General Public License version 11 | * 2.1, as published by the Free Software Foundation. See file 12 | * COPYING. 13 | */ 14 | 15 | 16 | #include "ssched_recs.h" 17 | #include "ssched_server.h" 18 | #include "ssched_client.h" 19 | 20 | #include "sim_recs.h" 21 | #include "sim_server.h" 22 | #include "sim_client.h" 23 | 24 | #include "test_ssched.h" 25 | 26 | 27 | namespace test = crimson::test_simple_scheduler; 28 | namespace ssched = crimson::simple_scheduler; 29 | 30 | 31 | void test::simple_server_accumulate_f(test::SimpleAccum& a, 32 | const ssched::NullData& add_info) { 33 | ++a.request_count; 34 | } 35 | 36 | 37 | void test::simple_client_accumulate_f(test::SimpleAccum& a, 38 | const ssched::NullData& ignore) { 39 | // empty 40 | } 41 | -------------------------------------------------------------------------------- /sim/src/ssched/ssched_recs.h: -------------------------------------------------------------------------------- 1 | // -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*- 2 | // vim: ts=8 sw=2 smarttab 3 | 4 | /* 5 | * Copyright (C) 2016 Red Hat Inc. 6 | * 7 | * Author: J. Eric Ivancich 8 | * 9 | * This is free software; you can redistribute it and/or modify it 10 | * under the terms of the GNU Lesser General Public License version 11 | * 2.1, as published by the Free Software Foundation. See file 12 | * COPYING. 13 | */ 14 | 15 | 16 | #pragma once 17 | 18 | 19 | #include 20 | #include 21 | 22 | 23 | namespace crimson { 24 | namespace simple_scheduler { 25 | 26 | // since we send no additional data out 27 | // NOTE: Change name to RespParams? Is it used elsewhere? 28 | struct NullData { 29 | friend std::ostream& operator<<(std::ostream& out, const NullData& n) { 30 | out << "NullData{ EMPTY }"; 31 | return out; 32 | } 33 | }; // struct NullData 34 | 35 | 36 | struct ReqParams { 37 | friend std::ostream& operator<<(std::ostream& out, const ReqParams& rp) { 38 | out << "ReqParams{ EMPTY }"; 39 | return out; 40 | } 41 | }; 42 | 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.5.1) 2 | 3 | project(dmclock CXX) 4 | 5 | list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_LIST_DIR}/cmake/modules") 6 | 7 | if (NOT(BOOST_FOUND)) 8 | find_package(Boost REQUIRED) 9 | endif() 10 | 11 | find_package(Threads) 12 | 13 | if(CMAKE_CXX_STANDARD OR CMAKE_CXX_FLAGS MATCHES "-std=(c|gnu)\\+\\+") 14 | # use existing settings if available 15 | else() 16 | set(CMAKE_CXX_STANDARD 11) 17 | set(CMAKE_CXX_STANDARD_REQUIRED ON) 18 | endif() 19 | 20 | add_subdirectory(src) 21 | 22 | # Determine if dmclock is built as a subproject (using add_subdirectory) 23 | # or if it is the master project. 24 | set(MASTER_PROJECT FALSE) 25 | if(CMAKE_CURRENT_SOURCE_DIR STREQUAL CMAKE_SOURCE_DIR) 26 | set(MASTER_PROJECT TRUE) 27 | endif() 28 | 29 | option(dmclock_TEST "Generate test targets" ${MASTER_PROJECT}) 30 | if(dmclock_TEST) 31 | if (NOT(TARGET gtest AND TARGET gtest_main)) 32 | if (NOT GTEST_FOUND) 33 | find_package(GTest QUIET) 34 | if (NOT GTEST_FOUND) 35 | include(BuildGTest) 36 | endif() 37 | endif() 38 | endif() 39 | 40 | enable_testing() 41 | add_subdirectory(test) 42 | add_subdirectory(support/test) 43 | add_subdirectory(sim) 44 | endif() 45 | -------------------------------------------------------------------------------- /sim/dmc_sim_example.conf: -------------------------------------------------------------------------------- 1 | [global] 2 | server_groups = 1 3 | client_groups = 4 4 | server_random_selection = false 5 | server_soft_limit = false 6 | 7 | [client.0] 8 | client_count = 1 9 | client_wait = 0 10 | client_total_ops = 2000 11 | client_server_select_range = 1 12 | client_iops_goal = 200 13 | client_outstanding_ops = 32 14 | client_reservation = 0.0 15 | client_limit = 0.0 16 | client_weight = 1.0 17 | 18 | [client.1] 19 | client_count = 1 20 | client_wait = 5 21 | client_total_ops = 2000 22 | client_server_select_range = 1 23 | client_iops_goal = 200 24 | client_outstanding_ops = 32 25 | client_reservation = 0.0 26 | client_limit = 40.0 27 | client_weight = 1.0 28 | 29 | [client.2] 30 | client_count = 1 31 | client_wait = 10 32 | client_total_ops = 2000 33 | client_server_select_range = 1 34 | client_iops_goal = 200 35 | client_outstanding_ops = 32 36 | client_reservation = 0.0 37 | client_limit = 50.0 38 | client_weight = 2.0 39 | client_req_cost = 1 40 | 41 | [client.3] 42 | client_count = 1 43 | client_wait = 10 44 | client_total_ops = 2000 45 | client_server_select_range = 1 46 | client_iops_goal = 200 47 | client_outstanding_ops = 32 48 | client_reservation = 0.0 49 | client_limit = 50.0 50 | client_weight = 2.0 51 | client_req_cost = 3 52 | 53 | [server.0] 54 | server_count = 1 55 | server_iops = 160 56 | server_threads = 1 57 | -------------------------------------------------------------------------------- /sim/src/ssched/ssched_client.h: -------------------------------------------------------------------------------- 1 | // -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*- 2 | // vim: ts=8 sw=2 smarttab 3 | 4 | /* 5 | * Copyright (C) 2016 Red Hat Inc. 6 | * 7 | * Author: J. Eric Ivancich 8 | * 9 | * This is free software; you can redistribute it and/or modify it 10 | * under the terms of the GNU Lesser General Public License version 11 | * 2.1, as published by the Free Software Foundation. See file 12 | * COPYING. 13 | */ 14 | 15 | 16 | #pragma once 17 | 18 | #include "ssched_recs.h" 19 | 20 | 21 | namespace crimson { 22 | namespace simple_scheduler { 23 | 24 | // S is server identifier type 25 | template 26 | class ServiceTracker { 27 | 28 | public: 29 | 30 | // we have to start the counters at 1, as 0 is used in the 31 | // cleaning process 32 | ServiceTracker() 33 | { 34 | // empty 35 | } 36 | 37 | void track_resp(const S& server_id, 38 | const NullData& ignore, 39 | uint64_t request_cost) { 40 | // empty 41 | } 42 | 43 | /* 44 | * Returns the ReqParams for the given server. 45 | */ 46 | ReqParams get_req_params(const S& server) { 47 | return ReqParams(); 48 | } // get_req_params 49 | }; // class ServiceTracker 50 | } // namespace simple_scheduler 51 | } // namespace crimson 52 | -------------------------------------------------------------------------------- /sim/src/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | set(local_flags "-Wall ${CMAKE_CXX_SIM_FLAGS}") 2 | 3 | set(ssched_sim_srcs test_ssched.cc test_ssched_main.cc) 4 | set(dmc_sim_srcs test_dmclock.cc test_dmclock_main.cc) 5 | set(config_srcs config.cc str_list.cc ConfUtils.cc) 6 | 7 | set_source_files_properties(${ssched_sim_srcs} ${dmc_sim_srcs} ${dmc_srcs} ${config_srcs} 8 | PROPERTIES 9 | COMPILE_FLAGS "${local_flags}" 10 | ) 11 | 12 | if ("${CMAKE_CXX_COMPILER_ID}" MATCHES "Clang") 13 | set(warnings_off " -Wno-unused-variable -Wno-unused-function") 14 | elseif ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "GNU") 15 | set(warnings_off " -Wno-unused-but-set-variable -Wno-unused-function") 16 | endif() 17 | 18 | # append warning flags to certain source files 19 | set_property( 20 | SOURCE ${ssched_sim_srcs} ${dmc_sim_srcs} ${config_srcs} 21 | APPEND_STRING 22 | PROPERTY COMPILE_FLAGS "${warnings_off}" 23 | ) 24 | 25 | add_executable(ssched_sim EXCLUDE_FROM_ALL ${ssched_sim_srcs}) 26 | target_include_directories(ssched_sim PRIVATE ssched) # ssched code 27 | add_executable(dmc_sim EXCLUDE_FROM_ALL ${dmc_sim_srcs} ${config_srcs}) 28 | 29 | set_target_properties(ssched_sim dmc_sim 30 | PROPERTIES 31 | RUNTIME_OUTPUT_DIRECTORY ..) 32 | 33 | add_dependencies(dmc_sim dmclock) 34 | 35 | target_link_libraries(ssched_sim LINK_PRIVATE Threads::Threads) 36 | target_link_libraries(dmc_sim LINK_PRIVATE dmclock) 37 | 38 | add_custom_target(dmclock-sims DEPENDS ssched_sim dmc_sim) 39 | -------------------------------------------------------------------------------- /benchmark/plot_gen.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | if [ "$1" != "" ]; then 4 | output_file="$1" 5 | else 6 | echo "Please provide the name of the output file" 7 | exit 8 | fi 9 | 10 | # parameter check -- k-value 11 | if [ "$2" != "" ]; then 12 | k_way="$2" 13 | else 14 | echo "Please provide the maximum K_WAY value" 15 | exit 16 | fi 17 | #echo "k-way: $k_way" 18 | #exit 19 | 20 | gnuplot << EOF 21 | 22 | # Note you need gnuplot 4.4 for the pdfcairo terminal. 23 | clear 24 | reset 25 | 26 | set terminal pdfcairo size 7in,5in font "Gill Sans,5" linewidth 1 rounded fontscale .8 noenhanced 27 | set output "${output_file}.pdf" 28 | 29 | # starts multiplot 30 | set multiplot layout 2,1 31 | 32 | # Line style for axes 33 | set style line 80 lt rgb "#808080" 34 | 35 | # Line style for grid 36 | set style line 81 lt 0 # dashed 37 | set style line 81 lt rgb "#808080" # grey 38 | 39 | set grid back linestyle 81 40 | set border 3 back linestyle 80 41 | 42 | #set xtics rotate out 43 | set style data histogram 44 | set style histogram clustered 45 | 46 | set style fill solid border 47 | set xlabel 'Heap Timing for different K values' 48 | set ylabel 'Time (nanosec)' 49 | set key top right 50 | 51 | set yrange [0:*] 52 | 53 | # plot 1 54 | set title 'Request Addition Time' 55 | plot for [COL=2:($k_way + 1)] '${output_file}.dat' using COL:xticlabels(1) title columnheader 56 | 57 | # plot 2 58 | set title 'Request Completion Time' 59 | plot for [COL=($k_way + 2):(2 * $k_way + 1)] '${output_file}.dat' using COL:xticlabels(1) title columnheader 60 | EOF 61 | -------------------------------------------------------------------------------- /test/dmcPrCtl.h: -------------------------------------------------------------------------------- 1 | // -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*- 2 | // vim: ts=8 sw=2 smarttab 3 | 4 | /* 5 | * Ceph - scalable distributed file system 6 | * 7 | * Copyright (C) 2017 Red Hat Inc. 8 | * 9 | * This is free software; you can redistribute it and/or 10 | * modify it under the terms of the GNU Lesser General Public 11 | * License version 2.1, as published by the Free Software 12 | * Foundation. See file COPYING. 13 | * 14 | */ 15 | 16 | // essentially the same as ceph's PrCtl.h, copied into the dmclock library 17 | 18 | #ifdef HAVE_SYS_PRCTL_H 19 | #include 20 | #include 21 | #include 22 | 23 | struct PrCtl { 24 | int saved_state = -1; 25 | int set_dumpable(int new_state) { 26 | int r = prctl(PR_SET_DUMPABLE, new_state); 27 | if (r) { 28 | r = -errno; 29 | std::cerr << "warning: unable to " << (new_state ? "set" : "unset") 30 | << " dumpable flag: " << strerror(r) 31 | << std::endl; 32 | } 33 | return r; 34 | } 35 | PrCtl(int new_state = 0) { 36 | int r = prctl(PR_GET_DUMPABLE); 37 | if (r == -1) { 38 | r = errno; 39 | std::cerr << "warning: unable to get dumpable flag: " << strerror(r) 40 | << std::endl; 41 | } else if (r != new_state) { 42 | if (!set_dumpable(new_state)) { 43 | saved_state = r; 44 | } 45 | } 46 | } 47 | ~PrCtl() { 48 | if (saved_state < 0) { 49 | return; 50 | } 51 | set_dumpable(saved_state); 52 | } 53 | }; 54 | #else 55 | struct PrCtl {}; 56 | #endif 57 | -------------------------------------------------------------------------------- /benchmark/data_gen.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | config_dir="configs" 3 | repeat=2 #5 4 | 5 | # parameter check -- output_file name 6 | if [ "$1" != "" ]; then 7 | output_file="$1" 8 | else 9 | echo "Please provide the name of the output file" 10 | exit 11 | fi 12 | 13 | # parameter check -- k-value 14 | if [ "$2" != "" ]; then 15 | k_way="$2" 16 | else 17 | echo "Please provide the maximum K_WAY value" 18 | exit 19 | fi 20 | 21 | # parameter check --repeat 22 | if [ "$3" != "" ]; then 23 | repeat="$3" 24 | fi 25 | 26 | echo "k-way:$k_way, num_repeat:$repeat" 27 | 28 | # create simulators in different directories 29 | k=2 30 | while [ $k -le $k_way ] 31 | do 32 | mkdir "build_$k" 33 | cd "build_$k" 34 | rm -rf * 35 | cmake -DCMAKE_BUILD_TYPE=Release -DK_WAY_HEAP=$k ../../. 36 | make dmclock-sims 37 | cd .. 38 | 39 | k=$(( $k + 1 )) 40 | done 41 | 42 | # run simulators 43 | echo '' > $output_file 44 | for config in "$config_dir"/*.conf 45 | do 46 | k=2 47 | while [ $k -le $k_way ] 48 | do 49 | cd "build_$k" 50 | 51 | # repeat same experiment 52 | i=0 53 | while [ $i -lt $repeat ] 54 | do 55 | i=$(( $i + 1 )) 56 | 57 | # clear cache first 58 | sync 59 | #sudo sh -c 'echo 1 >/proc/sys/vm/drop_caches' 60 | #sudo sh -c 'echo 2 >/proc/sys/vm/drop_caches' 61 | #sudo sh -c 'echo 3 >/proc/sys/vm/drop_caches' 62 | 63 | # run with heap 64 | msg="file_name:$k:$config" 65 | echo $msg >> ../$output_file 66 | echo "running $msg ..." 67 | ./sim/dmc_sim -c ../$config | awk '(/average/)' >> ../$output_file 68 | done # end repeat 69 | cd .. 70 | k=$(( $k + 1 )) 71 | done # end k_way 72 | done # end config 73 | 74 | -------------------------------------------------------------------------------- /sim/src/test_dmclock.cc: -------------------------------------------------------------------------------- 1 | // -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*- 2 | // vim: ts=8 sw=2 smarttab 3 | 4 | /* 5 | * Copyright (C) 2016 Red Hat Inc. 6 | * 7 | * Author: J. Eric Ivancich 8 | * 9 | * This is free software; you can redistribute it and/or modify it 10 | * under the terms of the GNU Lesser General Public License version 11 | * 2.1, as published by the Free Software Foundation. See file 12 | * COPYING. 13 | */ 14 | 15 | #include 16 | 17 | #include "dmclock_recs.h" 18 | #include "dmclock_server.h" 19 | #include "dmclock_client.h" 20 | 21 | #include "sim_recs.h" 22 | #include "sim_server.h" 23 | #include "sim_client.h" 24 | 25 | #include "test_dmclock.h" 26 | 27 | 28 | namespace test = crimson::test_dmc; 29 | 30 | 31 | // Note: if this static_assert fails then our two definitions of Cost 32 | // do not match; change crimson::qos_simulation::Cost to match the 33 | // definition of crimson::dmclock::Cost. 34 | static_assert(std::is_same::value, 35 | "Please make sure the simulator type crimson::qos_simulation::Cost matches the dmclock type crimson::dmclock::Cost."); 36 | 37 | 38 | void test::dmc_server_accumulate_f(test::DmcAccum& a, 39 | const test::dmc::PhaseType& phase) { 40 | if (test::dmc::PhaseType::reservation == phase) { 41 | ++a.reservation_count; 42 | } else { 43 | ++a.proportion_count; 44 | } 45 | } 46 | 47 | 48 | void test::dmc_client_accumulate_f(test::DmcAccum& a, 49 | const test::dmc::PhaseType& phase) { 50 | if (test::dmc::PhaseType::reservation == phase) { 51 | ++a.reservation_count; 52 | } else { 53 | ++a.proportion_count; 54 | } 55 | } 56 | -------------------------------------------------------------------------------- /benchmark/README.md: -------------------------------------------------------------------------------- 1 | # dmclock benchmarking 2 | 3 | **IMPORTANT**: now that K_WAY_HEAP is no longer allowed to have the 4 | value 1, the shell and Python scripts that generate the PDFs no longer 5 | work exactly correctly. Some effort to debug is necessary. 6 | 7 | This directory contains scripts to evaluate effects of different 8 | branching-factors (k=1 to k=11) in the IndirectIntrusiveHeap 9 | data-structure. IndirectIntrusiveHeap is now a k-way heap, so finding 10 | an ideal value for k (i.e., k=2 or k=3) for a particular work-load is 11 | important. Also, it is well-documented that the right choice of 12 | k-value improves the caching behaviour [Syed -- citation needed 13 | here]. As a result, the overall performance of an application using 14 | k-way heap increases significantly [Syed -- citation needed here]. 15 | 16 | A rule of thumb is the following: 17 | if number of elements are <= 6, use k=1 18 | otherwise, use k=3. 19 | 20 | ## Prerequisites 21 | 22 | requires python 2.7, gnuplot, and awk. 23 | 24 | ## Running benchmark 25 | 26 | ./run.sh [name_of_the_output] [k_way] [repeat] # [Syed -- last two command line args do not work] 27 | 28 | The "run.sh" script looks for config files in the "configs" directory, 29 | and the final output is generated as 30 | "name_of_the_output.pdf". Internally, "run.sh" calls other scripts 31 | such as data_gen.sh, data_parser.py, and plot_gen.sh. 32 | 33 | ## Modifying parameters 34 | 35 | To modify k-value and/or the amount of times each simulation is 36 | repeated, modify the following two variables in "run.sh" file: 37 | 38 | k_way=[your_value] 39 | repeat=[your_value] 40 | 41 | For example, k_way=3 means, the benchmark will compare simulations 42 | using 1-way, 2-way, and 3-way heaps. 43 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # dmclock (deprecated) 2 | 3 | This repository contains C++ 11 code that implements the dmclock 4 | distributed quality of service algorithm. See __mClock: Handling 5 | Throughput Variability for Hypervisor IO Scheduling__ by Gulati, 6 | Merchant, and Varman for a description of the algorithm. 7 | 8 | ## Important Notice 9 | 10 | This repository has been archived. Due to no known users outside 11 | of Ceph, we have moved the dmclock project directly into the 12 | [Ceph repository](https://github.com/ceph/ceph) to simplify backports 13 | and maintenance. 14 | 15 | For any contributions or further development of dmclock, please submit 16 | pull requests to the [Ceph project](https://github.com/ceph/ceph). 17 | 18 | ## Bugs and features 19 | 20 | There is a [dmclock project](https://tracker.ceph.com/projects/dmclock) through 21 | which bugs can be reported and features requested. 22 | 23 | ## Running cmake 24 | 25 | When running cmake, set the build type with either: 26 | 27 | -DCMAKE_BUILD_TYPE=Debug 28 | -DCMAKE_BUILD_TYPE=Release 29 | 30 | To turn on profiling, run cmake with an additional: 31 | 32 | -DPROFILE=yes 33 | 34 | ## Running make 35 | 36 | ### Building the dmclock library 37 | 38 | The `make` command builds a library libdmclock.a. That plus the header 39 | files in the src directory allow one to use the implementation in 40 | their code. 41 | 42 | ### Building unit tests 43 | 44 | The `make dmclock-tests` command builds unit tests. 45 | 46 | ### Building simulations 47 | 48 | The `make dmclock-sims` command builds two simulations -- *dmc_sim* 49 | and *ssched_sim* -- which incorporate, respectively, the dmclock 50 | priority queue or a very simple scheduler for comparison. Other 51 | priority queue implementations could be added in the future. 52 | 53 | ## dmclock API 54 | 55 | To be written.... 56 | -------------------------------------------------------------------------------- /src/dmclock_util.h: -------------------------------------------------------------------------------- 1 | // -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*- 2 | // vim: ts=8 sw=2 smarttab 3 | 4 | /* 5 | * Copyright (C) 2017 Red Hat Inc. 6 | * 7 | * Author: J. Eric Ivancich 8 | * 9 | * This is free software; you can redistribute it and/or modify it 10 | * under the terms of the GNU Lesser General Public License version 11 | * 2.1, as published by the Free Software Foundation. See file 12 | * COPYING. 13 | */ 14 | 15 | 16 | #pragma once 17 | 18 | 19 | #include 20 | #include 21 | #include 22 | 23 | #include 24 | #include 25 | #include 26 | 27 | 28 | namespace crimson { 29 | namespace dmclock { 30 | // we're using double to represent time, but we could change it by 31 | // changing the following declarations (and by making sure a min 32 | // function existed) 33 | using Time = double; 34 | static const Time TimeZero = 0.0; 35 | static const Time TimeMax = std::numeric_limits