├── .github ├── FUNDING.yml └── ISSUE_TEMPLATE │ └── bug.yaml ├── .gitignore ├── .travis.yml ├── CMakeLists.txt ├── LICENSE.md ├── Makefile ├── README.md ├── benchmarks ├── CMakeLists.txt ├── LICENSE.md ├── check-output.sh ├── histogram │ ├── CMakeLists.txt │ ├── histogram-pthread.c │ └── stddefines.h ├── kmeans │ ├── CMakeLists.txt │ ├── kmeans-pthread.c │ └── stddefines.h ├── linear_regression │ ├── CMakeLists.txt │ ├── linear_regression-pthread.c │ └── stddefines.h ├── matrix_multiply │ ├── CMakeLists.txt │ ├── map_reduce.h │ ├── matrix_multiply-pthread.c │ └── stddefines.h ├── pbzip2 │ ├── AUTHORS │ ├── BZ2StreamScanner.cpp │ ├── BZ2StreamScanner.h │ ├── CMakeLists.txt │ ├── COPYING │ ├── ErrorContext.cpp │ ├── ErrorContext.h │ ├── README │ ├── pbzip2.cpp │ └── pbzip2.h ├── pca │ ├── CMakeLists.txt │ ├── pca-pthread.c │ └── stddefines.h ├── producer_consumer │ ├── CMakeLists.txt │ └── producer_consumer.cpp ├── sqlite-modified │ ├── CMakeLists.txt │ ├── main.c │ ├── sqlite3.c │ └── sqlite3.h ├── sqlite │ ├── CMakeLists.txt │ ├── main.c │ ├── sqlite3.c │ └── sqlite3.h ├── string_match │ ├── CMakeLists.txt │ ├── map_reduce.h │ ├── stddefines.h │ └── string_match-pthread.c ├── toy-rs │ ├── Cargo.lock │ ├── Cargo.toml │ └── src │ │ └── main.rs ├── toy │ ├── CMakeLists.txt │ └── toy.cpp └── word_count │ ├── CMakeLists.txt │ ├── sort-pthread.c │ ├── sort-pthread.h │ ├── stddefines.h │ └── word_count-pthread.c ├── cmake ├── Findlibelfin.cmake └── coz-profilerConfig.cmake.in ├── common.mk ├── conanfile.txt ├── coz ├── coz-profilerConfig.cmake.in ├── docs ├── README.md ├── coz.1 └── coz.rst ├── example-coz-output.png ├── include └── coz.h ├── libcoz ├── CMakeLists.txt ├── Makefile ├── ccutil │ ├── log.h │ ├── spinlock.h │ ├── static_map.h │ ├── timer.h │ └── wrapped_array.h ├── inspect.cpp ├── inspect.h ├── libcoz.cpp ├── perf.cpp ├── perf.h ├── profiler.cpp ├── profiler.h ├── progress_point.h ├── real.cpp ├── real.h ├── thread_state.h └── util.h ├── patches ├── blackscholes.patch ├── dedup.patch ├── fluidanimate.patch ├── streamcluster.patch └── swaptions.patch ├── rust ├── Cargo.toml ├── README.md ├── examples │ └── toy.rs ├── src │ └── lib.rs ├── tests │ └── smoke.rs └── toy.png └── viewer ├── Makefile ├── README.md ├── css ├── plot.css └── ui.css ├── index.htm ├── js ├── profile.js ├── profile.js.map ├── ui.js └── ui.js.map ├── lib ├── bootstrap │ ├── bootstrap.css │ ├── bootstrap.css.map │ ├── bootstrap.js │ ├── bootstrap.min.css │ ├── bootstrap.min.css.map │ └── bootstrap.min.js ├── d3 │ ├── d3-tip.js │ ├── d3-tip.min.js │ ├── d3.js │ └── d3.min.js ├── font-awesome │ ├── css │ │ ├── font-awesome.css │ │ └── font-awesome.min.css │ └── fonts │ │ ├── FontAwesome.otf │ │ ├── fontawesome-webfont.eot │ │ ├── fontawesome-webfont.svg │ │ ├── fontawesome-webfont.ttf │ │ ├── fontawesome-webfont.woff │ │ └── fontawesome-webfont.woff2 ├── jquery-3.1.1.js ├── jquery.min.js └── science │ ├── LICENSE.txt │ ├── science.v1.js │ └── science.v1.min.js ├── package-lock.json ├── package.json ├── profiles ├── blackscholes.coz ├── dedup.coz ├── ferret.coz ├── fluidanimate.coz ├── memcached.coz ├── sqlite.coz └── swaptions.coz ├── ts ├── profile.ts └── ui.ts └── tsconfig.json /.github/FUNDING.yml: -------------------------------------------------------------------------------- 1 | # These are supported funding model platforms 2 | 3 | github: [plasma-umass] 4 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/bug.yaml: -------------------------------------------------------------------------------- 1 | name: Bug Report 2 | description: File a bug report for Coz (e.g., a crash or incorrect behavior). 3 | title: "[Bug]: " 4 | labels: ["bug"] 5 | body: 6 | - type: markdown 7 | attributes: 8 | value: | 9 | Thanks for reporting a bug! Please include enough information for us to understand and reproduce your bug. 10 | - type: textarea 11 | id: what-happened 12 | attributes: 13 | label: What happened? 14 | description: What went wrong? What did you expect to happen? 15 | validations: 16 | required: true 17 | - type: textarea 18 | id: mcve 19 | attributes: 20 | label: What code did you run Coz on? 21 | description: Ideally include a short C, C++, or Rust program here that is easy to build and run. 22 | validations: 23 | required: true 24 | - type: textarea 25 | id: coz-version 26 | attributes: 27 | label: Coz Version 28 | description: Where did you get Coz from? If from GitHub, which commit did you build from? If from a Linux package, which package index (e.g. apt) and which package version (e.g. coz 0.2.2-2)? 29 | validations: 30 | required: true 31 | - type: textarea 32 | id: os-version 33 | attributes: 34 | label: OS Version 35 | description: What OS and version are you running? e.g. run `uname -rsp` 36 | placeholder: | 37 | $ uname -rsp 38 | Linux X.X.X-XXX x86_64 39 | render: Shell 40 | validations: 41 | required: true 42 | - type: textarea 43 | id: extra 44 | attributes: 45 | label: Anything else to add? 46 | validations: 47 | required: false 48 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | deps 2 | libcoz/libcoz.so 3 | libcoz/obj 4 | 5 | benchmarks/*/obj 6 | benchmarks/*/profile.coz 7 | 8 | benchmarks/histogram/histogram 9 | benchmarks/kmeans/kmeans 10 | benchmarks/linear_regression/linear_regression 11 | benchmarks/matrix_multiply/matrix_multiply 12 | benchmarks/pbzip2/pbzip2 13 | benchmarks/pca/pca 14 | benchmarks/producer_consumer/producer_consumer 15 | benchmarks/string_match/string_match 16 | benchmarks/sqlite/sqlite-bench 17 | benchmarks/sqlite-modified/sqlite-bench 18 | benchmarks/toy/toy 19 | benchmarks/word_count/word_count 20 | 21 | benchmarks/histogram/histogram_datafiles 22 | benchmarks/linear_regression/linear_regression_datafiles 23 | benchmarks/matrix_multiply/.input_large 24 | benchmarks/matrix_multiply/.input_small 25 | benchmarks/matrix_multiply/matrix_file_A.txt 26 | benchmarks/matrix_multiply/matrix_file_B.txt 27 | benchmarks/matrix_multiply/matrix_file_out_pthreads.txt 28 | benchmarks/pbzip2/data 29 | benchmarks/pbzip2/bzip2-1.0.6 30 | benchmarks/string_match/string_match_datafiles 31 | benchmarks/word_count/word_count_datafiles 32 | 33 | build/ 34 | 35 | viewer/node_modules 36 | rust/Cargo.lock 37 | rust/target 38 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | # Build on Ubuntu 18.04 2 | dist: bionic 3 | 4 | # Specify language 5 | language: cpp 6 | 7 | # Build with both clang and gcc 8 | compiler: 9 | - clang 10 | - g++ 11 | 12 | # Build all branches except gh-pages 13 | branches: 14 | except: 15 | - gh-pages 16 | 17 | # Install dependencies 18 | before_install: 19 | - sudo apt-get update 20 | - sudo apt-get install -y --install-recommends build-essential cmake ninja-build docutils-common nodejs npm 21 | - sudo pip install conan 22 | 23 | # Make and install 24 | install: 25 | - mkdir build && cd build 26 | - conan install .. -s compiler.libcxx=libstdc++11 -s compiler.cppstd=11 --build=outdated 27 | - cmake .. -DCMAKE_BUILD_TYPE=RelWithDebInfo -DBUILD_BENCHMARKS=ON -G Ninja 28 | - ninja 29 | - sudo ninja install 30 | 31 | # Run tests 32 | script: 33 | - CTEST_OUTPUT_ON_FAILURE=1 ninja test 34 | 35 | # Test the Rust support as well 36 | matrix: 37 | include: 38 | - language: rust 39 | rust: stable 40 | before_install: true 41 | install: true 42 | script: cargo test --manifest-path rust/Cargo.toml 43 | 44 | -------------------------------------------------------------------------------- /CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.13.0) 2 | project(coz VERSION 0.2.2 LANGUAGES C CXX) 3 | 4 | enable_testing() 5 | 6 | set(CMAKE_CXX_STANDARD 11) 7 | set(CMAKE_CXX_STANDARD_REQUIRED ON) 8 | set(CONAN_CMAKE_SILENT_OUTPUT ON) 9 | 10 | list(APPEND CMAKE_MODULE_PATH ${PROJECT_BINARY_DIR} ${PROJECT_SOURCE_DIR}/cmake) 11 | 12 | find_package(Threads REQUIRED) 13 | find_package(libelfin REQUIRED) 14 | 15 | add_compile_options(-gdwarf-3) 16 | 17 | option(INSTALL_COZ "Enable installation of coz. (Projects embedding coz may want to turn this OFF.)" ON) 18 | 19 | if(INSTALL_COZ) 20 | include(GNUInstallDirs) 21 | include(CMakePackageConfigHelpers) 22 | install(PROGRAMS coz DESTINATION bin) 23 | install(FILES LICENSE.md DESTINATION licenses) 24 | configure_package_config_file( 25 | cmake/coz-profilerConfig.cmake.in 26 | ${CMAKE_CURRENT_BINARY_DIR}/coz-profilerConfig.cmake 27 | INSTALL_DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake) 28 | write_basic_package_version_file( 29 | ${CMAKE_CURRENT_BINARY_DIR}/coz-profilerConfigVersion.cmake 30 | COMPATIBILITY ExactVersion) # SameMajor only applies to versions >= 1.0. Versions 0.x have to match exactly according to semver.org 31 | install( 32 | FILES 33 | ${CMAKE_CURRENT_BINARY_DIR}/coz-profilerConfig.cmake 34 | ${CMAKE_CURRENT_BINARY_DIR}/coz-profilerConfigVersion.cmake 35 | DESTINATION 36 | ${CMAKE_INSTALL_LIBDIR}/cmake) 37 | install( 38 | EXPORT coz-profilerTargets 39 | DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake 40 | NAMESPACE coz::) 41 | endif() 42 | 43 | add_subdirectory(libcoz) 44 | 45 | option(BUILD_BENCHMARKS "Build benchmarks" OFF) 46 | if(BUILD_BENCHMARKS) 47 | if(NOT (CMAKE_BUILD_TYPE STREQUAL "Debug" OR CMAKE_BUILD_TYPE STREQUAL "RelWithDebInfo")) 48 | message(FATAL_ERROR "Build benchmarks with debug information - use Debug or RelWithDebInfo") 49 | endif() 50 | find_package(SQLite3 REQUIRED) 51 | find_package(BZip2 REQUIRED) 52 | add_subdirectory(benchmarks) 53 | endif() 54 | 55 | -------------------------------------------------------------------------------- /LICENSE.md: -------------------------------------------------------------------------------- 1 | Original work: _Copyright © 2015, Charlie Curtsinger and Emery Berger, University of Massachusetts Amherst_ 2 | Modified work: _Copyright © 2016, Charlie Curtsinger_ 3 | _All rights reserved._ 4 | 5 | Redistribution and use in source and binary forms, with or without 6 | modification, are permitted provided that the following conditions are met: 7 | 8 | 1. Redistributions of source code must retain the above copyright notice, this 9 | list of conditions and the following disclaimer. 10 | 2. Redistributions in binary form must reproduce the above copyright notice, 11 | this list of conditions and the following disclaimer in the documentation 12 | and/or other materials provided with the distribution. 13 | 14 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS “AS IS” AND 15 | ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 16 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 17 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR 18 | ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 19 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 20 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 21 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 22 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 23 | SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 24 | 25 | The views and conclusions contained in the software and documentation are those 26 | of the authors and should not be interpreted as representing official policies, 27 | either expressed or implied, of the FreeBSD Project. -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | ROOT := . 2 | DIRS := libcoz viewer 3 | 4 | include $(ROOT)/common.mk 5 | 6 | update-gh-pages:: all 7 | @echo $(LOG_PREFIX) Pushing profiler viewer to gh-pages branch $(LOG_SUFFIX) 8 | @git push origin `git subtree split --prefix viewer master 2> /dev/null`:gh-pages 9 | 10 | install:: all 11 | @echo $(LOG_PREFIX) Installing coz to prefix $(prefix) $(LOG_SUFFIX) 12 | @sed 's@destdir@"${DESTDIR}${prefix}"@g' coz-profilerConfig.cmake.in > coz-profilerConfig.cmake 13 | @$(INSTALL) -D coz $(DESTDIR)$(bindir)/coz 14 | @$(INSTALL) -D coz-profilerConfig.cmake $(DESTDIR)$(pkglibdir)/coz-profilerConfig.cmake 15 | @$(INSTALL) -D libcoz/libcoz.so $(DESTDIR)$(pkglibdir)/libcoz.so 16 | @$(INSTALL) -D include/coz.h $(DESTDIR)$(incdir)/coz.h 17 | @mkdir -p $(DESTDIR)$(man1dir) 18 | @$(RST2MAN) docs/coz.rst $(DESTDIR)$(man1dir)/coz.1 19 | 20 | bench bench_small bench_large:: 21 | @$(MAKE) -C benchmarks $@ 22 | 23 | check:: 24 | @$(MAKE) -C benchmarks check 25 | -------------------------------------------------------------------------------- /benchmarks/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | add_compile_options(-g -O3 -DNDEBUG -gdwarf-3) 2 | 3 | function(add_coz_run_target name) 4 | set(one_value_args "") 5 | set(multi_value_args COMMAND) 6 | set(options "") 7 | cmake_parse_arguments(COZ_RUN "${options}" "${one_value_args}" "${multi_value_args}" ${ARGN}) 8 | 9 | add_custom_target(${name} 10 | COMMENT "Running coz for ${name}" 11 | COMMAND ${PROJECT_SOURCE_DIR}/coz run --- ${COZ_RUN_COMMAND} 12 | WORKING_DIRECTORY ${PROJECT_BINARY_DIR} 13 | DEPENDS coz) 14 | endfunction() 15 | 16 | file(GLOB cmake_files */CMakeLists.txt) 17 | foreach(filepath ${cmake_files}) 18 | get_filename_component(dir ${filepath} DIRECTORY) 19 | add_subdirectory(${dir}) 20 | endforeach(filepath) 21 | -------------------------------------------------------------------------------- /benchmarks/LICENSE.md: -------------------------------------------------------------------------------- 1 | # Phoenix applications 2 | The `histogram`, `kmeans`, `linear_regression`, `matrix_multiply`, `pca`, `string_match`, and `word_count` directories contain code from [Phoenix](https://github.com/kozyraki/phoenix). The source code in these directories is licensed as follows: 3 | 4 | The Phoenix source code is distributed with a BSD license. The copyright is held by Stanford University. Phoenix is provided "as is" without any guarantees of any kind. 5 | 6 | # `pbzip2` 7 | The contents of the `pbzip2` directory are derived from [pbzip2](http://compression.ca/pbzip2/). This code is licensed as follows: 8 | 9 | This program, "pbzip2" is copyright (C) 2003-2011 Jeff Gilchrist. 10 | All rights reserved. 11 | 12 | The library "libbzip2" which pbzip2 uses, is copyright 13 | (C) 1996-2008 Julian R Seward. All rights reserved. 14 | 15 | Redistribution and use in source and binary forms, with or without 16 | modification, are permitted provided that the following conditions 17 | are met: 18 | 19 | 1. Redistributions of source code must retain the above copyright 20 | notice, this list of conditions and the following disclaimer. 21 | 22 | 2. The origin of this software must not be misrepresented; you must 23 | not claim that you wrote the original software. If you use this 24 | software in a product, an acknowledgment in the product 25 | documentation would be appreciated but is not required. 26 | 27 | 3. Altered source versions must be plainly marked as such, and must 28 | not be misrepresented as being the original software. 29 | 30 | 4. The name of the author may not be used to endorse or promote 31 | products derived from this software without specific prior written 32 | permission. 33 | 34 | THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS 35 | OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 36 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 37 | ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY 38 | DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 39 | DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE 40 | GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 41 | INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 42 | WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 43 | NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 44 | SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 45 | 46 | Jeff Gilchrist, Ottawa, Canada. 47 | pbzip2@compression.ca 48 | pbzip2 version 1.1.13 of Dec 18, 2015 49 | -------------------------------------------------------------------------------- /benchmarks/check-output.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | set -e 4 | rm -f profile.coz 5 | 6 | $@ 7 | 8 | grep -q "time=" profile.coz || { echo failure: valid profile.coz not generated; exit 1; } 9 | grep -q "throughput-point" profile.coz || { echo failure: throughput-point not found in profile; exit 1; } 10 | grep -q -P "samples\tlocation=" profile.coz || { echo failure: samples not found in profile; exit 1; } 11 | echo success: benchmark generated valid profile.coz 12 | -------------------------------------------------------------------------------- /benchmarks/histogram/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | add_executable(histogram histogram-pthread.c) 2 | target_link_libraries(histogram PRIVATE pthread) 3 | 4 | add_custom_command( 5 | COMMENT "Downloading histogram inputs" 6 | OUTPUT 7 | histogram_datafiles/small.bmp 8 | histogram_datafiles/large.bmp 9 | COMMAND wget -cq http://csl.stanford.edu/~christos/data/histogram.tar.gz 10 | COMMAND tar xzf histogram.tar.gz) 11 | 12 | add_custom_target(histogram_datafiles 13 | DEPENDS 14 | histogram_datafiles/small.bmp 15 | histogram_datafiles/large.bmp) 16 | 17 | add_coz_run_target(run_histogram_large 18 | COMMAND $ ${CMAKE_CURRENT_BINARY_DIR}/histogram_datafiles/large.bmp) 19 | add_dependencies(run_histogram_large histogram_datafiles) 20 | 21 | add_coz_run_target(run_histogram_small 22 | COMMAND $ ${CMAKE_CURRENT_BINARY_DIR}/histogram_datafiles/small.bmp) 23 | add_dependencies(run_histogram_small histogram_datafiles) 24 | -------------------------------------------------------------------------------- /benchmarks/histogram/stddefines.h: -------------------------------------------------------------------------------- 1 | /* Copyright (c) 2007-2009, Stanford University 2 | * All rights reserved. 3 | * 4 | * Redistribution and use in source and binary forms, with or without 5 | * modification, are permitted provided that the following conditions are met: 6 | * * Redistributions of source code must retain the above copyright 7 | * notice, this list of conditions and the following disclaimer. 8 | * * Redistributions in binary form must reproduce the above copyright 9 | * notice, this list of conditions and the following disclaimer in the 10 | * documentation and/or other materials provided with the distribution. 11 | * * Neither the name of Stanford University nor the 12 | * names of its contributors may be used to endorse or promote products 13 | * derived from this software without specific prior written permission. 14 | * 15 | * THIS SOFTWARE IS PROVIDED BY STANFORD UNIVERSITY ``AS IS'' AND ANY 16 | * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 17 | * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 18 | * DISCLAIMED. IN NO EVENT SHALL STANFORD UNIVERSITY BE LIABLE FOR ANY 19 | * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 20 | * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 21 | * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 22 | * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 23 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 24 | * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 25 | */ 26 | 27 | #ifndef STDDEFINES_H_ 28 | #define STDDEFINES_H_ 29 | 30 | #include 31 | #include 32 | #include 33 | #include 34 | #include 35 | 36 | //#define TIMING 37 | 38 | /* Debug printf */ 39 | #define dprintf(...) fprintf(stdout, __VA_ARGS__) 40 | 41 | /* Wrapper to check for errors */ 42 | #define CHECK_ERROR(a) \ 43 | if (a) \ 44 | { \ 45 | perror("Error at line\n\t" #a "\nSystem Msg"); \ 46 | assert ((a) == 0); \ 47 | } 48 | 49 | static inline void *MALLOC(size_t size) 50 | { 51 | void * temp = malloc(size); 52 | assert(temp); 53 | return temp; 54 | } 55 | 56 | static inline void *CALLOC(size_t num, size_t size) 57 | { 58 | void * temp = calloc(num, size); 59 | assert(temp); 60 | return temp; 61 | } 62 | 63 | static inline void *REALLOC(void *ptr, size_t size) 64 | { 65 | void * temp = realloc(ptr, size); 66 | assert(temp); 67 | return temp; 68 | } 69 | 70 | static inline char *GETENV(char *envstr) 71 | { 72 | char *env = getenv(envstr); 73 | if (!env) return "0"; 74 | else return env; 75 | } 76 | 77 | #define GET_TIME(start, end, duration) \ 78 | duration.tv_sec = (end.tv_sec - start.tv_sec); \ 79 | if (end.tv_nsec >= start.tv_nsec) { \ 80 | duration.tv_nsec = (end.tv_nsec - start.tv_nsec); \ 81 | } \ 82 | else { \ 83 | duration.tv_nsec = (1000000000L - (start.tv_nsec - end.tv_nsec)); \ 84 | duration.tv_sec--; \ 85 | } \ 86 | if (duration.tv_nsec >= 1000000000L) { \ 87 | duration.tv_sec++; \ 88 | duration.tv_nsec -= 1000000000L; \ 89 | } 90 | 91 | static inline unsigned int time_diff ( 92 | struct timeval *end, struct timeval *begin) 93 | { 94 | #ifdef TIMING 95 | uint64_t result; 96 | 97 | result = end->tv_sec - begin->tv_sec; 98 | result *= 1000000; /* usec */ 99 | result += end->tv_usec - begin->tv_usec; 100 | 101 | return result; 102 | #else 103 | return 0; 104 | #endif 105 | } 106 | 107 | static inline void get_time (struct timeval *t) 108 | { 109 | #ifdef TIMING 110 | gettimeofday (t, NULL); 111 | #endif 112 | } 113 | 114 | #endif // STDDEFINES_H_ 115 | -------------------------------------------------------------------------------- /benchmarks/kmeans/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | add_executable(kmeans kmeans-pthread.c) 2 | target_link_libraries(kmeans PRIVATE pthread) 3 | 4 | add_coz_run_target(run_kmeans_small COMMAND $ -d 3 -c 100 -p 10000 -s 100) 5 | add_coz_run_target(run_kmeans_large COMMAND $ -d 3 -c 100 -p 100000 -s 1000) 6 | 7 | add_test( 8 | NAME test_run_kmeans 9 | COMMAND ${PROJECT_SOURCE_DIR}/benchmarks/check-output.sh ${PROJECT_SOURCE_DIR}/coz run --- $ 10 | WORKING_DIRECTORY ${PROJECT_BINARY_DIR}) 11 | -------------------------------------------------------------------------------- /benchmarks/kmeans/stddefines.h: -------------------------------------------------------------------------------- 1 | /* Copyright (c) 2007-2009, Stanford University 2 | * All rights reserved. 3 | * 4 | * Redistribution and use in source and binary forms, with or without 5 | * modification, are permitted provided that the following conditions are met: 6 | * * Redistributions of source code must retain the above copyright 7 | * notice, this list of conditions and the following disclaimer. 8 | * * Redistributions in binary form must reproduce the above copyright 9 | * notice, this list of conditions and the following disclaimer in the 10 | * documentation and/or other materials provided with the distribution. 11 | * * Neither the name of Stanford University nor the 12 | * names of its contributors may be used to endorse or promote products 13 | * derived from this software without specific prior written permission. 14 | * 15 | * THIS SOFTWARE IS PROVIDED BY STANFORD UNIVERSITY ``AS IS'' AND ANY 16 | * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 17 | * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 18 | * DISCLAIMED. IN NO EVENT SHALL STANFORD UNIVERSITY BE LIABLE FOR ANY 19 | * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 20 | * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 21 | * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 22 | * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 23 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 24 | * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 25 | */ 26 | 27 | #ifndef STDDEFINES_H_ 28 | #define STDDEFINES_H_ 29 | 30 | #include 31 | #include 32 | #include 33 | #include 34 | #include 35 | 36 | //#define TIMING 37 | 38 | /* Debug printf */ 39 | #define dprintf(...) fprintf(stdout, __VA_ARGS__) 40 | 41 | /* Wrapper to check for errors */ 42 | #define CHECK_ERROR(a) \ 43 | if (a) \ 44 | { \ 45 | perror("Error at line\n\t" #a "\nSystem Msg"); \ 46 | assert ((a) == 0); \ 47 | } 48 | 49 | static inline void *MALLOC(size_t size) 50 | { 51 | void * temp = malloc(size); 52 | assert(temp); 53 | return temp; 54 | } 55 | 56 | static inline void *CALLOC(size_t num, size_t size) 57 | { 58 | void * temp = calloc(num, size); 59 | assert(temp); 60 | return temp; 61 | } 62 | 63 | static inline void *REALLOC(void *ptr, size_t size) 64 | { 65 | void * temp = realloc(ptr, size); 66 | assert(temp); 67 | return temp; 68 | } 69 | 70 | static inline char *GETENV(char *envstr) 71 | { 72 | char *env = getenv(envstr); 73 | if (!env) return "0"; 74 | else return env; 75 | } 76 | 77 | #define GET_TIME(start, end, duration) \ 78 | duration.tv_sec = (end.tv_sec - start.tv_sec); \ 79 | if (end.tv_nsec >= start.tv_nsec) { \ 80 | duration.tv_nsec = (end.tv_nsec - start.tv_nsec); \ 81 | } \ 82 | else { \ 83 | duration.tv_nsec = (1000000000L - (start.tv_nsec - end.tv_nsec)); \ 84 | duration.tv_sec--; \ 85 | } \ 86 | if (duration.tv_nsec >= 1000000000L) { \ 87 | duration.tv_sec++; \ 88 | duration.tv_nsec -= 1000000000L; \ 89 | } 90 | 91 | static inline unsigned int time_diff ( 92 | struct timeval *end, struct timeval *begin) 93 | { 94 | #ifdef TIMING 95 | uint64_t result; 96 | 97 | result = end->tv_sec - begin->tv_sec; 98 | result *= 1000000; /* usec */ 99 | result += end->tv_usec - begin->tv_usec; 100 | 101 | return result; 102 | #else 103 | return 0; 104 | #endif 105 | } 106 | 107 | static inline void get_time (struct timeval *t) 108 | { 109 | #ifdef TIMING 110 | gettimeofday (t, NULL); 111 | #endif 112 | } 113 | 114 | #endif // STDDEFINES_H_ 115 | -------------------------------------------------------------------------------- /benchmarks/linear_regression/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | add_executable(linear_regression linear_regression-pthread.c) 2 | target_link_libraries(linear_regression PRIVATE pthread) 3 | 4 | add_custom_command( 5 | COMMENT "Downloading linear_regression inputs" 6 | OUTPUT 7 | linear_regression_datafiles/key_file_500MB.txt 8 | linear_regression_datafiles/key_file_50MB.txt 9 | COMMAND wget -cq http://csl.stanford.edu/~christos/data/linear_regression.tar.gz 10 | COMMAND tar xzf linear_regression.tar.gz) 11 | 12 | add_custom_target(linear_regression_datafiles 13 | DEPENDS 14 | linear_regression_datafiles/key_file_500MB.txt 15 | linear_regression_datafiles/key_file_50MB.txt) 16 | 17 | add_coz_run_target(run_linear_regression_large 18 | COMMAND $ ${CMAKE_CURRENT_BINARY_DIR}/linear_regression_datafiles/key_file_500MB.txt) 19 | add_dependencies(run_linear_regression_large linear_regression_datafiles) 20 | 21 | add_coz_run_target(run_linear_regression_small 22 | COMMAND $ ${CMAKE_CURRENT_BINARY_DIR}/linear_regression_datafiles/key_file_50MB.txt) 23 | add_dependencies(run_linear_regression_small linear_regression_datafiles) 24 | -------------------------------------------------------------------------------- /benchmarks/linear_regression/linear_regression-pthread.c: -------------------------------------------------------------------------------- 1 | /* Copyright (c) 2007-2009, Stanford University 2 | * All rights reserved. 3 | * 4 | * Redistribution and use in source and binary forms, with or without 5 | * modification, are permitted provided that the following conditions are met: 6 | * * Redistributions of source code must retain the above copyright 7 | * notice, this list of conditions and the following disclaimer. 8 | * * Redistributions in binary form must reproduce the above copyright 9 | * notice, this list of conditions and the following disclaimer in the 10 | * documentation and/or other materials provided with the distribution. 11 | * * Neither the name of Stanford University nor the names of its 12 | * contributors may be used to endorse or promote products derived from 13 | * this software without specific prior written permission. 14 | * 15 | * THIS SOFTWARE IS PROVIDED BY STANFORD UNIVERSITY ``AS IS'' AND ANY 16 | * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 17 | * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 18 | * DISCLAIMED. IN NO EVENT SHALL STANFORD UNIVERSITY BE LIABLE FOR ANY 19 | * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 20 | * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 21 | * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 22 | * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 23 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 24 | * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 25 | */ 26 | 27 | #include 28 | #include 29 | #include 30 | #include 31 | #include 32 | #include 33 | #include 34 | #include 35 | 36 | #include 37 | #include 38 | #include 39 | #include 40 | 41 | #include "stddefines.h" 42 | 43 | #include "coz.h" 44 | 45 | typedef struct { 46 | char x; 47 | char y; 48 | } POINT_T; 49 | 50 | typedef struct 51 | { 52 | pthread_t tid; 53 | POINT_T *points; 54 | int num_elems; 55 | long long SX; 56 | long long SY; 57 | long long SXX; 58 | long long SYY; 59 | long long SXY; 60 | } lreg_args; 61 | 62 | /* linear_regression_pthread 63 | * 64 | */ 65 | void *linear_regression_pthread(void *args_in) 66 | { 67 | lreg_args* args =(lreg_args*)args_in; 68 | int i; 69 | 70 | args->SX = 0; 71 | args->SXX = 0; 72 | args->SY = 0; 73 | args->SYY = 0; 74 | args->SXY = 0; 75 | 76 | // ADD UP RESULTS 77 | for (i = 0; i < args->num_elems; i++) 78 | { 79 | //Compute SX, SY, SYY, SXX, SXY 80 | args->SX += args->points[i].x; 81 | args->SXX += args->points[i].x*args->points[i].x; 82 | args->SY += args->points[i].y; 83 | args->SYY += args->points[i].y*args->points[i].y; 84 | args->SXY += args->points[i].x*args->points[i].y; 85 | 86 | COZ_PROGRESS; 87 | } 88 | 89 | return (void *)0; 90 | } 91 | 92 | 93 | int main(int argc, char *argv[]) 94 | { 95 | int fd; 96 | char * fdata; 97 | char * fname; 98 | struct stat finfo; 99 | 100 | int req_units, num_threads, num_procs, i; 101 | pthread_attr_t attr; 102 | lreg_args* tid_args; 103 | 104 | 105 | // Make sure a filename is specified 106 | if (argv[1] == NULL) 107 | { 108 | printf("USAGE: %s \n", argv[0]); 109 | exit(1); 110 | } 111 | 112 | fname = argv[1]; 113 | 114 | // Read in the file 115 | CHECK_ERROR((fd = open(fname, O_RDONLY)) < 0); 116 | // Get the file info (for file length) 117 | CHECK_ERROR(fstat(fd, &finfo) < 0); 118 | // Memory map the file 119 | CHECK_ERROR((fdata = (char*)mmap(0, finfo.st_size + 1, 120 | PROT_READ | PROT_WRITE, MAP_PRIVATE, fd, 0)) == NULL); 121 | 122 | CHECK_ERROR((num_procs = sysconf(_SC_NPROCESSORS_ONLN)) <= 0); 123 | printf("The number of processors is %d\n\n", num_procs); 124 | 125 | pthread_attr_init(&attr); 126 | pthread_attr_setscope(&attr, PTHREAD_SCOPE_SYSTEM); 127 | 128 | num_threads = num_procs; 129 | 130 | printf("Linear Regression P-Threads: Running...\n"); 131 | 132 | 133 | POINT_T *points = (POINT_T*)fdata; 134 | long long n = (long long) finfo.st_size / sizeof(POINT_T); 135 | 136 | req_units = n / num_threads; 137 | tid_args = (lreg_args *)CALLOC(sizeof(lreg_args), num_procs); 138 | 139 | // Assign a portion of the points for each thread 140 | for(i = 0; i < num_threads; i++) 141 | { 142 | tid_args[i].points = &points[i*req_units]; 143 | tid_args[i].num_elems = req_units; 144 | if(i == (num_threads - 1)) 145 | tid_args[i].num_elems = n - i*req_units; 146 | 147 | CHECK_ERROR(pthread_create(&tid_args[i].tid, &attr, linear_regression_pthread, (void*)&tid_args[i]) != 0); 148 | } 149 | 150 | long long SX_ll = 0, SY_ll = 0, SXX_ll = 0, SYY_ll = 0, SXY_ll = 0; 151 | 152 | /* Barrier, wait for all threads to finish */ 153 | for (i = 0; i < num_threads; i++) 154 | { 155 | int ret_val; 156 | CHECK_ERROR(pthread_join(tid_args[i].tid, (void **)(void*)&ret_val) != 0); 157 | CHECK_ERROR(ret_val != 0); 158 | 159 | SX_ll += tid_args[i].SX; 160 | SY_ll += tid_args[i].SY; 161 | SXX_ll += tid_args[i].SXX; 162 | SYY_ll += tid_args[i].SYY; 163 | SXY_ll += tid_args[i].SXY; 164 | } 165 | 166 | free(tid_args); 167 | 168 | double a, b, xbar, ybar, r2; 169 | double SX = (double)SX_ll; 170 | double SY = (double)SY_ll; 171 | double SXX= (double)SXX_ll; 172 | double SYY= (double)SYY_ll; 173 | double SXY= (double)SXY_ll; 174 | 175 | b = (double)(n*SXY - SX*SY) / (n*SXX - SX*SX); 176 | a = (SY_ll - b*SX_ll) / n; 177 | xbar = (double)SX_ll / n; 178 | ybar = (double)SY_ll / n; 179 | r2 = (double)(n*SXY - SX*SY) * (n*SXY - SX*SY) / ((n*SXX - SX*SX)*(n*SYY - SY*SY)); 180 | 181 | printf("Linear Regression P-Threads Results:\n"); 182 | printf("\ta = %lf\n", a); 183 | printf("\tb = %lf\n", b); 184 | printf("\txbar = %lf\n", xbar); 185 | printf("\tybar = %lf\n", ybar); 186 | printf("\tr2 = %lf\n", r2); 187 | printf("\tSX = %lld\n", SX_ll); 188 | printf("\tSY = %lld\n", SY_ll); 189 | printf("\tSXX = %lld\n", SXX_ll); 190 | printf("\tSYY = %lld\n", SYY_ll); 191 | printf("\tSXY = %lld\n", SXY_ll); 192 | 193 | CHECK_ERROR(pthread_attr_destroy(&attr) < 0); 194 | CHECK_ERROR(munmap(fdata, finfo.st_size + 1) < 0); 195 | CHECK_ERROR(close(fd) < 0); 196 | return 0; 197 | } 198 | -------------------------------------------------------------------------------- /benchmarks/linear_regression/stddefines.h: -------------------------------------------------------------------------------- 1 | /* Copyright (c) 2007-2009, Stanford University 2 | * All rights reserved. 3 | * 4 | * Redistribution and use in source and binary forms, with or without 5 | * modification, are permitted provided that the following conditions are met: 6 | * * Redistributions of source code must retain the above copyright 7 | * notice, this list of conditions and the following disclaimer. 8 | * * Redistributions in binary form must reproduce the above copyright 9 | * notice, this list of conditions and the following disclaimer in the 10 | * documentation and/or other materials provided with the distribution. 11 | * * Neither the name of Stanford University nor the 12 | * names of its contributors may be used to endorse or promote products 13 | * derived from this software without specific prior written permission. 14 | * 15 | * THIS SOFTWARE IS PROVIDED BY STANFORD UNIVERSITY ``AS IS'' AND ANY 16 | * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 17 | * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 18 | * DISCLAIMED. IN NO EVENT SHALL STANFORD UNIVERSITY BE LIABLE FOR ANY 19 | * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 20 | * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 21 | * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 22 | * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 23 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 24 | * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 25 | */ 26 | 27 | #ifndef STDDEFINES_H_ 28 | #define STDDEFINES_H_ 29 | 30 | #include 31 | #include 32 | #include 33 | #include 34 | #include 35 | 36 | //#define TIMING 37 | 38 | /* Debug printf */ 39 | #define dprintf(...) fprintf(stdout, __VA_ARGS__) 40 | 41 | /* Wrapper to check for errors */ 42 | #define CHECK_ERROR(a) \ 43 | if (a) \ 44 | { \ 45 | perror("Error at line\n\t" #a "\nSystem Msg"); \ 46 | assert ((a) == 0); \ 47 | } 48 | 49 | static inline void *MALLOC(size_t size) 50 | { 51 | void * temp = malloc(size); 52 | assert(temp); 53 | return temp; 54 | } 55 | 56 | static inline void *CALLOC(size_t num, size_t size) 57 | { 58 | void * temp = calloc(num, size); 59 | assert(temp); 60 | return temp; 61 | } 62 | 63 | static inline void *REALLOC(void *ptr, size_t size) 64 | { 65 | void * temp = realloc(ptr, size); 66 | assert(temp); 67 | return temp; 68 | } 69 | 70 | static inline char *GETENV(char *envstr) 71 | { 72 | char *env = getenv(envstr); 73 | if (!env) return "0"; 74 | else return env; 75 | } 76 | 77 | #define GET_TIME(start, end, duration) \ 78 | duration.tv_sec = (end.tv_sec - start.tv_sec); \ 79 | if (end.tv_nsec >= start.tv_nsec) { \ 80 | duration.tv_nsec = (end.tv_nsec - start.tv_nsec); \ 81 | } \ 82 | else { \ 83 | duration.tv_nsec = (1000000000L - (start.tv_nsec - end.tv_nsec)); \ 84 | duration.tv_sec--; \ 85 | } \ 86 | if (duration.tv_nsec >= 1000000000L) { \ 87 | duration.tv_sec++; \ 88 | duration.tv_nsec -= 1000000000L; \ 89 | } 90 | 91 | static inline unsigned int time_diff ( 92 | struct timeval *end, struct timeval *begin) 93 | { 94 | #ifdef TIMING 95 | uint64_t result; 96 | 97 | result = end->tv_sec - begin->tv_sec; 98 | result *= 1000000; /* usec */ 99 | result += end->tv_usec - begin->tv_usec; 100 | 101 | return result; 102 | #else 103 | return 0; 104 | #endif 105 | } 106 | 107 | static inline void get_time (struct timeval *t) 108 | { 109 | #ifdef TIMING 110 | gettimeofday (t, NULL); 111 | #endif 112 | } 113 | 114 | #endif // STDDEFINES_H_ 115 | -------------------------------------------------------------------------------- /benchmarks/matrix_multiply/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | add_executable(matrix_multiply matrix_multiply-pthread.c) 2 | target_link_libraries(matrix_multiply PRIVATE pthread) 3 | target_compile_options(matrix_multiply PRIVATE -Wno-format) 4 | 5 | add_custom_command( 6 | COMMENT "Generating bench input" 7 | OUTPUT ${PROJECT_BINARY_DIR}/matrix_file_A_1000.txt ${PROJECT_BINARY_DIR}/matrix_file_B_1000.txt 8 | BYPRODUCTS ${PROJECT_BINARY_DIR}/matrix_file_out_pthreads_1000.txt 9 | COMMAND ${CMAKE_CURRENT_BINARY_DIR}/matrix_multiply 1000 -create_files > /dev/null 10 | WORKING_DIRECTORY ${PROJECT_BINARY_DIR} 11 | DEPENDS matrix_multiply) 12 | add_custom_target(matrix_multiply_large_datafiles 13 | DEPENDS ${PROJECT_BINARY_DIR}/matrix_file_A_1000.txt ${PROJECT_BINARY_DIR}/matrix_file_B_1000.txt) 14 | 15 | add_custom_command( 16 | COMMENT "Generating test input" 17 | OUTPUT ${PROJECT_BINARY_DIR}/matrix_file_A_400.txt ${PROJECT_BINARY_DIR}/matrix_file_B_400.txt 18 | BYPRODUCTS ${PROJECT_BINARY_DIR}/matrix_file_out_pthreads_400.txt 19 | COMMAND ${CMAKE_CURRENT_BINARY_DIR}/matrix_multiply 400 -create_files > /dev/null 20 | WORKING_DIRECTORY ${PROJECT_BINARY_DIR} 21 | DEPENDS matrix_multiply) 22 | add_custom_target(matrix_multiply_small_datafiles 23 | DEPENDS ${PROJECT_BINARY_DIR}/matrix_file_A_400.txt ${PROJECT_BINARY_DIR}/matrix_file_B_400.txt) 24 | 25 | add_coz_run_target(run_matrix_multiply_large 26 | COMMAND $ 1000 > /dev/null) 27 | add_dependencies(run_matrix_multiply_large matrix_multiply_large_datafiles) 28 | 29 | add_coz_run_target(run_matrix_multiply_small 30 | COMMAND $ 400 > /dev/null) 31 | add_dependencies(run_matrix_multiply_small matrix_multiply_small_datafiles) 32 | -------------------------------------------------------------------------------- /benchmarks/matrix_multiply/stddefines.h: -------------------------------------------------------------------------------- 1 | /* Copyright (c) 2007-2009, Stanford University 2 | * All rights reserved. 3 | * 4 | * Redistribution and use in source and binary forms, with or without 5 | * modification, are permitted provided that the following conditions are met: 6 | * * Redistributions of source code must retain the above copyright 7 | * notice, this list of conditions and the following disclaimer. 8 | * * Redistributions in binary form must reproduce the above copyright 9 | * notice, this list of conditions and the following disclaimer in the 10 | * documentation and/or other materials provided with the distribution. 11 | * * Neither the name of Stanford University nor the 12 | * names of its contributors may be used to endorse or promote products 13 | * derived from this software without specific prior written permission. 14 | * 15 | * THIS SOFTWARE IS PROVIDED BY STANFORD UNIVERSITY ``AS IS'' AND ANY 16 | * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 17 | * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 18 | * DISCLAIMED. IN NO EVENT SHALL STANFORD UNIVERSITY BE LIABLE FOR ANY 19 | * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 20 | * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 21 | * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 22 | * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 23 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 24 | * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 25 | */ 26 | 27 | #ifndef STDDEFINES_H_ 28 | #define STDDEFINES_H_ 29 | 30 | #include 31 | #include 32 | #include 33 | #include 34 | #include 35 | 36 | //#define TIMING 37 | 38 | /* Debug printf */ 39 | #define dprintf(...) fprintf(stdout, __VA_ARGS__) 40 | 41 | /* Wrapper to check for errors */ 42 | #define CHECK_ERROR(a) \ 43 | if (a) \ 44 | { \ 45 | perror("Error at line\n\t" #a "\nSystem Msg"); \ 46 | assert ((a) == 0); \ 47 | } 48 | 49 | static inline void *MALLOC(size_t size) 50 | { 51 | void * temp = malloc(size); 52 | assert(temp); 53 | return temp; 54 | } 55 | 56 | static inline void *CALLOC(size_t num, size_t size) 57 | { 58 | void * temp = calloc(num, size); 59 | assert(temp); 60 | return temp; 61 | } 62 | 63 | static inline void *REALLOC(void *ptr, size_t size) 64 | { 65 | void * temp = realloc(ptr, size); 66 | assert(temp); 67 | return temp; 68 | } 69 | 70 | static inline char *GETENV(char *envstr) 71 | { 72 | char *env = getenv(envstr); 73 | if (!env) return "0"; 74 | else return env; 75 | } 76 | 77 | #define GET_TIME(start, end, duration) \ 78 | duration.tv_sec = (end.tv_sec - start.tv_sec); \ 79 | if (end.tv_nsec >= start.tv_nsec) { \ 80 | duration.tv_nsec = (end.tv_nsec - start.tv_nsec); \ 81 | } \ 82 | else { \ 83 | duration.tv_nsec = (1000000000L - (start.tv_nsec - end.tv_nsec)); \ 84 | duration.tv_sec--; \ 85 | } \ 86 | if (duration.tv_nsec >= 1000000000L) { \ 87 | duration.tv_sec++; \ 88 | duration.tv_nsec -= 1000000000L; \ 89 | } 90 | 91 | static inline unsigned int time_diff ( 92 | struct timeval *end, struct timeval *begin) 93 | { 94 | #ifdef TIMING 95 | uint64_t result; 96 | 97 | result = end->tv_sec - begin->tv_sec; 98 | result *= 1000000; /* usec */ 99 | result += end->tv_usec - begin->tv_usec; 100 | 101 | return result; 102 | #else 103 | return 0; 104 | #endif 105 | } 106 | 107 | static inline void get_time (struct timeval *t) 108 | { 109 | #ifdef TIMING 110 | gettimeofday (t, NULL); 111 | #endif 112 | } 113 | 114 | #endif // STDDEFINES_H_ 115 | -------------------------------------------------------------------------------- /benchmarks/pbzip2/AUTHORS: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/plasma-umass/coz/3d711c847ee9c3da9ceb9cc9acc7e43c82d53b18/benchmarks/pbzip2/AUTHORS -------------------------------------------------------------------------------- /benchmarks/pbzip2/BZ2StreamScanner.h: -------------------------------------------------------------------------------- 1 | /* 2 | * File: BZ2StreamScanner.h 3 | * Author: Yavor Nikolov 4 | * 5 | * Created on March 6, 2010, 10:07 PM 6 | */ 7 | 8 | #ifndef _BZ2STREAMSCANNER_H 9 | #define _BZ2STREAMSCANNER_H 10 | 11 | #include "pbzip2.h" 12 | #include 13 | #include 14 | 15 | using namespace std; 16 | 17 | namespace pbzip2 18 | { 19 | 20 | class BZ2StreamScanner 21 | { 22 | public: 23 | typedef unsigned char CharType; 24 | 25 | static const size_t DEFAULT_IN_BUFF_CAPACITY = 1024 * 1024; // 1M 26 | static const size_t DEFAULT_OUT_BUFF_LIMIT = 1024 * 1024; 27 | 28 | enum BZ2SScannerErrorFlag 29 | { 30 | ERR_MEM_ALLOC_INBUFF = 1, 31 | ERR_MEM_ALLOC_OUTBUFF = 1 << 1, 32 | ERR_IO_READ = 1 << 2, 33 | ERR_IO_INSUFFICIENT_BUFF_CAPACITY = 1 << 3, 34 | ERR_INVALID_STATE = 1 << 4, 35 | ERR_INVALID_FILE_FORMAT = 1 << 5 36 | }; 37 | 38 | BZ2StreamScanner( int hInFile, size_t inBuffCapacity = DEFAULT_IN_BUFF_CAPACITY ); 39 | int init( int hInFile, size_t inBuffCapacity = DEFAULT_IN_BUFF_CAPACITY ); 40 | 41 | virtual ~BZ2StreamScanner(); 42 | 43 | outBuff * getNextStream(); 44 | 45 | size_t getInBuffSize() const { return ( _inBuffEnd - _inBuff ); } 46 | size_t getInBuffCapacity() const { return _inBuffCapacity; } 47 | const basic_string & getHeader() const { return _bz2Header; } 48 | size_t getHeaderSize() const { return _bz2Header.size(); } 49 | int getErrState() const { return _errState; } 50 | bool failed() { return ( _errState != 0 ); } 51 | 52 | /** true if header has been found since last initialization */ 53 | bool isBz2HeaderFound() const { return _bz2HeaderFound; } 54 | 55 | /** status of last/current search only */ 56 | bool getSearchStatus() const { return _searchStatus; } 57 | 58 | // end of file 59 | bool eof() const { return _eof; } 60 | 61 | /** true if out buffer is full enough to produce output block */ 62 | bool isOutBuffFullEnough() const { return _outBuff.bufSize >= getOutBuffCapacityLimit(); } 63 | 64 | /** 65 | * dispose memory resources 66 | */ 67 | virtual void dispose(); 68 | 69 | void printCurrentState(); 70 | 71 | private: 72 | /* disable copy c-tor */ 73 | BZ2StreamScanner( const BZ2StreamScanner& orig ) {} 74 | 75 | void initOutBuff( char * buf = NULL, size_t bufSize = 0, size_t bufCapacity = 0 ); 76 | int appendOutBuffData( CharType * end ); 77 | int appendOutBuffData() { return appendOutBuffData( getInBuffSearchPtr() ); } 78 | int appendOutBuffDataUpToLimit(); 79 | int ensureOutBuffCapacity( size_t newSize ); 80 | int readData(); 81 | 82 | CharType * getInBuffEnd() { return _inBuffEnd; } 83 | CharType * getInBuffBegin() { return _inBuff; } 84 | CharType * getInBuffCurrent() { return _inBuffCurrent; } 85 | CharType * getInBuffSearchPtr() { return _inBuffSearchPtr; } 86 | char * getOutBuffEnd() { return _outBuff.buf + _outBuff.bufSize; } 87 | size_t getUnsearchedCount() const { return _inBuffEnd - _inBuffSearchPtr; } 88 | 89 | /** 90 | * Search next bz2 header. Read more data from file if needed. 91 | * 92 | * @return pointer to header is returned if found; 93 | * getInBuffEnd() - if not found; NULL - on error. 94 | */ 95 | CharType * searchNextHeader(); 96 | 97 | /** 98 | * Search next bz2 header just in currently available input buffer. 99 | * (Doesn't read more data from file). 100 | * 101 | * @return pointer to header or getInBuffEnd() if such is not found. 102 | */ 103 | CharType * searchNextHeaderInBuff(); 104 | 105 | /** 106 | * Prepare for next read from file into input buffer. 107 | * Consumes remaining input data buffer and moves header tail to beginning. 108 | * 109 | */ 110 | int rewindInBuff(); 111 | 112 | /** 113 | * Locate BZh header prefix in buffer. In case of first search - just check 114 | * the beginning of buffer and signal error if it doesn't match to headers. 115 | * 116 | * @return pointer to BZh header prefix if located. getInBuffEnd() if not. 117 | * failure() and getErrState() will indicate error if such occurred. 118 | */ 119 | CharType * locateHeaderPrefixInBuff(); 120 | 121 | size_t getOutBuffCapacityLimit() const { return _outBuffCapacityLimit; } 122 | 123 | int _hInFile; // input file descriptor 124 | bool _eof; 125 | 126 | basic_string _bz2Header; 127 | basic_string _bz2HeaderZero; 128 | bool _bz2HeaderFound; 129 | bool _searchStatus; 130 | 131 | CharType * _inBuff; 132 | CharType * _inBuffEnd; // end of data read from file 133 | CharType * _inBuffCurrent; 134 | CharType * _inBuffSearchPtr; 135 | 136 | size_t _inBuffCapacity; // allocated memory capacity for in buffer 137 | 138 | outBuff _outBuff; 139 | size_t _outBuffCapacity; 140 | size_t _outBuffCapacityHint; // keep max used capacity 141 | size_t _outBuffCapacityLimit; 142 | 143 | unsigned int _errState; // 0 - ok; otherwise error 144 | int _outSequenceNumber; // output block sequence number in bz2 stream (>0 if segmented) 145 | int _streamNumber; 146 | }; 147 | 148 | } 149 | 150 | #endif /* _BZ2STREAMSCANNER_H */ 151 | 152 | -------------------------------------------------------------------------------- /benchmarks/pbzip2/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | add_executable(pbzip2 BZ2StreamScanner.cpp ErrorContext.cpp pbzip2.cpp) 2 | target_link_libraries(pbzip2 PRIVATE bz2 pthread) 3 | target_compile_options(pbzip2 PRIVATE -Wno-format) 4 | 5 | set(datafiles ${CMAKE_CURRENT_BINARY_DIR}/../linear_regression/linear_regression_datafiles) 6 | 7 | add_coz_run_target(run_pbzip2_large 8 | COMMAND $ -c < ${datafiles}/key_file_500MB.txt > ${CMAKE_CURRENT_BINARY_DIR}/key_file_500MB_compressed.bz2) 9 | add_dependencies(run_pbzip2_large linear_regression_datafiles) 10 | 11 | add_coz_run_target(run_pbzip2_small 12 | COMMAND $ -c < ${datafiles}/key_file_50MB.txt > ${CMAKE_CURRENT_BINARY_DIR}/key_file_50MB_compressed.bz2) 13 | add_dependencies(run_pbzip2_small linear_regression_datafiles) 14 | 15 | -------------------------------------------------------------------------------- /benchmarks/pbzip2/COPYING: -------------------------------------------------------------------------------- 1 | This program, "pbzip2" is copyright (C) 2003-2011 Jeff Gilchrist. 2 | All rights reserved. 3 | 4 | The library "libbzip2" which pbzip2 uses, is copyright 5 | (C) 1996-2008 Julian R Seward. All rights reserved. 6 | 7 | Redistribution and use in source and binary forms, with or without 8 | modification, are permitted provided that the following conditions 9 | are met: 10 | 11 | 1. Redistributions of source code must retain the above copyright 12 | notice, this list of conditions and the following disclaimer. 13 | 14 | 2. The origin of this software must not be misrepresented; you must 15 | not claim that you wrote the original software. If you use this 16 | software in a product, an acknowledgment in the product 17 | documentation would be appreciated but is not required. 18 | 19 | 3. Altered source versions must be plainly marked as such, and must 20 | not be misrepresented as being the original software. 21 | 22 | 4. The name of the author may not be used to endorse or promote 23 | products derived from this software without specific prior written 24 | permission. 25 | 26 | THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS 27 | OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 28 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 29 | ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY 30 | DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 31 | DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE 32 | GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 33 | INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 34 | WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 35 | NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 36 | SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 37 | 38 | Jeff Gilchrist, Ottawa, Canada. 39 | pbzip2@compression.ca 40 | pbzip2 version 1.1.6 of Oct 30, 2011 41 | -------------------------------------------------------------------------------- /benchmarks/pbzip2/ErrorContext.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * File: ErrorContext.cpp 3 | * Author: Yavor Nikolov 4 | * 5 | * Created on 29 October 2011, 18:14 6 | */ 7 | 8 | #include "pbzip2.h" 9 | #include "ErrorContext.h" 10 | 11 | #include 12 | #include 13 | 14 | namespace pbzip2 15 | { 16 | 17 | ErrorContext * ErrorContext::_instance = 0; 18 | pthread_mutex_t ErrorContext::_err_ctx_mutex = PTHREAD_MUTEX_INITIALIZER; 19 | 20 | ErrorContext * ErrorContext::getInstance() 21 | { 22 | pthread_mutex_lock( &_err_ctx_mutex ); 23 | 24 | if ( ErrorContext::_instance == NULL ) 25 | { 26 | _instance = new(std::nothrow) ErrorContext; 27 | 28 | if ( _instance == NULL ) 29 | { 30 | fprintf( stderr, "pbzip2: *ERROR: Can't initialize error context - out of memory!\n" ); 31 | } 32 | } 33 | 34 | pthread_mutex_unlock( &_err_ctx_mutex ); 35 | 36 | return _instance; 37 | } 38 | 39 | void ErrorContext::printErrnoMsg( FILE * out, int err ) 40 | { 41 | if ( err != 0 ) 42 | { 43 | fprintf( out, "pbzip2: *ERROR: system call failed with errno=[%d: %s]!\n", 44 | err, std::strerror( err ) ); 45 | } 46 | } 47 | 48 | void ErrorContext::syncPrintErrnoMsg( FILE * out, int err ) 49 | { 50 | pthread_mutex_lock( &_err_ctx_mutex ); 51 | printErrnoMsg( out, err ); 52 | pthread_mutex_unlock( &_err_ctx_mutex ); 53 | } 54 | 55 | void ErrorContext::printErrorMessages( FILE * out ) 56 | { 57 | pthread_mutex_lock( &_err_ctx_mutex ); 58 | 59 | printErrnoMsg( out, _first_kernel_err_no ); 60 | printErrnoMsg( out, _last_kernel_err_no ); 61 | 62 | pthread_mutex_unlock( &_err_ctx_mutex ); 63 | } 64 | 65 | void ErrorContext::saveError() 66 | { 67 | int newerr = errno; 68 | 69 | pthread_mutex_lock( &_err_ctx_mutex ); 70 | 71 | if ( newerr != 0 ) 72 | { 73 | int & err_ref = ( _first_kernel_err_no == 0 ) 74 | ? _first_kernel_err_no 75 | : _last_kernel_err_no; 76 | 77 | err_ref = newerr; 78 | } 79 | 80 | _last_kernel_err_no = errno; 81 | 82 | pthread_mutex_unlock( &_err_ctx_mutex ); 83 | } 84 | 85 | void ErrorContext::reset() 86 | { 87 | pthread_mutex_lock( &_err_ctx_mutex ); 88 | _first_kernel_err_no = _last_kernel_err_no = 0; 89 | pthread_mutex_unlock( &_err_ctx_mutex ); 90 | } 91 | 92 | } // namespace pbzip2 93 | -------------------------------------------------------------------------------- /benchmarks/pbzip2/ErrorContext.h: -------------------------------------------------------------------------------- 1 | /* 2 | * File: ErrorContext.h 3 | * Author: Yavor Nikolov 4 | * 5 | * Created on 29 October 2011, 18:14 6 | */ 7 | 8 | #ifndef ERRORCONTEXT_H 9 | #define ERRORCONTEXT_H 10 | 11 | #include "pbzip2.h" 12 | 13 | namespace pbzip2 14 | { 15 | 16 | class ErrorContext 17 | { 18 | private: 19 | static ErrorContext * _instance; 20 | static pthread_mutex_t _err_ctx_mutex; 21 | 22 | int _first_kernel_err_no; 23 | int _last_kernel_err_no; 24 | 25 | private: 26 | ErrorContext(): 27 | _first_kernel_err_no( 0 ), 28 | _last_kernel_err_no( 0 ) 29 | { 30 | } 31 | 32 | ErrorContext( ErrorContext const & s ); 33 | void operator=( ErrorContext const & s ); 34 | public: 35 | static ErrorContext * getInstance(); 36 | void printErrorMessages( FILE * out = stderr ); 37 | void saveError(); 38 | void reset(); 39 | 40 | static void printErrnoMsg( FILE * out, int err ); 41 | static void syncPrintErrnoMsg( FILE * out, int err ); 42 | }; 43 | 44 | } // namespace pbzip2 45 | 46 | #endif /* ERRORCONTEXT_H */ 47 | 48 | -------------------------------------------------------------------------------- /benchmarks/pbzip2/README: -------------------------------------------------------------------------------- 1 | THIS FILE IS IN THE PUBLIC DOMAIN. DISTRIBUTE FREELY. 2 | 3 | 4 | The Complete Moby(tm) Shakespeare: CONTENTS 5 | ------------------------------------------- 6 | (In approximate chronological order of composition within each group.) 7 | 8 | 9 | Histories 10 | --------- 11 | 2 Henry VI 12 | 3 Henry VI 13 | 1 Henry VI 14 | Richard III 15 | Venus and Adonis 16 | The Rape of Lucrece 17 | Richard II 18 | King John 19 | 1 Henry IV 20 | 2 Henry IV 21 | Henry V 22 | Sonnets and 'A Lover's Complaint' 23 | Various Poems 24 | Henry VIII 25 | 26 | Comedies 27 | -------- 28 | The Two Gentlemen of Verona 29 | The Taming of the Shrew 30 | The Comedy of Errors 31 | Love's Labour's Lost 32 | A Midsummer Night's Dream 33 | The Merchant of Venice 34 | The Merry Wives of Windsor 35 | Much Ado About Nothing 36 | As You Like It 37 | Twelfth Night 38 | Troilus and Cressida 39 | Measure for Measure 40 | All's Well That Ends Well 41 | Pericles Prince of Tyre 42 | The Winter's Tale 43 | Cymbeline 44 | The Tempest 45 | 46 | Tragedies 47 | --------- 48 | Titus Andronicus 49 | Romeo and Juliet 50 | Julius Caesar 51 | Hamlet 52 | Othello 53 | Timon of Athens 54 | King Lear 55 | Macbeth 56 | Antony and Cleopatra 57 | Coriolanus 58 | 59 | Glossary 60 | -------- 61 | -------------------------------------------------------------------------------- /benchmarks/pca/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | add_executable(pca pca-pthread.c) 2 | target_link_libraries(pca PRIVATE pthread) 3 | 4 | add_coz_run_target(run_pca COMMAND $ > /dev/null) 5 | -------------------------------------------------------------------------------- /benchmarks/pca/stddefines.h: -------------------------------------------------------------------------------- 1 | /* Copyright (c) 2007-2009, Stanford University 2 | * All rights reserved. 3 | * 4 | * Redistribution and use in source and binary forms, with or without 5 | * modification, are permitted provided that the following conditions are met: 6 | * * Redistributions of source code must retain the above copyright 7 | * notice, this list of conditions and the following disclaimer. 8 | * * Redistributions in binary form must reproduce the above copyright 9 | * notice, this list of conditions and the following disclaimer in the 10 | * documentation and/or other materials provided with the distribution. 11 | * * Neither the name of Stanford University nor the 12 | * names of its contributors may be used to endorse or promote products 13 | * derived from this software without specific prior written permission. 14 | * 15 | * THIS SOFTWARE IS PROVIDED BY STANFORD UNIVERSITY ``AS IS'' AND ANY 16 | * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 17 | * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 18 | * DISCLAIMED. IN NO EVENT SHALL STANFORD UNIVERSITY BE LIABLE FOR ANY 19 | * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 20 | * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 21 | * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 22 | * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 23 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 24 | * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 25 | */ 26 | 27 | #ifndef STDDEFINES_H_ 28 | #define STDDEFINES_H_ 29 | 30 | #include 31 | #include 32 | #include 33 | #include 34 | #include 35 | 36 | //#define TIMING 37 | 38 | /* Debug printf */ 39 | #define dprintf(...) fprintf(stdout, __VA_ARGS__) 40 | 41 | /* Wrapper to check for errors */ 42 | #define CHECK_ERROR(a) \ 43 | if (a) \ 44 | { \ 45 | perror("Error at line\n\t" #a "\nSystem Msg"); \ 46 | assert ((a) == 0); \ 47 | } 48 | 49 | static inline void *MALLOC(size_t size) 50 | { 51 | void * temp = malloc(size); 52 | assert(temp); 53 | return temp; 54 | } 55 | 56 | static inline void *CALLOC(size_t num, size_t size) 57 | { 58 | void * temp = calloc(num, size); 59 | assert(temp); 60 | return temp; 61 | } 62 | 63 | static inline void *REALLOC(void *ptr, size_t size) 64 | { 65 | void * temp = realloc(ptr, size); 66 | assert(temp); 67 | return temp; 68 | } 69 | 70 | static inline char *GETENV(char *envstr) 71 | { 72 | char *env = getenv(envstr); 73 | if (!env) return "0"; 74 | else return env; 75 | } 76 | 77 | #define GET_TIME(start, end, duration) \ 78 | duration.tv_sec = (end.tv_sec - start.tv_sec); \ 79 | if (end.tv_nsec >= start.tv_nsec) { \ 80 | duration.tv_nsec = (end.tv_nsec - start.tv_nsec); \ 81 | } \ 82 | else { \ 83 | duration.tv_nsec = (1000000000L - (start.tv_nsec - end.tv_nsec)); \ 84 | duration.tv_sec--; \ 85 | } \ 86 | if (duration.tv_nsec >= 1000000000L) { \ 87 | duration.tv_sec++; \ 88 | duration.tv_nsec -= 1000000000L; \ 89 | } 90 | 91 | static inline unsigned int time_diff ( 92 | struct timeval *end, struct timeval *begin) 93 | { 94 | #ifdef TIMING 95 | uint64_t result; 96 | 97 | result = end->tv_sec - begin->tv_sec; 98 | result *= 1000000; /* usec */ 99 | result += end->tv_usec - begin->tv_usec; 100 | 101 | return result; 102 | #else 103 | return 0; 104 | #endif 105 | } 106 | 107 | static inline void get_time (struct timeval *t) 108 | { 109 | #ifdef TIMING 110 | gettimeofday (t, NULL); 111 | #endif 112 | } 113 | 114 | #endif // STDDEFINES_H_ 115 | -------------------------------------------------------------------------------- /benchmarks/producer_consumer/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | add_executable(producer_consumer producer_consumer.cpp) 2 | target_link_libraries(producer_consumer PRIVATE pthread) 3 | 4 | add_coz_run_target(run_producer_consumer COMMAND $) 5 | -------------------------------------------------------------------------------- /benchmarks/producer_consumer/producer_consumer.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2015, Charlie Curtsinger and Emery Berger, 3 | * University of Massachusetts Amherst 4 | * This file is part of the Coz project. See LICENSE.md file at the top-level 5 | * directory of this distribution and at http://github.com/plasma-umass/coz. 6 | */ 7 | 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | 14 | #include 15 | 16 | #include 17 | 18 | enum { 19 | Items = 1000000, 20 | QueueSize = 10, 21 | ProducerCount = 5, 22 | ConsumerCount = 3 23 | }; 24 | 25 | int produced = 0; 26 | int consumed = 0; 27 | std::queue queue; 28 | 29 | pthread_mutex_t queue_lock = PTHREAD_MUTEX_INITIALIZER; 30 | pthread_cond_t producer_condvar = PTHREAD_COND_INITIALIZER; 31 | pthread_cond_t consumer_condvar = PTHREAD_COND_INITIALIZER; 32 | pthread_cond_t main_condvar = PTHREAD_COND_INITIALIZER; 33 | 34 | void* producer(void* arg) { 35 | for(size_t n = 0; n < Items / ProducerCount; n++) { 36 | pthread_mutex_lock(&queue_lock); 37 | while(queue.size() == QueueSize) { 38 | pthread_cond_wait(&producer_condvar, &queue_lock); 39 | } 40 | queue.push(123); 41 | produced++; 42 | pthread_mutex_unlock(&queue_lock); 43 | pthread_cond_signal(&consumer_condvar); 44 | } 45 | pthread_mutex_lock(&queue_lock); 46 | pthread_cond_signal(&main_condvar); 47 | pthread_mutex_unlock(&queue_lock); 48 | return NULL; 49 | } 50 | 51 | void* consumer(void* arg) { 52 | while(true) { 53 | pthread_mutex_lock(&queue_lock); 54 | while(queue.size() == 0) { 55 | pthread_cond_wait(&consumer_condvar, &queue_lock); 56 | } 57 | int front = queue.front(); 58 | queue.pop(); 59 | assert(front == 123); 60 | consumed++; 61 | pthread_mutex_unlock(&queue_lock); 62 | pthread_cond_signal(&producer_condvar); 63 | COZ_PROGRESS; 64 | } 65 | } 66 | 67 | int main(int argc, char** argv) { 68 | pthread_t producers[ProducerCount]; 69 | pthread_t consumers[ConsumerCount]; 70 | 71 | for(size_t i=0; i) 6 | -------------------------------------------------------------------------------- /benchmarks/sqlite-modified/main.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | 8 | #include "coz.h" 9 | 10 | #define THREAD_COUNT 64 11 | #define INSERTIONS_PER_THREAD 10000 12 | 13 | void* thread_fn(void* arg) { 14 | int id = (int)(intptr_t)arg; 15 | 16 | int rc; 17 | sqlite3* db; 18 | char* err; 19 | 20 | if(sqlite3_open(":memory:", &db)) { 21 | fprintf(stderr, "Can't open database: %s\n", sqlite3_errmsg(db)); 22 | sqlite3_close(db); 23 | return NULL; 24 | } 25 | 26 | sqlite3_exec(db, "PRAGMA synchronous=OFF", NULL, NULL, &err); 27 | sqlite3_exec(db, "PRAGMA journal_mode=MEMORY", NULL, NULL, &err); 28 | 29 | char buf[512]; 30 | sprintf(buf, "DROP TABLE IF EXISTS tab%d", id); 31 | 32 | do { 33 | rc = sqlite3_exec(db, buf, NULL, NULL, &err); 34 | } while(rc == SQLITE_BUSY); 35 | if(rc) { 36 | printf("Error: %s\n", err); 37 | abort(); 38 | } 39 | 40 | sprintf(buf, "CREATE TABLE tab%d(id INTEGER PRIMARY KEY, x INTEGER, y INTEGER, z TEXT)", id); 41 | do { 42 | rc = sqlite3_exec(db, buf, NULL, NULL, &err); 43 | } while(rc == SQLITE_BUSY); 44 | if(rc) { 45 | printf("Error: %s\n", err); 46 | abort(); 47 | } 48 | 49 | sprintf(buf, "INSERT INTO tab%d VALUES(?1, ?2, ?3, ?4)", id); 50 | sqlite3_stmt* stmt; 51 | sqlite3_prepare_v2(db, buf, strlen(buf), &stmt, NULL); 52 | 53 | for (int i=0; i) 6 | -------------------------------------------------------------------------------- /benchmarks/sqlite/main.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | 8 | #include "coz.h" 9 | 10 | #define THREAD_COUNT 64 11 | #define INSERTIONS_PER_THREAD 10000 12 | 13 | void* thread_fn(void* arg) { 14 | int id = (int)(intptr_t)arg; 15 | 16 | int rc; 17 | sqlite3* db; 18 | char* err; 19 | 20 | if(sqlite3_open(":memory:", &db)) { 21 | fprintf(stderr, "Can't open database: %s\n", sqlite3_errmsg(db)); 22 | sqlite3_close(db); 23 | return NULL; 24 | } 25 | 26 | sqlite3_exec(db, "PRAGMA synchronous=OFF", NULL, NULL, &err); 27 | sqlite3_exec(db, "PRAGMA journal_mode=MEMORY", NULL, NULL, &err); 28 | 29 | char buf[512]; 30 | sprintf(buf, "DROP TABLE IF EXISTS tab%d", id); 31 | 32 | do { 33 | rc = sqlite3_exec(db, buf, NULL, NULL, &err); 34 | } while(rc == SQLITE_BUSY); 35 | if(rc) { 36 | printf("Error: %s\n", err); 37 | abort(); 38 | } 39 | 40 | sprintf(buf, "CREATE TABLE tab%d(id INTEGER PRIMARY KEY, x INTEGER, y INTEGER, z TEXT)", id); 41 | do { 42 | rc = sqlite3_exec(db, buf, NULL, NULL, &err); 43 | } while(rc == SQLITE_BUSY); 44 | if(rc) { 45 | printf("Error: %s\n", err); 46 | abort(); 47 | } 48 | 49 | sprintf(buf, "INSERT INTO tab%d VALUES(?1, ?2, ?3, ?4)", id); 50 | sqlite3_stmt* stmt; 51 | sqlite3_prepare_v2(db, buf, strlen(buf), &stmt, NULL); 52 | 53 | for (int i=0; i ${CMAKE_CURRENT_BINARY_DIR}/string_match_datafiles/key_file_500MB.txt) 19 | add_dependencies(run_string_match_large string_match_datafiles) 20 | 21 | add_coz_run_target(run_string_match_small 22 | COMMAND $ ${CMAKE_CURRENT_BINARY_DIR}/string_match_datafiles/key_file_50MB.txt) 23 | add_dependencies(run_string_match_small string_match_datafiles) 24 | -------------------------------------------------------------------------------- /benchmarks/string_match/stddefines.h: -------------------------------------------------------------------------------- 1 | /* Copyright (c) 2007-2009, Stanford University 2 | * All rights reserved. 3 | * 4 | * Redistribution and use in source and binary forms, with or without 5 | * modification, are permitted provided that the following conditions are met: 6 | * * Redistributions of source code must retain the above copyright 7 | * notice, this list of conditions and the following disclaimer. 8 | * * Redistributions in binary form must reproduce the above copyright 9 | * notice, this list of conditions and the following disclaimer in the 10 | * documentation and/or other materials provided with the distribution. 11 | * * Neither the name of Stanford University nor the 12 | * names of its contributors may be used to endorse or promote products 13 | * derived from this software without specific prior written permission. 14 | * 15 | * THIS SOFTWARE IS PROVIDED BY STANFORD UNIVERSITY ``AS IS'' AND ANY 16 | * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 17 | * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 18 | * DISCLAIMED. IN NO EVENT SHALL STANFORD UNIVERSITY BE LIABLE FOR ANY 19 | * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 20 | * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 21 | * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 22 | * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 23 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 24 | * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 25 | */ 26 | 27 | #ifndef STDDEFINES_H_ 28 | #define STDDEFINES_H_ 29 | 30 | #include 31 | #include 32 | #include 33 | #include 34 | #include 35 | 36 | //#define TIMING 37 | 38 | /* Debug printf */ 39 | #define dprintf(...) fprintf(stdout, __VA_ARGS__) 40 | 41 | /* Wrapper to check for errors */ 42 | #define CHECK_ERROR(a) \ 43 | if (a) \ 44 | { \ 45 | perror("Error at line\n\t" #a "\nSystem Msg"); \ 46 | assert ((a) == 0); \ 47 | } 48 | 49 | static inline void *MALLOC(size_t size) 50 | { 51 | void * temp = malloc(size); 52 | assert(temp); 53 | return temp; 54 | } 55 | 56 | static inline void *CALLOC(size_t num, size_t size) 57 | { 58 | void * temp = calloc(num, size); 59 | assert(temp); 60 | return temp; 61 | } 62 | 63 | static inline void *REALLOC(void *ptr, size_t size) 64 | { 65 | void * temp = realloc(ptr, size); 66 | assert(temp); 67 | return temp; 68 | } 69 | 70 | static inline char *GETENV(char *envstr) 71 | { 72 | char *env = getenv(envstr); 73 | if (!env) return "0"; 74 | else return env; 75 | } 76 | 77 | #define GET_TIME(start, end, duration) \ 78 | duration.tv_sec = (end.tv_sec - start.tv_sec); \ 79 | if (end.tv_nsec >= start.tv_nsec) { \ 80 | duration.tv_nsec = (end.tv_nsec - start.tv_nsec); \ 81 | } \ 82 | else { \ 83 | duration.tv_nsec = (1000000000L - (start.tv_nsec - end.tv_nsec)); \ 84 | duration.tv_sec--; \ 85 | } \ 86 | if (duration.tv_nsec >= 1000000000L) { \ 87 | duration.tv_sec++; \ 88 | duration.tv_nsec -= 1000000000L; \ 89 | } 90 | 91 | static inline unsigned int time_diff ( 92 | struct timeval *end, struct timeval *begin) 93 | { 94 | #ifdef TIMING 95 | uint64_t result; 96 | 97 | result = end->tv_sec - begin->tv_sec; 98 | result *= 1000000; /* usec */ 99 | result += end->tv_usec - begin->tv_usec; 100 | 101 | return result; 102 | #else 103 | return 0; 104 | #endif 105 | } 106 | 107 | static inline void get_time (struct timeval *t) 108 | { 109 | #ifdef TIMING 110 | gettimeofday (t, NULL); 111 | #endif 112 | } 113 | 114 | #endif // STDDEFINES_H_ 115 | -------------------------------------------------------------------------------- /benchmarks/toy-rs/Cargo.lock: -------------------------------------------------------------------------------- 1 | # This file is automatically @generated by Cargo. 2 | # It is not intended for manual editing. 3 | version = 3 4 | 5 | [[package]] 6 | name = "coz" 7 | version = "0.1.3" 8 | source = "registry+https://github.com/rust-lang/crates.io-index" 9 | checksum = "cef55b3fe2f5477d59e12bc792e8b3c95a25bd099eadcfae006ecea136de76e2" 10 | dependencies = [ 11 | "libc", 12 | "once_cell", 13 | ] 14 | 15 | [[package]] 16 | name = "libc" 17 | version = "0.2.131" 18 | source = "registry+https://github.com/rust-lang/crates.io-index" 19 | checksum = "04c3b4822ccebfa39c02fc03d1534441b22ead323fa0f48bb7ddd8e6ba076a40" 20 | 21 | [[package]] 22 | name = "once_cell" 23 | version = "1.13.0" 24 | source = "registry+https://github.com/rust-lang/crates.io-index" 25 | checksum = "18a6dbe30758c9f83eb00cbea4ac95966305f5a7772f3f42ebfc7fc7eddbd8e1" 26 | 27 | [[package]] 28 | name = "toy-rs" 29 | version = "0.1.0" 30 | dependencies = [ 31 | "coz", 32 | ] 33 | -------------------------------------------------------------------------------- /benchmarks/toy-rs/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "toy-rs" 3 | version = "0.1.0" 4 | edition = "2021" 5 | 6 | # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html 7 | 8 | [dependencies] 9 | coz = "0.1" 10 | 11 | [profile.dev] 12 | opt-level = 2 13 | debug = true 14 | -------------------------------------------------------------------------------- /benchmarks/toy-rs/src/main.rs: -------------------------------------------------------------------------------- 1 | #[allow(unused)] 2 | use coz; 3 | use std::thread; 4 | 5 | fn black_box(dummy: T) -> T { 6 | unsafe { 7 | std::ptr::read_volatile(&dummy) 8 | } 9 | } 10 | 11 | #[no_mangle] 12 | pub fn a_first_fn() -> i64 { 13 | let mut v: i64 = 0; 14 | for x in 0..200000000 { 15 | v += x * x; 16 | v -= x * x; 17 | v += x * x; 18 | v -= x * x; 19 | } 20 | return v; 21 | } 22 | 23 | #[no_mangle] 24 | pub fn b_second_fn() -> i64 { 25 | let mut v: i64 = 0; 26 | for x in 0..100000000 { 27 | v += x * x; 28 | v -= x * x; 29 | v += x * x; 30 | v -= x * x; 31 | } 32 | return v; 33 | } 34 | 35 | fn main() { 36 | for _n in 1..100 { 37 | let handle1 = thread::spawn(|| a_first_fn()); 38 | let handle2 = thread::spawn(|| b_second_fn()); 39 | handle1.join().unwrap(); 40 | handle2.join().unwrap(); 41 | coz::progress!(); 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /benchmarks/toy/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | add_executable(toy toy.cpp) 2 | target_link_libraries(toy PRIVATE pthread) 3 | 4 | add_coz_run_target(run_toy COMMAND $) 5 | -------------------------------------------------------------------------------- /benchmarks/toy/toy.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2015, Charlie Curtsinger and Emery Berger, 3 | * University of Massachusetts Amherst 4 | * This file is part of the Coz project. See LICENSE.md file at the top-level 5 | * directory of this distribution and at http://github.com/plasma-umass/coz. 6 | */ 7 | 8 | #include 9 | #include 10 | 11 | volatile size_t x; 12 | char padding[1024]; 13 | volatile size_t y; 14 | 15 | 16 | void a() { 17 | for(x=0; x<2000000; x++) {} 18 | } 19 | 20 | void b() { 21 | for(y=0; y<1900000; y++) {} 22 | } 23 | 24 | int main() { 25 | for (int i = 0; i < 1000; i++) { 26 | std::thread a_thread(a); 27 | std::thread b_thread(b); 28 | 29 | a_thread.join(); 30 | b_thread.join(); 31 | COZ_PROGRESS; 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /benchmarks/word_count/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | add_executable(word_count sort-pthread.c word_count-pthread.c) 2 | target_link_libraries(word_count PRIVATE pthread) 3 | 4 | add_custom_command( 5 | COMMENT "Downloading word_count inputs" 6 | OUTPUT 7 | word_count_datafiles/word_100MB.txt 8 | word_count_datafiles/word_10MB.txt 9 | COMMAND wget -cq http://csl.stanford.edu/~christos/data/word_count.tar.gz 10 | COMMAND tar xzf word_count.tar.gz) 11 | 12 | add_custom_target(word_count_datafiles 13 | DEPENDS 14 | word_count_datafiles/word_100MB.txt 15 | word_count_datafiles/word_10MB.txt) 16 | 17 | add_coz_run_target(run_word_count_large 18 | COMMAND $ ${CMAKE_CURRENT_BINARY_DIR}/word_count_datafiles/word_100MB.txt) 19 | add_dependencies(run_word_count_large word_count_datafiles) 20 | 21 | add_coz_run_target(run_word_count_small 22 | COMMAND $ ${CMAKE_CURRENT_BINARY_DIR}/word_count_datafiles/word_10MB.txt) 23 | add_dependencies(run_word_count_small word_count_datafiles) 24 | -------------------------------------------------------------------------------- /benchmarks/word_count/sort-pthread.c: -------------------------------------------------------------------------------- 1 | /* Copyright (c) 2007-2009, Stanford University 2 | * All rights reserved. 3 | * 4 | * Redistribution and use in source and binary forms, with or without 5 | * modification, are permitted provided that the following conditions are met: 6 | * * Redistributions of source code must retain the above copyright 7 | * notice, this list of conditions and the following disclaimer. 8 | * * Redistributions in binary form must reproduce the above copyright 9 | * notice, this list of conditions and the following disclaimer in the 10 | * documentation and/or other materials provided with the distribution. 11 | * * Neither the name of Stanford University nor the names of its 12 | * contributors may be used to endorse or promote products derived from 13 | * this software without specific prior written permission. 14 | * 15 | * THIS SOFTWARE IS PROVIDED BY STANFORD UNIVERSITY ``AS IS'' AND ANY 16 | * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 17 | * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 18 | * DISCLAIMED. IN NO EVENT SHALL STANFORD UNIVERSITY BE LIABLE FOR ANY 19 | * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 20 | * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 21 | * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 22 | * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 23 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 24 | * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 25 | */ 26 | 27 | #include 28 | #include 29 | #include 30 | #include 31 | #include 32 | #include 33 | #include 34 | #include 35 | 36 | #define CHECK_ERROR(a) \ 37 | if (a) \ 38 | { \ 39 | perror("Error at line\n\t" #a "\nSystem Msg"); \ 40 | exit(1); \ 41 | } 42 | 43 | void *sort_section(void *args_in) ; 44 | 45 | typedef struct { 46 | void* base; 47 | size_t num_elems; 48 | size_t width; 49 | int (*compar)(const void *, const void *); 50 | } sort_args; 51 | 52 | /** sort_section() 53 | * USes qsort to sort the respective portions 54 | */ 55 | void *sort_section(void *args_in) 56 | { 57 | sort_args* args =(sort_args*)args_in; 58 | 59 | qsort(args->base, args->num_elems, args->width, args->compar); 60 | free(args); 61 | return (void *)0; 62 | } 63 | 64 | /** sort_pthreads() 65 | * Function that creates the threads to sort 66 | */ 67 | void sort_pthreads(void *base, size_t num_elems, size_t width, 68 | int (*compar)(const void *, const void *)) 69 | { 70 | int req_units, num_threads, num_procs, i; 71 | pthread_attr_t attr; 72 | pthread_t * tid; 73 | 74 | CHECK_ERROR((num_procs = sysconf(_SC_NPROCESSORS_ONLN)) <= 0); 75 | printf("THe number of processors is %d\n\n", num_procs); 76 | 77 | tid = (pthread_t *)malloc(num_procs * sizeof(pthread_t)); 78 | pthread_attr_init(&attr); 79 | pthread_attr_setscope(&attr, PTHREAD_SCOPE_SYSTEM); 80 | 81 | num_threads = num_procs; 82 | 83 | while(num_threads > 0) 84 | { 85 | req_units = num_elems / num_threads; 86 | 87 | for(i=0; ibase = ((char*)base) + i*req_units*width; 92 | out->num_elems = req_units; 93 | if(i == (num_threads - 1)) 94 | out->num_elems = num_elems - i*req_units; 95 | out->width = width; 96 | out->compar = compar; 97 | 98 | CHECK_ERROR(pthread_create(&tid[i], &attr, sort_section, (void*)out) != 0); 99 | 100 | } 101 | 102 | /* Barrier, wait for all threads to finish */ 103 | for (i = 0; i < num_threads; i++) 104 | { 105 | long ret_val; 106 | CHECK_ERROR(pthread_join(tid[i], (void **)(void*)&ret_val) != 0); 107 | CHECK_ERROR(ret_val != 0); 108 | } 109 | 110 | num_threads = num_threads / 2; 111 | } 112 | 113 | 114 | //qsort(base, num_elems, width, compar); 115 | 116 | free(tid); 117 | } 118 | -------------------------------------------------------------------------------- /benchmarks/word_count/sort-pthread.h: -------------------------------------------------------------------------------- 1 | /* Copyright (c) 2007-2009, Stanford University 2 | * All rights reserved. 3 | * 4 | * Redistribution and use in source and binary forms, with or without 5 | * modification, are permitted provided that the following conditions are met: 6 | * * Redistributions of source code must retain the above copyright 7 | * notice, this list of conditions and the following disclaimer. 8 | * * Redistributions in binary form must reproduce the above copyright 9 | * notice, this list of conditions and the following disclaimer in the 10 | * documentation and/or other materials provided with the distribution. 11 | * * Neither the name of Stanford University nor the names of its 12 | * contributors may be used to endorse or promote products derived from 13 | * this software without specific prior written permission. 14 | * 15 | * THIS SOFTWARE IS PROVIDED BY STANFORD UNIVERSITY ``AS IS'' AND ANY 16 | * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 17 | * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 18 | * DISCLAIMED. IN NO EVENT SHALL STANFORD UNIVERSITY BE LIABLE FOR ANY 19 | * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 20 | * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 21 | * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 22 | * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 23 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 24 | * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 25 | */ 26 | 27 | #ifndef _SORT_PTHREADS_H_ 28 | #define _SORT_PTHREADS_H_ 29 | 30 | void sort_pthreads(void *base, size_t num_elems, size_t width, 31 | int (*compar)(const void *, const void *)); 32 | 33 | #endif // _SORT_PTHREADS_H_ 34 | -------------------------------------------------------------------------------- /benchmarks/word_count/stddefines.h: -------------------------------------------------------------------------------- 1 | /* Copyright (c) 2007-2009, Stanford University 2 | * All rights reserved. 3 | * 4 | * Redistribution and use in source and binary forms, with or without 5 | * modification, are permitted provided that the following conditions are met: 6 | * * Redistributions of source code must retain the above copyright 7 | * notice, this list of conditions and the following disclaimer. 8 | * * Redistributions in binary form must reproduce the above copyright 9 | * notice, this list of conditions and the following disclaimer in the 10 | * documentation and/or other materials provided with the distribution. 11 | * * Neither the name of Stanford University nor the 12 | * names of its contributors may be used to endorse or promote products 13 | * derived from this software without specific prior written permission. 14 | * 15 | * THIS SOFTWARE IS PROVIDED BY STANFORD UNIVERSITY ``AS IS'' AND ANY 16 | * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 17 | * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 18 | * DISCLAIMED. IN NO EVENT SHALL STANFORD UNIVERSITY BE LIABLE FOR ANY 19 | * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 20 | * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 21 | * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 22 | * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 23 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 24 | * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 25 | */ 26 | 27 | #ifndef STDDEFINES_H_ 28 | #define STDDEFINES_H_ 29 | 30 | #include 31 | #include 32 | #include 33 | #include 34 | #include 35 | 36 | //#define TIMING 37 | 38 | /* Debug printf */ 39 | #define dprintf(...) fprintf(stdout, __VA_ARGS__) 40 | 41 | /* Wrapper to check for errors */ 42 | #define CHECK_ERROR(a) \ 43 | if (a) \ 44 | { \ 45 | perror("Error at line\n\t" #a "\nSystem Msg"); \ 46 | assert ((a) == 0); \ 47 | } 48 | 49 | static inline void *MALLOC(size_t size) 50 | { 51 | void * temp = malloc(size); 52 | assert(temp); 53 | return temp; 54 | } 55 | 56 | static inline void *CALLOC(size_t num, size_t size) 57 | { 58 | void * temp = calloc(num, size); 59 | assert(temp); 60 | return temp; 61 | } 62 | 63 | static inline void *REALLOC(void *ptr, size_t size) 64 | { 65 | void * temp = realloc(ptr, size); 66 | assert(temp); 67 | return temp; 68 | } 69 | 70 | static inline char *GETENV(char *envstr) 71 | { 72 | char *env = getenv(envstr); 73 | if (!env) return "0"; 74 | else return env; 75 | } 76 | 77 | #define GET_TIME(start, end, duration) \ 78 | duration.tv_sec = (end.tv_sec - start.tv_sec); \ 79 | if (end.tv_nsec >= start.tv_nsec) { \ 80 | duration.tv_nsec = (end.tv_nsec - start.tv_nsec); \ 81 | } \ 82 | else { \ 83 | duration.tv_nsec = (1000000000L - (start.tv_nsec - end.tv_nsec)); \ 84 | duration.tv_sec--; \ 85 | } \ 86 | if (duration.tv_nsec >= 1000000000L) { \ 87 | duration.tv_sec++; \ 88 | duration.tv_nsec -= 1000000000L; \ 89 | } 90 | 91 | static inline unsigned int time_diff ( 92 | struct timeval *end, struct timeval *begin) 93 | { 94 | #ifdef TIMING 95 | uint64_t result; 96 | 97 | result = end->tv_sec - begin->tv_sec; 98 | result *= 1000000; /* usec */ 99 | result += end->tv_usec - begin->tv_usec; 100 | 101 | return result; 102 | #else 103 | return 0; 104 | #endif 105 | } 106 | 107 | static inline void get_time (struct timeval *t) 108 | { 109 | #ifdef TIMING 110 | gettimeofday (t, NULL); 111 | #endif 112 | } 113 | 114 | #endif // STDDEFINES_H_ 115 | -------------------------------------------------------------------------------- /cmake/Findlibelfin.cmake: -------------------------------------------------------------------------------- 1 | include(FindPkgConfig) 2 | pkg_check_modules(libelfxx REQUIRED libelf++) # >=0.3) 3 | pkg_check_modules(libdwarfxx REQUIRED libdwarf++)#>=0.3) 4 | 5 | add_library(libelfin::libelf++ INTERFACE IMPORTED) 6 | set_target_properties(libelfin::libelf++ PROPERTIES 7 | INTERFACE_INCLUDE_DIRECTORIES "${libelfxx_INCLUDE_DIRS}" 8 | INTERFACE_LINK_LIBRARIES "${libelfxx_LDFLAGS}" 9 | INTERFACE_COMPILE_OPTIONS "${libelfxx_CFLAGS};${libelfxx_CFLAGS_OTHER}") 10 | add_library(libelfin::libdwarf++ INTERFACE IMPORTED) 11 | set_target_properties(libelfin::libdwarf++ PROPERTIES 12 | INTERFACE_INCLUDE_DIRECTORIES "${libdwarfxx_INCLUDE_DIRS}" 13 | INTERFACE_LINK_LIBRARIES "${libdwarfxx_LDFLAGS}" 14 | INTERFACE_COMPILE_OPTIONS "${libdwarfxx_CFLAGS};${libdwarfxx_CFLAGS_OTHER}") 15 | 16 | if(libelfxx_FOUND AND libdwarfxx_FOUND) 17 | set(libelfin_FOUND 1) 18 | set(libelfin_VERSION ${libelfxx_VERSION}) 19 | if(NOT TARGET libelfin::libelfin) 20 | add_library(libelfin::libelfin INTERFACE IMPORTED) 21 | endif() 22 | set_target_properties(libelfin::libelfin PROPERTIES 23 | INTERFACE_LINK_LIBRARIES "libelfin::libdwarf++;libelfin::libelf++") 24 | endif() 25 | 26 | include(FindPackageHandleStandardArgs) 27 | find_package_handle_standard_args(libelfin 28 | REQUIRED_VARS libelfin_VERSION 29 | VERSION_VAR libelfin_VERSION) 30 | -------------------------------------------------------------------------------- /cmake/coz-profilerConfig.cmake.in: -------------------------------------------------------------------------------- 1 | @PACKAGE_INIT@ 2 | 3 | message(INFO " ${COZ_INCLUDE_DIR} ${COZ_LIBRARY} ${COZ_FOUND}") 4 | 5 | # Use find_dependency to find dependend packages. 6 | 7 | include(${CMAKE_CURRENT_LIST_DIR}/coz-profilerTargets.cmake) 8 | 9 | add_executable(coz::profiler IMPORTED) 10 | 11 | # This includes the lib file 12 | get_target_property(_COZ_LIBARRY_PATH coz::coz IMPORTED_LOCATION) 13 | # {INSTALLATION}/lib/libcoz.so 14 | get_filename_component(_IMPORT_PREFIX "${_COZ_LIBRARY_PATH}" PATH) 15 | # {INSTALLATION}/lib 16 | get_filename_component(_IMPORT_PREFIX "${_COZ_LIBARRY_PATH}" PATH) 17 | # {INSTALLATION} 18 | set_property(TARGET coz::profiler PROPERTY IMPORTED_LOCATION ${_COZ_LIBARRY_PATH}) 19 | # Cleanup temporary variables 20 | set(_COZ_LIBARRY_PATH) 21 | 22 | -------------------------------------------------------------------------------- /common.mk: -------------------------------------------------------------------------------- 1 | DESTDIR ?= 2 | prefix ?= /usr 3 | bindir := $(prefix)/bin 4 | pkglibdir := $(prefix)/lib/coz-profiler 5 | incdir := $(prefix)/include 6 | mandir := $(prefix)/share/man 7 | man1dir := $(mandir)/man1 8 | 9 | INSTALL = install 10 | RST2MAN = rst2man 11 | 12 | # Build with clang by default 13 | CC ?= clang 14 | CXX ?= clang++ 15 | 16 | # Set coz and include path for coz 17 | ifeq ($(USE_SYSTEM_COZ),1) 18 | COZ := $(shell which coz) 19 | else 20 | COZ := $(ROOT)/coz 21 | endif 22 | 23 | # Default flags 24 | CFLAGS ?= -g -O2 25 | CXXFLAGS ?= $(CFLAGS) 26 | 27 | # Default source and object files 28 | SRCS ?= $(wildcard *.cpp) $(wildcard *.c) 29 | OBJS ?= $(addprefix obj/,$(patsubst %.cpp,%.o,$(patsubst %.c,%.o,$(SRCS)))) 30 | 31 | # Prevent errors if files named all, clean, distclean, bench, or test exist 32 | .PHONY: all clean distclean bench bench_small bench_large test 33 | 34 | # Targets to build recursively into $(DIRS) 35 | RECURSIVE_TARGETS ?= all clean bench bench_large bench_small test install check 36 | 37 | # Targets separated by type 38 | SHARED_LIB_TARGETS := $(filter %.so, $(TARGETS)) 39 | STATIC_LIB_TARGETS := $(filter %.a, $(TARGETS)) 40 | OTHER_TARGETS := $(filter-out %.so, $(filter-out %.a, $(TARGETS))) 41 | 42 | # If not set, the build path is just the current directory name 43 | MAKEPATH ?= $(shell basename $(shell pwd)) 44 | 45 | # Log the build path in gray, following by a log message in bold green 46 | LOG_PREFIX := "$(shell tput setaf 7)[$(MAKEPATH)]$(shell tput sgr0)$(shell tput setaf 2)" 47 | LOG_SUFFIX := "$(shell tput sgr0)" 48 | 49 | # Build in parallel 50 | MAKEFLAGS += -j 51 | 52 | # Build all targets by default, unless this is a benchmark 53 | all:: $(TARGETS) 54 | 55 | # Clean up after a build 56 | clean:: 57 | @for t in $(TARGETS); do \ 58 | echo $(LOG_PREFIX) Cleaning $$t $(LOG_SUFFIX); \ 59 | done 60 | @rm -rf $(TARGETS) obj 61 | 62 | # Bring source back to pristine state 63 | distclean:: clean 64 | @$(MAKE) -C benchmarks clean 65 | 66 | # Compile a C++ source file (and generate its dependency rules) 67 | obj/%.o: %.cpp $(PREREQS) 68 | @echo $(LOG_PREFIX) Compiling $< $(LOG_SUFFIX) 69 | @mkdir -p obj 70 | @$(CXX) $(CXXFLAGS) -MMD -MP -o $@ -c $< 71 | 72 | # Compile a C source file (and generate its dependency rules) 73 | obj/%.o: %.c $(PREREQS) 74 | @echo $(LOG_PREFIX) Compiling $< $(LOG_SUFFIX) 75 | @mkdir -p obj 76 | @$(CC) $(CFLAGS) -MMD -MP -o $@ -c $< 77 | 78 | # Link a shared library 79 | $(SHARED_LIB_TARGETS): $(OBJS) 80 | @echo $(LOG_PREFIX) Linking $@ $(LOG_SUFFIX) 81 | @$(CXX) -shared $(LDFLAGS) -o $@ $^ $(LIBS) 82 | 83 | $(STATIC_LIB_TARGETS): $(OBJS) 84 | @echo $(LOG_PREFIX) Linking $@ $(LOG_SUFFIX) 85 | @ar rs $@ $^ 86 | 87 | # Link binary targets 88 | $(OTHER_TARGETS): $(OBJS) 89 | @echo $(LOG_PREFIX) Linking $@ $(LOG_SUFFIX) 90 | @$(CXX) $(LDFLAGS) -o $@ $^ $(LIBS) 91 | 92 | # Include dependency rules for all objects 93 | -include $(OBJS:.o=.d) 94 | 95 | # Build any recursive targets in subdirectories 96 | $(RECURSIVE_TARGETS):: 97 | @for dir in $(DIRS); do \ 98 | $(MAKE) -C $$dir --no-print-directory $@ MAKEPATH="$(MAKEPATH)/$$dir" || exit 1; \ 99 | done 100 | -------------------------------------------------------------------------------- /conanfile.txt: -------------------------------------------------------------------------------- 1 | [requires] 2 | libelfin/[>=0.3] 3 | 4 | [build_requires] 5 | bzip2/[>=1.0.8] 6 | sqlite3/[>=3.33.0] 7 | 8 | [generators] 9 | cmake_find_package 10 | -------------------------------------------------------------------------------- /coz: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | # Copyright (c) 2019, Charlie Curtsinger and Emery Berger, 4 | # University of Massachusetts Amherst 5 | # This file is part of the Coz project. See LICENSE.md file at the top-level 6 | # directory of this distribution and at http://github.com/plasma-umass/coz. 7 | 8 | import argparse 9 | import copy 10 | import os 11 | import subprocess 12 | import sys 13 | 14 | from os.path import abspath, realpath, curdir, dirname, sep as path_sep 15 | 16 | # Entry point 17 | def run_command_line(): 18 | # By default, parse all arguments 19 | parsed_args = sys.argv[1:] 20 | remaining_args = [] 21 | # If there is a '---' separator, only parse arguments before the separator 22 | if '---' in sys.argv: 23 | separator_index = sys.argv.index('---') 24 | parsed_args = sys.argv[1:separator_index] 25 | remaining_args = sys.argv[separator_index+1:] 26 | # Pass the un-parsed arguments to the parser result 27 | _parser.set_defaults(remaining_args=remaining_args) 28 | # Parse it 29 | args = _parser.parse_args(parsed_args) 30 | if not hasattr(args, 'func'): 31 | sys.stderr.write('error: pass a command before ---, such as `coz run --- $CMD`\n') 32 | _parser.print_help() 33 | sys.exit(1) 34 | 35 | # Call the parser's handler (set by the subcommand parser using defaults) 36 | args.func(args) 37 | 38 | # Handler for the `coz run` subcommand 39 | def _coz_run(args): 40 | # Ensure the user specified a command after the '---' separator 41 | if len(args.remaining_args) == 0: 42 | sys.stderr.write('error: specify a command to profile after `---`\n') 43 | args.parser.print_help() 44 | sys.exit(1) 45 | 46 | env = copy.deepcopy(os.environ) 47 | 48 | # Find coz 49 | coz_prefix = dirname(realpath(sys.argv[0])) 50 | 51 | # Candidate runtime library locations 52 | library_locations = [ 53 | # Check for library adjacent to this script 54 | os.path.join(coz_prefix, '..', 'lib64', 'libcoz.so'), 55 | os.path.join(coz_prefix, '..', 'lib', 'libcoz.so'), 56 | 57 | # Check for library under the coz-profiler subdirectory 58 | os.path.join(coz_prefix, '..', 'lib64', 'coz-profiler', 'libcoz.so'), 59 | os.path.join(coz_prefix, '..', 'lib', 'coz-profiler', 'libcoz.so'), 60 | 61 | # Local library under development directory 62 | os.path.join('libcoz', 'libcoz.so'), # Local library during development 63 | os.path.join(coz_prefix, 'libcoz', 'libcoz.so'), 64 | os.path.join(coz_prefix, 'build', 'libcoz', 'libcoz.so'), 65 | ] 66 | 67 | # Find the first library location that exists 68 | coz_runtime_found = False 69 | coz_runtime = None 70 | 71 | while len(library_locations) > 0 and not coz_runtime_found: 72 | candidate = library_locations.pop(0) 73 | if os.path.exists(candidate): 74 | coz_runtime_found = True 75 | coz_runtime = candidate 76 | 77 | if not coz_runtime_found: 78 | sys.stderr.write('error: unable to locate coz runtime library\n') 79 | sys.exit(1) 80 | 81 | if 'LD_PRELOAD' in env: 82 | env['LD_PRELOAD'] += ':' + coz_runtime 83 | else: 84 | env['LD_PRELOAD'] = coz_runtime 85 | 86 | if len(args.binary_scope) > 0: 87 | env['COZ_BINARY_SCOPE'] = '\t'.join(args.binary_scope) 88 | else: 89 | env['COZ_BINARY_SCOPE'] = 'MAIN' 90 | 91 | if len(args.source_scope) > 0: 92 | env['COZ_SOURCE_SCOPE'] = '\t'.join(args.source_scope) 93 | else: 94 | env['COZ_SOURCE_SCOPE'] = '%' 95 | 96 | env['COZ_PROGRESS_POINTS'] = '\t'.join(args.progress) 97 | 98 | env['COZ_OUTPUT'] = args.output 99 | 100 | if args.end_to_end: 101 | env['COZ_END_TO_END'] = '1' 102 | 103 | if args.fixed_line: 104 | env['COZ_FIXED_LINE'] = args.fixed_line 105 | 106 | if args.fixed_speedup != None: 107 | env['COZ_FIXED_SPEEDUP'] = str(args.fixed_speedup) 108 | 109 | try: 110 | result = subprocess.call(args.remaining_args, env=env) 111 | except KeyboardInterrupt: 112 | # Exit with special control-C return code 113 | result = 130 114 | # Add a newline to mimic output when running without coz 115 | print() 116 | exit(result) 117 | 118 | def open_browser(url): 119 | import webbrowser 120 | webbrowser.open_new_tab(url) 121 | 122 | def _coz_plot(args): 123 | coz_plot_url = 'http://plasma-umass.github.io/coz' 124 | import threading 125 | t1 = threading.Thread(target=open_browser,args=(coz_plot_url,)) 126 | t1.start() 127 | #if sys.platform == 'darwin': 128 | # subprocess.call(['open', coz_plot_url]) 129 | #elif sys.platform == 'win32': 130 | # os.startfile(coz_plot_url) 131 | #else: 132 | # subprocess.call(['xdg-open', coz_plot_url]) 133 | 134 | 135 | # Special format handler for line reference arguments 136 | def line_ref(val): 137 | try: 138 | (filename, line) = val.rsplit(':', 1) 139 | line = int(line) 140 | return filename + ':' + str(line) 141 | except: 142 | msg = "Invalid line reference %r. The format is :." % val 143 | raise argparse.ArgumentTypeError(msg) 144 | 145 | ######### Build the top-level parser ######### 146 | _parser = argparse.ArgumentParser() 147 | _subparsers = _parser.add_subparsers() 148 | 149 | ######### Build the parser for the `run` sub-command ######### 150 | _run_parser = _subparsers.add_parser('run', 151 | usage='%(prog)s [profiling options] --- [args]', 152 | help='Run a program with coz to collect a causal profile.') 153 | 154 | # Add common profiler options 155 | _run_parser.add_argument('--binary-scope', '-b', 156 | metavar='', 157 | default=[], action='append', 158 | help='Profile matching executables. Use \'%%\' as a wildcard, or \'MAIN\' to include the main executable (default=MAIN)') 159 | 160 | _run_parser.add_argument('--source-scope', '-s', 161 | metavar='', 162 | default=[], action='append', 163 | help='Profile matching source files. Use \'%%\' as a wildcard. (default=%%)') 164 | 165 | _run_parser.add_argument('--progress', '-p', 166 | metavar=':', 167 | type=line_ref, action='append', default=[], 168 | help='[NOT SUPPORTED] Add a sampling-based progress point') 169 | 170 | _run_parser.add_argument('--output', '-o', 171 | metavar='', 172 | default=abspath(curdir+path_sep+'profile.coz'), 173 | help='Profiler output (default=`profile.coz`)') 174 | 175 | _run_parser.add_argument('--end-to-end', 176 | action='store_true', default=False, 177 | help='Run a single performance experiment per-execution') 178 | 179 | _run_parser.add_argument('--fixed-line', 180 | metavar=':', default=None, 181 | help='Evaluate optimizations of a specific source line') 182 | 183 | _run_parser.add_argument('--fixed-speedup', 184 | metavar=' (0-100)', 185 | type=int, choices=list(range(0, 101)), default=None, 186 | help='Evaluate optimizations of a specific amount') 187 | 188 | # Use defaults to recover handler function and parser object from parser output 189 | _run_parser.set_defaults(func=_coz_run, parser=_run_parser) 190 | 191 | ######### Build the parser for the `coz plot` subcommand 192 | _plot_parser = _subparsers.add_parser('plot', 193 | help='Plot the speedup results from one or more causal profiling runs.') 194 | 195 | # Use defaults to recover handler function and parser object from parser output 196 | _plot_parser.set_defaults(func=_coz_plot, parser=_plot_parser) 197 | 198 | if __name__ == "__main__": 199 | run_command_line() 200 | -------------------------------------------------------------------------------- /coz-profilerConfig.cmake.in: -------------------------------------------------------------------------------- 1 | 2 | 3 | set(COZDIR destdir) 4 | 5 | set(COZ_BIN ${COZDIR}/bin/coz) 6 | set(COZ_INCLUDE_DIR ${COZDIR}/include) 7 | get_filename_component(LIBRARY_DIR ${CMAKE_CURRENT_LIST_FILE} DIRECTORY) 8 | set(COZ_LIBRARY ${LIBRARY_DIR}/libcoz.so) 9 | 10 | set(COZ_FOUND ON) 11 | 12 | message(INFO " ${COZ_INCLUDE_DIR} ${COZ_LIBRARY} ${COZ_FOUND}") 13 | 14 | mark_as_advanced(COZ_FOUND COZ_INCLUDE_DIR COZ_LIBRARY) 15 | 16 | add_library(coz::coz UNKNOWN IMPORTED) 17 | set_target_properties(coz::coz PROPERTIES 18 | INTERFACE_INCLUDE_DIRECTORIES "${COZ_INCLUDE_DIR}") 19 | 20 | set_target_properties(coz::coz PROPERTIES 21 | IMPORTED_LINK_INTERFACE_LANGUAGES "C" 22 | IMPORTED_LOCATION "${COZ_INCLUDE_DIR}") 23 | 24 | add_executable(coz::profiler IMPORTED) 25 | 26 | set_property(TARGET coz::profiler PROPERTY IMPORTED_LOCATION ${COZ_BIN}) 27 | -------------------------------------------------------------------------------- /docs/README.md: -------------------------------------------------------------------------------- 1 | The file `coz.1` was automatically generated by using `rst2man`: 2 | 3 | ``` 4 | rst2man coz.rst coz.1 5 | ``` 6 | 7 | To install `rst2man` on Linux systems, execute the following command: 8 | 9 | ``` 10 | sudo apt-get install python-docutils 11 | ``` 12 | -------------------------------------------------------------------------------- /docs/coz.1: -------------------------------------------------------------------------------- 1 | .\" Man page generated from reStructuredText. 2 | . 3 | .TH COZ 1 "2017-08-06" "0.2" "User Commands" 4 | .SH NAME 5 | coz \- profiler running experiments on multithreaded code 6 | . 7 | .nr rst2man-indent-level 0 8 | . 9 | .de1 rstReportMargin 10 | \\$1 \\n[an-margin] 11 | level \\n[rst2man-indent-level] 12 | level margin: \\n[rst2man-indent\\n[rst2man-indent-level]] 13 | - 14 | \\n[rst2man-indent0] 15 | \\n[rst2man-indent1] 16 | \\n[rst2man-indent2] 17 | .. 18 | .de1 INDENT 19 | .\" .rstReportMargin pre: 20 | . RS \\$1 21 | . nr rst2man-indent\\n[rst2man-indent-level] \\n[an-margin] 22 | . nr rst2man-indent-level +1 23 | .\" .rstReportMargin post: 24 | .. 25 | .de UNINDENT 26 | . RE 27 | .\" indent \\n[an-margin] 28 | .\" old: \\n[rst2man-indent\\n[rst2man-indent-level]] 29 | .nr rst2man-indent-level -1 30 | .\" new: \\n[rst2man-indent\\n[rst2man-indent-level]] 31 | .in \\n[rst2man-indent\\n[rst2man-indent-level]]u 32 | .. 33 | .SH SYNOPSIS 34 | .sp 35 | coz run [profiling options] \-\-\- [args] 36 | .sp 37 | coz plot [\-h] 38 | .SH DESCRIPTION 39 | .sp 40 | Coz is a new kind of profiler that unlocks optimization opportunities 41 | missed by traditional profilers. Coz employs a novel technique we call 42 | \fIcausal profiling\fP that measures optimization potential. This 43 | measurement matches developers\(aq assumptions about profilers: that 44 | optimizing highly\-ranked code will have the greatest impact on 45 | performance. Causal profiling measures optimization potential for 46 | serial, parallel, and asynchronous programs without instrumentation of 47 | special handling for library calls and concurrency 48 | primitives. Instead, a causal profiler uses performance experiments to 49 | predict the effect of optimizations. This allows the profiler to 50 | establish causality: "optimizing function X will have effect Y," 51 | exactly the measurement developers had assumed they were getting all 52 | along. 53 | .SH OPTIONS 54 | .INDENT 0.0 55 | .TP 56 | .B \-h\fP,\fB \-\-help 57 | show this help message and exit 58 | .TP 59 | .BI \-\-binary\-scope \ \fR,\fB \ \-b \ 60 | Profile matching executables. Use \(aq%\(aq as a wildcard, or \(aqMAIN\(aq to 61 | include the main executable (default=MAIN) 62 | .TP 63 | .BI \-\-source\-scope \ \fR,\fB \ \-s \ 64 | Profile matching source files. Use \(aq%\(aq as a wildcard. (default=%) 65 | .UNINDENT 66 | .INDENT 0.0 67 | .TP 68 | .B \-\-progress :, \-p : 69 | [NOT SUPPORTED] Add a sampling\-based progress point 70 | .UNINDENT 71 | .INDENT 0.0 72 | .TP 73 | .BI \-\-output \ \fR,\fB \ \-o \ 74 | Profiler output (default=\(gaprofile.coz\(ga) 75 | .TP 76 | .B \-\-end\-to\-end 77 | Run a single performance experiment per\-execution 78 | .UNINDENT 79 | .INDENT 0.0 80 | .TP 81 | .B \-\-fixed\-line : 82 | Evaluate optimizations of a specific source line 83 | .TP 84 | .B \-\-fixed\-speedup (0\-100) 85 | Evaluate optimizations of a specific amount 86 | .UNINDENT 87 | .SH SEE ALSO 88 | .INDENT 0.0 89 | .IP \(bu 2 90 | \fI\%http://coz\-profiler.org\fP 91 | .IP \(bu 2 92 | \fBman gdb\fP 93 | .UNINDENT 94 | .SH AUTHOR 95 | Emery Berger - emery@cs.umass.edu, Charlie Curtsinger - curtsinger@grinnell.edu 96 | .SH COPYRIGHT 97 | public domain 98 | .\" Generated by docutils manpage writer. 99 | . 100 | -------------------------------------------------------------------------------- /docs/coz.rst: -------------------------------------------------------------------------------- 1 | ===== 2 | coz 3 | ===== 4 | 5 | -------------------------------------------------- 6 | profiler running experiments on multithreaded code 7 | -------------------------------------------------- 8 | 9 | :Author: Emery Berger - emery@cs.umass.edu 10 | :Author: Charlie Curtsinger - curtsinger@grinnell.edu 11 | :Date: 2017-08-06 12 | :Copyright: public domain 13 | :Version: 0.2 14 | :Manual section: 1 15 | :Manual group: User Commands 16 | 17 | SYNOPSIS 18 | ======== 19 | 20 | coz run [profiling options] --- [args] 21 | 22 | coz plot [-h] 23 | 24 | DESCRIPTION 25 | =========== 26 | 27 | Coz is a new kind of profiler that unlocks optimization opportunities 28 | missed by traditional profilers. Coz employs a novel technique we call 29 | *causal profiling* that measures optimization potential. This 30 | measurement matches developers' assumptions about profilers: that 31 | optimizing highly-ranked code will have the greatest impact on 32 | performance. Causal profiling measures optimization potential for 33 | serial, parallel, and asynchronous programs without instrumentation of 34 | special handling for library calls and concurrency 35 | primitives. Instead, a causal profiler uses performance experiments to 36 | predict the effect of optimizations. This allows the profiler to 37 | establish causality: "optimizing function X will have effect Y," 38 | exactly the measurement developers had assumed they were getting all 39 | along. 40 | 41 | OPTIONS 42 | ======= 43 | -h, --help 44 | show this help message and exit 45 | 46 | --binary-scope , -b 47 | Profile matching executables. Use '%' as a wildcard, or 'MAIN' to 48 | include the main executable (default=MAIN) 49 | 50 | --source-scope , -s 51 | Profile matching source files. Use '%' as a wildcard. (default=%) 52 | 53 | --progress :, -p : 54 | [NOT SUPPORTED] Add a sampling-based progress point 55 | 56 | --output , -o 57 | Profiler output (default=`profile.coz`) 58 | 59 | --end-to-end 60 | Run a single performance experiment per-execution 61 | 62 | --fixed-line : 63 | Evaluate optimizations of a specific source line 64 | 65 | --fixed-speedup (0-100) 66 | Evaluate optimizations of a specific amount 67 | 68 | SEE ALSO 69 | ======== 70 | 71 | * ``__ 72 | * ``man gdb`` 73 | -------------------------------------------------------------------------------- /example-coz-output.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/plasma-umass/coz/3d711c847ee9c3da9ceb9cc9acc7e43c82d53b18/example-coz-output.png -------------------------------------------------------------------------------- /include/coz.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2015, Charlie Curtsinger and Emery Berger, 3 | * University of Massachusetts Amherst 4 | * This file is part of the Coz project. See LICENSE.md file at the top-level 5 | * directory of this distribution and at http://github.com/plasma-umass/coz. 6 | */ 7 | 8 | #if !defined(COZ_H) 9 | #define COZ_H 10 | 11 | #ifndef __USE_GNU 12 | # define __USE_GNU 13 | #endif 14 | 15 | #ifndef _GNU_SOURCE 16 | # define _GNU_SOURCE 17 | #endif 18 | 19 | #include 20 | #include 21 | #include /* for memcpy hack below */ 22 | 23 | #if defined(__cplusplus) 24 | extern "C" { 25 | #endif 26 | 27 | #define COZ_COUNTER_TYPE_THROUGHPUT 1 28 | #define COZ_COUNTER_TYPE_BEGIN 2 29 | #define COZ_COUNTER_TYPE_END 3 30 | 31 | // Declare dlsym as a weak reference so libdl isn't required 32 | void* dlsym(void* handle, const char* symbol) __attribute__((weak)); 33 | 34 | // Counter info struct, containing both a counter and backoff size 35 | typedef struct { 36 | size_t count; // The actual count 37 | size_t backoff; // Used to batch updates to the shared counter. Currently unused. 38 | } coz_counter_t; 39 | 40 | // The type of the _coz_get_counter function 41 | typedef coz_counter_t* (*coz_get_counter_t)(int, const char*); 42 | 43 | // Locate and invoke _coz_get_counter 44 | static coz_counter_t* _call_coz_get_counter(int type, const char* name) { 45 | static unsigned char _initialized = 0; 46 | static coz_get_counter_t fn; // The pointer to _coz_get_counter 47 | 48 | if(!_initialized) { 49 | if(dlsym) { 50 | // Locate the _coz_get_counter method 51 | void* p = dlsym(RTLD_DEFAULT, "_coz_get_counter"); 52 | 53 | // Use memcpy to avoid pedantic GCC complaint about storing function pointer in void* 54 | memcpy(&fn, &p, sizeof(p)); 55 | } 56 | 57 | _initialized = 1; 58 | } 59 | 60 | // Call the function, or return null if profiler is not found 61 | if(fn) return fn(type, name); 62 | else return 0; 63 | } 64 | 65 | // Macro to initialize and increment a counter 66 | #define COZ_INCREMENT_COUNTER(type, name) \ 67 | if(1) { \ 68 | static unsigned char _initialized = 0; \ 69 | static coz_counter_t* _counter = 0; \ 70 | \ 71 | if(!_initialized) { \ 72 | _counter = _call_coz_get_counter(type, name); \ 73 | _initialized = 1; \ 74 | } \ 75 | if(_counter) { \ 76 | __atomic_add_fetch(&_counter->count, 1, __ATOMIC_RELAXED); \ 77 | } \ 78 | } 79 | 80 | #define STR2(x) #x 81 | #define STR(x) STR2(x) 82 | 83 | #define COZ_PROGRESS_NAMED(name) COZ_INCREMENT_COUNTER(COZ_COUNTER_TYPE_THROUGHPUT, name) 84 | 85 | #define COZ_PROGRESS COZ_INCREMENT_COUNTER(COZ_COUNTER_TYPE_THROUGHPUT, __FILE__ ":" STR(__LINE__)) 86 | #define COZ_BEGIN(name) COZ_INCREMENT_COUNTER(COZ_COUNTER_TYPE_BEGIN, name) 87 | #define COZ_END(name) COZ_INCREMENT_COUNTER(COZ_COUNTER_TYPE_END, name) 88 | 89 | #if defined(__cplusplus) 90 | } 91 | #endif 92 | 93 | #endif 94 | -------------------------------------------------------------------------------- /libcoz/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | set(sources 2 | ${PROJECT_SOURCE_DIR}/include/coz.h 3 | inspect.cpp 4 | inspect.h 5 | libcoz.cpp 6 | perf.cpp 7 | perf.h 8 | profiler.cpp 9 | profiler.h 10 | progress_point.h 11 | real.cpp 12 | real.h 13 | thread_state.h 14 | util.h 15 | ) 16 | 17 | add_library(coz MODULE ${sources} ${public_headers}) 18 | if(CONAN_PACKAGE_VERSION) 19 | set_target_properties(coz PROPERTIES VERSION ${CONAN_PACKAGE_VERSION}) 20 | endif() 21 | target_include_directories(coz 22 | PUBLIC 23 | $ 24 | $) 25 | target_link_libraries(coz PRIVATE ${CMAKE_DL_LIBS} rt Threads::Threads libelfin::libelfin) 26 | 27 | add_library(coz-instrumentation INTERFACE) 28 | target_include_directories(coz-instrumentation 29 | INTERFACE 30 | $ 31 | $) 32 | target_link_libraries(coz-instrumentation INTERFACE -Wl,--push-state,--no-as-needed ${CMAKE_DL_LIBS} -Wl,--pop-state) 33 | 34 | if(INSTALL_COZ) 35 | install(TARGETS coz 36 | EXPORT coz-profilerTargets 37 | ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR} 38 | LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR} 39 | RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}) 40 | install(DIRECTORY ${PROJECT_SOURCE_DIR}/include/. DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}) 41 | endif() 42 | -------------------------------------------------------------------------------- /libcoz/Makefile: -------------------------------------------------------------------------------- 1 | ROOT := .. 2 | TARGETS := libcoz.so 3 | LIBS := -ldl -lrt -lpthread $(shell pkg-config --libs libelf++ libdwarf++) 4 | CXXFLAGS := -gdwarf-3 --std=c++0x -g -O2 -fPIC -I$(ROOT)/include -I. \ 5 | $(shell pkg-config --cflags libelf++ libdwarf++) 6 | 7 | include $(ROOT)/common.mk 8 | 9 | check:: libcoz.so 10 | printf "int main(int argc, char *argv[])\n{\nreturn (0);\n}\n" > x.c 11 | gcc -g -o x x.c || ( $(RM) x x.c ; exit 1) 12 | ../coz run --- ./x 13 | if grep -q time= profile.coz; then echo success: coz profiler ran as it should.; fi 14 | $(RM) -f x.c x profile.coz 15 | -------------------------------------------------------------------------------- /libcoz/ccutil/log.h: -------------------------------------------------------------------------------- 1 | #if !defined(CCUTIL_LOG_H) 2 | #define CCUTIL_LOG_H 3 | 4 | #include 5 | 6 | namespace ccutil { 7 | static const char* InfoColor = "\033[01;34m"; 8 | static const char* WarningColor = "\033[01;33m"; 9 | static const char* FatalColor = "\033[01;31m"; 10 | static const char* SourceColor = "\033[34m"; 11 | static const char* EndColor = "\033[0m"; 12 | 13 | class logger_base { 14 | public: 15 | logger_base indent(size_t n, size_t tab_size = 2) { 16 | return logger_base(); 17 | } 18 | 19 | template logger_base operator<<(T t) { 20 | return logger_base(); 21 | } 22 | }; 23 | 24 | class logger : public logger_base { 25 | private: 26 | bool _done; 27 | bool _exit; 28 | public: 29 | logger(bool exit = false, bool done = true) : _exit(exit), _done(done) {} 30 | 31 | logger(logger&& other) { 32 | _exit = other._exit; 33 | _done = other._done; 34 | other._done = false; 35 | } 36 | 37 | ~logger() { 38 | if(_done) { 39 | std::cerr << EndColor << "\n"; 40 | if(_exit) abort(); 41 | } 42 | } 43 | 44 | void operator=(logger&& other) { 45 | _exit = other._exit; 46 | _done = other._done; 47 | other._done = false; 48 | } 49 | 50 | logger&& indent(size_t n, size_t tab_size = 2) { 51 | for(size_t i=0; i logger&& operator<<(T t) { 60 | std::cerr << t; 61 | return std::move(*this); 62 | } 63 | }; 64 | } 65 | 66 | #if defined(NDEBUG) 67 | # define LOG(color, exit) (ccutil::logger(exit) << color) 68 | # define INFO (ccutil::logger_base()) 69 | # define ASSERT(cond) (ccutil::logger_base()) 70 | #else 71 | # define LOG(color, exit) (ccutil::logger(exit) << ccutil::SourceColor << "[" << __FILE__ << ":" << __LINE__ << "] " << color) 72 | # define INFO LOG(ccutil::InfoColor, false) 73 | # define ASSERT(cond) (cond) ? ccutil::logger_base() : FATAL 74 | #endif 75 | 76 | #define WARNING LOG(ccutil::WarningColor, false) 77 | #define PREFER(cond) (cond) ? ccutil::logger_base() : WARNING 78 | 79 | #define FATAL LOG(ccutil::FatalColor, true) 80 | #define REQUIRE(cond) (cond) ? ccutil::logger_base() : FATAL 81 | 82 | #endif -------------------------------------------------------------------------------- /libcoz/ccutil/spinlock.h: -------------------------------------------------------------------------------- 1 | #if !defined(CCUTIL_SPINLOCK_H) 2 | #define CCUTIL_SPINLOCK_H 3 | 4 | #include 5 | 6 | class spinlock { 7 | public: 8 | inline void lock() { 9 | while(_flag.test_and_set()) { 10 | #if defined(__i386__) || defined(__x86_64__) 11 | /* 12 | * NOTE: "rep nop" works on all Intel architectures and has the same 13 | * encoding as "pause" on the newer ones. 14 | */ 15 | __asm__ __volatile__ ("rep nop"); 16 | #else 17 | /* nothing */ 18 | #endif 19 | } 20 | } 21 | 22 | inline bool trylock() { 23 | return !_flag.test_and_set(); 24 | } 25 | 26 | inline void unlock() { 27 | _flag.clear(); 28 | } 29 | 30 | private: 31 | std::atomic_flag _flag = ATOMIC_FLAG_INIT; 32 | }; 33 | 34 | #endif 35 | -------------------------------------------------------------------------------- /libcoz/ccutil/static_map.h: -------------------------------------------------------------------------------- 1 | #if !defined(CCUTIL_STATIC_MAP_H) 2 | #define CCUTIL_STATIC_MAP_H 3 | 4 | #include 5 | 6 | #include "log.h" 7 | 8 | template 9 | class static_map { 10 | public: 11 | V* insert(K key) { 12 | size_t bucket = get_bucket(key); 13 | size_t offset = 0; 14 | while(offset < MapSize) { 15 | K empty_key = NullKey; 16 | size_t index = (bucket + offset) % MapSize; 17 | if(_entries[index]._tag.compare_exchange_weak(empty_key, key)) { 18 | // Successfully tagged the entry 19 | return &_entries[index]._value; 20 | } 21 | // Advance to the next bucket 22 | offset++; 23 | } 24 | 25 | // TODO: Could just keep probing until a slot opens, but livelock would be possible... 26 | WARNING << "Thread state map is full!"; 27 | return nullptr; 28 | } 29 | 30 | V* find(K key) { 31 | size_t bucket = get_bucket(key); 32 | size_t offset = 0; 33 | while(offset < MapSize) { 34 | size_t index = (bucket + offset) % MapSize; 35 | if(_entries[index]._tag.load() == key) { 36 | return &_entries[index]._value; 37 | } 38 | // Advance to the next bucket 39 | offset++; 40 | } 41 | 42 | return nullptr; 43 | } 44 | 45 | void remove(K key) { 46 | size_t bucket = get_bucket(key); 47 | size_t offset = 0; 48 | while(offset < MapSize) { 49 | size_t index = (bucket + offset) % MapSize; 50 | if(_entries[index]._tag.load() == key) { 51 | _entries[index]._tag.store(NullKey); 52 | return; 53 | } 54 | // Advance to the next bucket 55 | offset++; 56 | } 57 | } 58 | 59 | private: 60 | size_t get_bucket(K key) { 61 | // TODO: Support hash function parameter if this class is reused 62 | return key % MapSize; 63 | } 64 | 65 | struct entry { 66 | std::atomic _tag; 67 | V _value; 68 | }; 69 | 70 | entry _entries[MapSize]; 71 | }; 72 | 73 | #endif 74 | -------------------------------------------------------------------------------- /libcoz/ccutil/timer.h: -------------------------------------------------------------------------------- 1 | #if !defined(CCUTIL_TIMER_H) 2 | #define CCUTIL_TIMER_H 3 | 4 | #include 5 | #include 6 | #include 7 | 8 | #include "log.h" 9 | 10 | class timer { 11 | public: 12 | timer() : _initialized(false) {} 13 | 14 | timer(int sig) { 15 | struct sigevent ev; 16 | memset(&ev, 0, sizeof(ev)); 17 | ev.sigev_notify = SIGEV_THREAD_ID; 18 | ev.sigev_signo = sig; 19 | ev._sigev_un._tid = gettid(); 20 | 21 | REQUIRE(timer_create(CLOCK_THREAD_CPUTIME_ID, &ev, &_timer) == 0) 22 | << "Failed to create timer!"; 23 | 24 | _initialized = true; 25 | } 26 | 27 | timer(timer&& other) { 28 | _timer = other._timer; 29 | _initialized = other._initialized; 30 | other._initialized = false; 31 | } 32 | 33 | ~timer() { 34 | if(_initialized) { 35 | REQUIRE(timer_delete(_timer) == 0) << "Failed to delete timer!"; 36 | } 37 | } 38 | 39 | void operator=(timer&& other) { 40 | _timer = other._timer; 41 | _initialized = other._initialized; 42 | other._initialized = false; 43 | } 44 | 45 | void start_interval(size_t time_ns) { 46 | ASSERT(_initialized) << "Can't start an uninitialized timer"; 47 | 48 | long ns = time_ns % 1000000000; 49 | time_t s = (time_ns - ns) / 1000000000; 50 | 51 | struct itimerspec ts; 52 | memset(&ts, 0, sizeof(ts)); 53 | ts.it_interval.tv_sec = s; 54 | ts.it_interval.tv_nsec = ns; 55 | ts.it_value.tv_sec = s; 56 | ts.it_value.tv_nsec = ns; 57 | 58 | REQUIRE(timer_settime(_timer, 0, &ts, NULL) == 0) << "Failed to start interval timer"; 59 | 60 | _initialized = true; 61 | } 62 | 63 | void start_oneshot(size_t time_ns) { 64 | ASSERT(_initialized) << "Can't start an uninitialized timer"; 65 | 66 | long ns = time_ns % 1000000000; 67 | time_t s = (time_ns - ns) / 1000000000; 68 | 69 | struct itimerspec ts; 70 | memset(&ts, 0, sizeof(ts)); 71 | ts.it_value.tv_sec = s; 72 | ts.it_value.tv_nsec = ns; 73 | 74 | REQUIRE(timer_settime(_timer, 0, &ts, NULL) == 0) << "Failed to start one-shot timer"; 75 | } 76 | 77 | private: 78 | timer(const timer&) = delete; 79 | void operator=(const timer&) = delete; 80 | 81 | timer_t _timer; 82 | bool _initialized; 83 | }; 84 | 85 | #endif 86 | -------------------------------------------------------------------------------- /libcoz/ccutil/wrapped_array.h: -------------------------------------------------------------------------------- 1 | #if !defined(CCUTIL_WRAPPED_ARRAY_H) 2 | #define CCUTIL_WRAPPED_ARRAY_H 3 | 4 | namespace ccutil { 5 | template class wrapped_array { 6 | private: 7 | T* _base; 8 | size_t _size; 9 | public: 10 | // Construct an array wrapper from a base pointer and array size 11 | wrapped_array(T* base, size_t size) : _base(base), _size(size) {} 12 | wrapped_array(const wrapped_array& other) : _base(other._base), _size(other._size) {} 13 | 14 | // Get the size of the wrapped array 15 | size_t size() { return _size; } 16 | 17 | // Access an element by index 18 | T& operator[](size_t i) { return _base[i]; } 19 | 20 | // Get a slice of this array, from a start index (inclusive) to end index (exclusive) 21 | wrapped_array slice(size_t start, size_t end) { 22 | return wrapped_array(&_base[start], end - start); 23 | } 24 | 25 | operator T*() { 26 | return _base; 27 | } 28 | 29 | // Iterator class for convenient range-based for loop support 30 | class iterator { 31 | private: 32 | T* _p; 33 | public: 34 | // Start the iterator at a given pointer 35 | iterator(T* p) : _p(p) {} 36 | 37 | // Advance to the next element 38 | void operator++() { ++_p; } 39 | void operator++(int) { _p++; } 40 | 41 | // Get the current element 42 | T& operator*() const { return *_p; } 43 | 44 | // Compare iterators 45 | bool operator==(const iterator& other) const { return _p == other._p; } 46 | bool operator!=(const iterator& other) const { return _p != other._p; } 47 | }; 48 | 49 | // Get an iterator positioned at the beginning of the wrapped array 50 | iterator begin() { return iterator(_base); } 51 | 52 | // Get an iterator positioned at the end of the wrapped array 53 | iterator end() { return iterator(&_base[_size]); } 54 | }; 55 | 56 | // Function for automatic template argument deduction 57 | template wrapped_array wrap_array(A* base, size_t size) { 58 | return wrapped_array(base, size); 59 | } 60 | } 61 | 62 | #endif 63 | -------------------------------------------------------------------------------- /libcoz/inspect.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2015, Charlie Curtsinger and Emery Berger, 3 | * University of Massachusetts Amherst 4 | * This file is part of the Coz project. See LICENSE.md file at the top-level 5 | * directory of this distribution and at http://github.com/plasma-umass/coz. 6 | */ 7 | 8 | #if !defined(CAUSAL_RUNTIME_INSPECT_H) 9 | #define CAUSAL_RUNTIME_INSPECT_H 10 | 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | #include 17 | #include 18 | #include 19 | #include 20 | #include 21 | 22 | namespace dwarf { 23 | class die; 24 | class line_table; 25 | } 26 | 27 | class file; 28 | class interval; 29 | class line; 30 | class memory_map; 31 | 32 | /** 33 | * Handle for a single line in the program's memory map 34 | */ 35 | class line { 36 | public: 37 | line(std::weak_ptr f, size_t l) : _file(f), _line(l) {} 38 | 39 | inline std::shared_ptr get_file() const { return _file.lock(); } 40 | inline size_t get_line() const { return _line; } 41 | inline void add_sample() { _samples.fetch_add(1, std::memory_order_relaxed); } 42 | inline size_t get_samples() const { return _samples.load(std::memory_order_relaxed); } 43 | 44 | private: 45 | std::weak_ptr _file; 46 | size_t _line; 47 | std::atomic _samples = ATOMIC_VAR_INIT(0); 48 | }; 49 | 50 | class interval { 51 | public: 52 | /// Standard constructor 53 | interval(uintptr_t base, uintptr_t limit) : _base(base), _limit(limit) {} 54 | interval(void* base, void* limit) : interval((uintptr_t)base, (uintptr_t)limit) {} 55 | 56 | /// Unit interval constructor 57 | interval(uintptr_t p) : _base(p), _limit(p+1) {} 58 | interval(void* p) : interval((uintptr_t)p) {} 59 | 60 | /// Default constructor for use in maps 61 | interval() : interval(nullptr, nullptr) {} 62 | 63 | /// Shift 64 | interval operator+(uintptr_t x) const { 65 | return interval(_base + x, _limit + x); 66 | } 67 | 68 | /// Shift in place 69 | void operator+=(uintptr_t x) { 70 | _base += x; 71 | _limit += x; 72 | } 73 | 74 | /// Comparison function that treats overlapping intervals as equal 75 | bool operator<(const interval& b) const { 76 | return _limit <= b._base; 77 | } 78 | 79 | /// Check if an interval contains a point 80 | bool contains(uintptr_t x) const { 81 | return _base <= x && x < _limit; 82 | } 83 | 84 | uintptr_t get_base() const { return _base; } 85 | uintptr_t get_limit() const { return _limit; } 86 | 87 | private: 88 | uintptr_t _base; 89 | uintptr_t _limit; 90 | }; 91 | 92 | /** 93 | * Handle for a file in the program's memory map 94 | */ 95 | class file : public std::enable_shared_from_this { 96 | public: 97 | explicit file(const std::string& name) : _name(name) {} 98 | file(const file&) = default; 99 | file& operator=(const file&) = default; 100 | 101 | inline const std::string& get_name() const { return _name; } 102 | 103 | inline const std::map> lines() const { 104 | return _lines; 105 | } 106 | 107 | private: 108 | friend class memory_map; 109 | 110 | inline std::shared_ptr get_line(size_t index) { 111 | auto iter = _lines.find(index); 112 | if(iter != _lines.end()) { 113 | return iter->second; 114 | } else { 115 | std::shared_ptr l(new line(shared_from_this(), index)); 116 | _lines.emplace(index, l); 117 | return l; 118 | } 119 | } 120 | 121 | inline bool has_line(size_t index) { 122 | return _lines.find(index) != _lines.end(); 123 | } 124 | 125 | std::string _name; 126 | std::map> _lines; 127 | }; 128 | 129 | /** 130 | * The class responsible for constructing and tracking the mapping between address 131 | * ranges and files/lines. 132 | */ 133 | class memory_map { 134 | public: 135 | inline const std::map>& files() const { return _files; } 136 | inline const std::map>& ranges() const { return _ranges; } 137 | 138 | /// Build a map from addresses to source lines by examining binaries that match the provided 139 | /// scope patterns, adding only source files matching the source scope patterns. 140 | void build(const std::unordered_set& binary_scope, 141 | const std::unordered_set& source_scope); 142 | 143 | std::shared_ptr find_line(const std::string& name); 144 | std::shared_ptr find_line(uintptr_t addr); 145 | 146 | static memory_map& get_instance(); 147 | 148 | private: 149 | memory_map() : _files(std::map>()), 150 | _ranges(std::map>()) {} 151 | memory_map(const memory_map&) = delete; 152 | memory_map& operator=(const memory_map&) = delete; 153 | 154 | inline std::shared_ptr get_file(const std::string& filename) { 155 | auto iter = _files.find(filename); 156 | if(iter != _files.end()) { 157 | return iter->second; 158 | } else { 159 | std::shared_ptr f(new file(filename)); 160 | _files.emplace(filename, f); 161 | return f; 162 | } 163 | } 164 | 165 | void add_range(std::string filename, size_t line_no, interval range); 166 | 167 | /// Find a debug version of provided file and add all of its in-scope lines to the map 168 | bool process_file(const std::string& name, uintptr_t load_address, 169 | const std::unordered_set& source_scope); 170 | 171 | /// Add entries for all inlined calls 172 | void process_inlines(const dwarf::die& d, 173 | const dwarf::line_table& table, 174 | const std::unordered_set& source_scope, 175 | uintptr_t load_address); 176 | 177 | std::map> _files; 178 | std::map> _ranges; 179 | }; 180 | 181 | static std::ostream& operator<<(std::ostream& os, const interval& i) { 182 | os << std::hex << "0x" << i.get_base() << "-0x" << i.get_limit() << std::dec; 183 | return os; 184 | } 185 | 186 | static std::ostream& operator<<(std::ostream& os, const file& f) { 187 | os << f.get_name(); 188 | return os; 189 | } 190 | 191 | static std::ostream& operator<<(std::ostream& os, const file* f) { 192 | os << *f; 193 | return os; 194 | } 195 | 196 | static std::ostream& operator<<(std::ostream& os, const line& l) { 197 | os << l.get_file() << ":" << l.get_line(); 198 | return os; 199 | } 200 | 201 | static std::ostream& operator<<(std::ostream& os, const line* l) { 202 | os << *l; 203 | return os; 204 | } 205 | 206 | #endif 207 | -------------------------------------------------------------------------------- /libcoz/perf.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2015, Charlie Curtsinger and Emery Berger, 3 | * University of Massachusetts Amherst 4 | * This file is part of the Coz project. See LICENSE.md file at the top-level 5 | * directory of this distribution and at http://github.com/plasma-umass/coz. 6 | */ 7 | 8 | #if !defined(CAUSAL_RUNTIME_PERF_H) 9 | #define CAUSAL_RUNTIME_PERF_H 10 | 11 | #include 12 | #include 13 | 14 | #include 15 | #include 16 | #include 17 | 18 | #include "ccutil/log.h" 19 | #include "ccutil/wrapped_array.h" 20 | 21 | #if __GLIBC__ == 2 && __GLIBC_MINOR__ < 30 22 | #include 23 | #define gettid() syscall(SYS_gettid) 24 | #endif 25 | 26 | // Workaround for missing hw_breakpoint.h include file: 27 | // This include file just defines constants used to configure watchpoint registers. 28 | // This will be constant across x86 systems. 29 | enum { HW_BREAKPOINT_X = 4}; 30 | 31 | class perf_event { 32 | public: 33 | enum class record_type; 34 | class record; 35 | class sample_record; 36 | 37 | /// Default constructor 38 | perf_event(); 39 | /// Open a perf_event file using the given options structure 40 | perf_event(struct perf_event_attr& pe, pid_t pid = 0, int cpu = -1); 41 | /// Move constructor 42 | perf_event(perf_event&& other); 43 | 44 | /// Close the perf event file and unmap the ring buffer 45 | ~perf_event(); 46 | 47 | /// Move assignment is supported 48 | void operator=(perf_event&& other); 49 | 50 | /// Read event count 51 | uint64_t get_count() const; 52 | 53 | /// Start counting events and collecting samples 54 | void start(); 55 | 56 | /// Stop counting events 57 | void stop(); 58 | 59 | /// Close the perf_event file and unmap the ring buffer 60 | void close(); 61 | 62 | /// Configure the perf_event file to deliver a signal when samples are ready to be processed 63 | void set_ready_signal(int sig); 64 | 65 | /// An enum class with all the available sampling data 66 | enum class sample : uint64_t { 67 | ip = PERF_SAMPLE_IP, 68 | pid_tid = PERF_SAMPLE_TID, 69 | time = PERF_SAMPLE_TIME, 70 | addr = PERF_SAMPLE_ADDR, 71 | id = PERF_SAMPLE_ID, 72 | stream_id = PERF_SAMPLE_STREAM_ID, 73 | cpu = PERF_SAMPLE_CPU, 74 | period = PERF_SAMPLE_PERIOD, 75 | 76 | #if defined(PREF_SAMPLE_READ) 77 | read = PERF_SAMPLE_READ, 78 | #else 79 | read = 0, 80 | #endif 81 | 82 | callchain = PERF_SAMPLE_CALLCHAIN, 83 | raw = PERF_SAMPLE_RAW, 84 | 85 | #if defined(PERF_SAMPLE_BRANCH_STACK) 86 | branch_stack = PERF_SAMPLE_BRANCH_STACK, 87 | #else 88 | branch_stack = 0, 89 | #endif 90 | 91 | #if defined(PERF_SAMPLE_REGS_USER) 92 | regs = PERF_SAMPLE_REGS_USER, 93 | #else 94 | regs = 0, 95 | #endif 96 | 97 | #if defined(PERF_SAMPLE_STACK_USER) 98 | stack = PERF_SAMPLE_STACK_USER, 99 | #else 100 | stack = 0, 101 | #endif 102 | 103 | _end = PERF_SAMPLE_MAX 104 | }; 105 | 106 | /// Check if this perf_event was configured to collect a type of sample data 107 | inline bool is_sampling(sample s) const { 108 | return _sample_type & static_cast(s); 109 | } 110 | 111 | /// Get the configuration for this perf_event's read format 112 | inline uint64_t get_read_format() const { 113 | return _read_format; 114 | } 115 | 116 | /// An enum to distinguish types of records in the mmapped ring buffer 117 | enum class record_type { 118 | mmap = PERF_RECORD_MMAP, 119 | lost = PERF_RECORD_LOST, 120 | comm = PERF_RECORD_COMM, 121 | exit = PERF_RECORD_EXIT, 122 | throttle = PERF_RECORD_THROTTLE, 123 | unthrottle = PERF_RECORD_UNTHROTTLE, 124 | fork = PERF_RECORD_FORK, 125 | read = PERF_RECORD_READ, 126 | sample = PERF_RECORD_SAMPLE, 127 | 128 | #if defined(PERF_RECORD_MMAP2) 129 | mmap2 = PERF_RECORD_MMAP2 130 | #else 131 | mmap2 = 0 132 | #endif 133 | }; 134 | 135 | class iterator; 136 | 137 | /// A generic record type 138 | struct record { 139 | friend class perf_event::iterator; 140 | public: 141 | record_type get_type() const { return static_cast(_header->type); } 142 | 143 | inline bool is_mmap() const { return get_type() == record_type::mmap; } 144 | inline bool is_lost() const { return get_type() == record_type::lost; } 145 | inline bool is_comm() const { return get_type() == record_type::comm; } 146 | inline bool is_exit() const { return get_type() == record_type::exit; } 147 | inline bool is_throttle() const { return get_type() == record_type::throttle; } 148 | inline bool is_unthrottle() const { return get_type() == record_type::unthrottle; } 149 | inline bool is_fork() const { return get_type() == record_type::fork; } 150 | inline bool is_read() const { return get_type() == record_type::read; } 151 | inline bool is_sample() const { return get_type() == record_type::sample; } 152 | inline bool is_mmap2() const { return get_type() == record_type::mmap2; } 153 | 154 | uint64_t get_ip() const; 155 | uint64_t get_pid() const; 156 | uint64_t get_tid() const; 157 | uint64_t get_time() const; 158 | uint32_t get_cpu() const; 159 | ccutil::wrapped_array get_callchain() const; 160 | 161 | private: 162 | record(const perf_event& source, struct perf_event_header* header) : 163 | _source(source), _header(header) {} 164 | 165 | template T locate_field() const; 166 | 167 | const perf_event& _source; 168 | struct perf_event_header* _header; 169 | }; 170 | 171 | class iterator { 172 | public: 173 | iterator(perf_event& source, struct perf_event_mmap_page* mapping) : 174 | _source(source), _mapping(mapping) { 175 | if(mapping != nullptr) { 176 | _index = mapping->data_tail; 177 | _head = mapping->data_head; 178 | //__atomic_thread_fence(__ATOMIC_SEQ_CST); // Not required for thread-local perf events 179 | } else { 180 | _index = 0; 181 | _head = 0; 182 | } 183 | } 184 | 185 | ~iterator() { 186 | if(_mapping != nullptr) { 187 | _mapping->data_tail = _index; 188 | } 189 | } 190 | 191 | void next(); 192 | record get(); 193 | bool has_data() const; 194 | 195 | iterator& operator++() { next(); return *this; } 196 | record operator*() { return get(); } 197 | bool operator!=(const iterator& other) { return has_data() != other.has_data(); } 198 | 199 | private: 200 | perf_event& _source; 201 | size_t _index; 202 | size_t _head; 203 | struct perf_event_mmap_page* _mapping; 204 | 205 | // Buffer to hold the current record. Just a hack until records play nice with the ring buffer 206 | uint8_t _buf[4096]; 207 | }; 208 | 209 | /// Get an iterator to the beginning of the memory mapped ring buffer 210 | iterator begin() { 211 | return iterator(*this, _mapping); 212 | } 213 | 214 | // Get an iterator to the end of the memory mapped ring buffer 215 | iterator end() { 216 | return iterator(*this, nullptr); 217 | } 218 | 219 | private: 220 | // Disallow copy and assignment 221 | perf_event(const perf_event&) = delete; 222 | void operator=(const perf_event&) = delete; 223 | 224 | // Copy data out of the mmap ring buffer 225 | static void copy_from_ring_buffer(struct perf_event_mmap_page* mapping, 226 | ptrdiff_t index, void* dest, size_t bytes); 227 | 228 | /// File descriptor for the perf event 229 | long _fd = -1; 230 | 231 | /// Memory mapped perf event region 232 | struct perf_event_mmap_page* _mapping = nullptr; 233 | 234 | /// The sample type from this perf_event's configuration 235 | uint64_t _sample_type = 0; 236 | /// The read format from this perf event's configuration 237 | uint64_t _read_format = 0; 238 | }; 239 | 240 | #endif 241 | -------------------------------------------------------------------------------- /libcoz/progress_point.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2015, Charlie Curtsinger and Emery Berger, 3 | * University of Massachusetts Amherst 4 | * This file is part of the Coz project. See LICENSE.md file at the top-level 5 | * directory of this distribution and at http://github.com/plasma-umass/coz. 6 | */ 7 | 8 | #if !defined(CAUSAL_RUNTIME_PROGRESS_POINT_H) 9 | #define CAUSAL_RUNTIME_PROGRESS_POINT_H 10 | 11 | #include 12 | #include 13 | 14 | #include "coz.h" 15 | 16 | #include "inspect.h" 17 | #include "perf.h" 18 | #include "util.h" 19 | 20 | #include "ccutil/log.h" 21 | 22 | /// Enum wrapper around defines for progress point types 23 | enum class progress_point_type { 24 | throughput = COZ_COUNTER_TYPE_THROUGHPUT, 25 | begin = COZ_COUNTER_TYPE_BEGIN, 26 | end = COZ_COUNTER_TYPE_END 27 | }; 28 | 29 | /** 30 | * A progress point to measure throughput 31 | */ 32 | class throughput_point { 33 | public: 34 | class saved; 35 | 36 | /// Create a throughput progress point with a given name 37 | throughput_point(const std::string& name) : _name(name), _counter() {} 38 | 39 | /// Save the state of this progress point 40 | saved* save() const { 41 | return new saved(this); 42 | } 43 | 44 | /// Add one to the number of visits to this progress point 45 | void visit(size_t visits=1) { 46 | __atomic_add_fetch(&_counter.count, visits, __ATOMIC_RELAXED); 47 | } 48 | 49 | /// Get the number of visits to this progress point 50 | size_t get_count() const { 51 | return __atomic_load_n(&_counter.count, __ATOMIC_RELAXED); 52 | } 53 | 54 | /// Get a pointer to the counter struct (used by source progress points) 55 | coz_counter_t* get_counter_struct() { 56 | return &_counter; 57 | } 58 | 59 | /// Get the name of this progress point 60 | const std::string& get_name() const { 61 | return _name; 62 | } 63 | 64 | class saved { 65 | public: 66 | saved() {} 67 | 68 | /// Save the state of a throughput point 69 | saved(const throughput_point* origin) : _origin(origin), _start_count(origin->get_count()) {} 70 | 71 | /// Log the change in this progress point since it was saved 72 | void log(std::ostream& os) const { 73 | os << "throughput-point\t" 74 | << "name=" << _origin->get_name() << "\t" 75 | << "delta=" << get_delta() << "\n"; 76 | } 77 | 78 | size_t get_delta() const { 79 | return _origin->get_count() - _start_count; 80 | } 81 | 82 | protected: 83 | const throughput_point* _origin; 84 | size_t _start_count; 85 | }; 86 | 87 | private: 88 | const std::string _name; 89 | coz_counter_t _counter; 90 | }; 91 | 92 | /** 93 | * A progress point to measure latency with two counters 94 | */ 95 | class latency_point { 96 | public: 97 | class saved; 98 | 99 | /// Create a latency progress point with a given name 100 | latency_point(const std::string& name) : _name(name), _begin_counter(), _end_counter() {} 101 | 102 | /// Save the state of this progress point 103 | saved* save() const { 104 | return new saved(this); 105 | } 106 | 107 | /// Add one visit to the begin progress point 108 | void visit_begin(size_t visits=1) { 109 | __atomic_add_fetch(&_begin_counter.count, visits, __ATOMIC_RELAXED); 110 | } 111 | 112 | /// Add one visit to the end progress point 113 | void visit_end(size_t visits=1) { 114 | __atomic_add_fetch(&_end_counter.count, visits, __ATOMIC_RELAXED); 115 | } 116 | 117 | /// Get the number of visits to the begin progress point 118 | size_t get_begin_count() const { 119 | return __atomic_load_n(&_begin_counter.count, __ATOMIC_RELAXED); 120 | } 121 | 122 | /// Get the number of visits to the end progress point 123 | size_t get_end_count() const { 124 | return __atomic_load_n(&_end_counter.count, __ATOMIC_RELAXED); 125 | } 126 | 127 | /// Get a pointer to the begin point's counter struct (used by source progress points) 128 | coz_counter_t* get_begin_counter_struct() { 129 | return &_begin_counter; 130 | } 131 | 132 | /// Get a pointer to the end point's counter struct (used by source progress points) 133 | coz_counter_t* get_end_counter_struct() { 134 | return &_end_counter; 135 | } 136 | 137 | /// Get the name of this progress point 138 | const std::string& get_name() const { 139 | return _name; 140 | } 141 | 142 | class saved { 143 | public: 144 | saved() {} 145 | 146 | /// Save the state of a throughput point 147 | saved(const latency_point* origin) : _origin(origin), 148 | _begin_start_count(origin->get_begin_count()), 149 | _end_start_count(origin->get_end_count()) {} 150 | 151 | /// Log the change in this progress point since it was saved 152 | virtual void log(std::ostream& os) const { 153 | os << "latency-point\t" 154 | << "name=" << _origin->get_name() << "\t" 155 | << "arrivals=" << get_begin_delta() << "\t" 156 | << "departures=" << get_end_delta() << "\t" 157 | << "difference=" << get_difference() << "\n"; 158 | } 159 | 160 | virtual size_t get_begin_delta() const { 161 | return _origin->get_begin_count() - _begin_start_count; 162 | } 163 | 164 | virtual size_t get_end_delta() const { 165 | return _origin->get_end_count() - _end_start_count; 166 | } 167 | 168 | virtual size_t get_difference() const { 169 | return _origin->get_begin_count() - _origin->get_end_count(); 170 | } 171 | 172 | protected: 173 | const latency_point* _origin; 174 | size_t _begin_start_count; 175 | size_t _end_start_count; 176 | }; 177 | 178 | private: 179 | const std::string _name; 180 | coz_counter_t _begin_counter; 181 | coz_counter_t _end_counter; 182 | }; 183 | 184 | #endif 185 | -------------------------------------------------------------------------------- /libcoz/real.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2015, Charlie Curtsinger and Emery Berger, 3 | * University of Massachusetts Amherst 4 | * This file is part of the Coz project. See LICENSE.md file at the top-level 5 | * directory of this distribution and at http://github.com/plasma-umass/coz. 6 | */ 7 | 8 | #if !defined(CAUSAL_RUNTIME_REAL_H) 9 | #define CAUSAL_RUNTIME_REAL_H 10 | 11 | #include 12 | #include 13 | #include 14 | #include 15 | 16 | #define DECLARE_WRAPPER(name) extern decltype(::name)* name; 17 | 18 | namespace real { 19 | DECLARE_WRAPPER(exit); 20 | DECLARE_WRAPPER(_exit); 21 | DECLARE_WRAPPER(_Exit); 22 | DECLARE_WRAPPER(fork); 23 | 24 | DECLARE_WRAPPER(sigaction); 25 | DECLARE_WRAPPER(signal); 26 | DECLARE_WRAPPER(kill); 27 | DECLARE_WRAPPER(sigprocmask); 28 | DECLARE_WRAPPER(sigwait); 29 | DECLARE_WRAPPER(sigwaitinfo); 30 | DECLARE_WRAPPER(sigtimedwait); 31 | 32 | DECLARE_WRAPPER(pthread_create); 33 | DECLARE_WRAPPER(pthread_exit); 34 | DECLARE_WRAPPER(pthread_join); 35 | DECLARE_WRAPPER(pthread_tryjoin_np); 36 | DECLARE_WRAPPER(pthread_timedjoin_np); 37 | DECLARE_WRAPPER(pthread_sigmask); 38 | DECLARE_WRAPPER(pthread_kill); 39 | DECLARE_WRAPPER(pthread_sigqueue); 40 | 41 | DECLARE_WRAPPER(pthread_mutex_lock); 42 | DECLARE_WRAPPER(pthread_mutex_trylock); 43 | DECLARE_WRAPPER(pthread_mutex_unlock); 44 | 45 | DECLARE_WRAPPER(pthread_cond_wait); 46 | DECLARE_WRAPPER(pthread_cond_timedwait); 47 | DECLARE_WRAPPER(pthread_cond_signal); 48 | DECLARE_WRAPPER(pthread_cond_broadcast); 49 | 50 | DECLARE_WRAPPER(pthread_barrier_wait); 51 | 52 | DECLARE_WRAPPER(pthread_rwlock_rdlock); 53 | DECLARE_WRAPPER(pthread_rwlock_tryrdlock); 54 | DECLARE_WRAPPER(pthread_rwlock_timedrdlock); 55 | DECLARE_WRAPPER(pthread_rwlock_wrlock); 56 | DECLARE_WRAPPER(pthread_rwlock_trywrlock); 57 | DECLARE_WRAPPER(pthread_rwlock_timedwrlock); 58 | DECLARE_WRAPPER(pthread_rwlock_unlock); 59 | }; 60 | 61 | #endif 62 | -------------------------------------------------------------------------------- /libcoz/thread_state.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2015, Charlie Curtsinger and Emery Berger, 3 | * University of Massachusetts Amherst 4 | * This file is part of the Coz project. See LICENSE.md file at the top-level 5 | * directory of this distribution and at http://github.com/plasma-umass/coz. 6 | */ 7 | 8 | #if !defined(CAUSAL_RUNTIME_THREAD_STATE_H) 9 | #define CAUSAL_RUNTIME_THREAD_STATE_H 10 | 11 | #include 12 | 13 | #include "ccutil/timer.h" 14 | 15 | class thread_state { 16 | public: 17 | bool in_use = false; //< Set by the main thread to prevent signal handler from racing 18 | size_t local_delay = 0; //< The count of delays (or selected line visits) in the thread 19 | perf_event sampler; //< The sampler object for this thread 20 | timer process_timer; //< The timer that triggers sample processing for this thread 21 | size_t pre_block_time; //< The time saved before (possibly) blocking 22 | 23 | inline void set_in_use(bool value) { 24 | in_use = value; 25 | std::atomic_signal_fence(std::memory_order_seq_cst); 26 | } 27 | 28 | bool check_in_use() { 29 | return in_use; 30 | } 31 | }; 32 | 33 | #endif 34 | -------------------------------------------------------------------------------- /libcoz/util.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2015, Charlie Curtsinger and Emery Berger, 3 | * University of Massachusetts Amherst 4 | * This file is part of the Coz project. See LICENSE.md file at the top-level 5 | * directory of this distribution and at http://github.com/plasma-umass/coz. 6 | */ 7 | 8 | #if !defined(CAUSAL_RUNTIME_UTIL_H) 9 | #define CAUSAL_RUNTIME_UTIL_H 10 | 11 | #if defined(__APPLE__) 12 | #include 13 | #else 14 | #include 15 | #endif 16 | 17 | #include 18 | #include 19 | #include 20 | 21 | #include 22 | #include 23 | #include 24 | 25 | #include "real.h" 26 | 27 | /** 28 | * Get the current time in nanoseconds 29 | */ 30 | static size_t get_time() { 31 | #if defined(__APPLE__) 32 | return mach_absolute_time(); 33 | #else 34 | struct timespec ts; 35 | if(clock_gettime(CLOCK_REALTIME, &ts)) { 36 | perror("get_time():"); 37 | abort(); 38 | } 39 | return ts.tv_nsec + ts.tv_sec * 1000 * 1000 * 1000; 40 | #endif 41 | } 42 | 43 | static inline size_t wait(size_t ns) { 44 | if(ns == 0) return 0; 45 | 46 | struct timespec ts; 47 | ts.tv_nsec = ns % (1000 * 1000 * 1000); 48 | ts.tv_sec = (ns - ts.tv_nsec) / (1000 * 1000 * 1000); 49 | 50 | size_t start_time = get_time(); 51 | while(nanosleep(&ts, &ts) != 0) {} 52 | 53 | return get_time() - start_time; 54 | } 55 | 56 | static inline std::vector split(const std::string& s, char delim='\t') { 57 | std::vector elems; 58 | std::stringstream ss(s); 59 | std::string item; 60 | while (std::getline(ss, item, delim)) { 61 | if(item.length()) elems.push_back(item); 62 | } 63 | return elems; 64 | } 65 | 66 | static inline std::string getenv_safe(const char* var, const char* fallback = "") { 67 | const char* value = getenv(var); 68 | if(!value) value = fallback; 69 | return std::string(value); 70 | } 71 | 72 | #endif 73 | -------------------------------------------------------------------------------- /patches/blackscholes.patch: -------------------------------------------------------------------------------- 1 | 8a9 2 | > #include 3 | 84,87d84 4 | < fptype OutputX; 5 | < fptype xInput; 6 | < fptype xNPrimeofX; 7 | < fptype expValues; 8 | 89,92d85 9 | < fptype xK2_2, xK2_3; 10 | < fptype xK2_4, xK2_5; 11 | < fptype xLocal, xLocal_1; 12 | < fptype xLocal_2, xLocal_3; 13 | 96,129c89,95 14 | < InputX = -InputX; 15 | < sign = 1; 16 | < } else 17 | < sign = 0; 18 | < 19 | < xInput = InputX; 20 | < 21 | < // Compute NPrimeX term common to both four & six decimal accuracy calcs 22 | < expValues = exp(-0.5f * InputX * InputX); 23 | < xNPrimeofX = expValues; 24 | < xNPrimeofX = xNPrimeofX * inv_sqrt_2xPI; 25 | < 26 | < xK2 = 0.2316419 * xInput; 27 | < xK2 = 1.0 + xK2; 28 | < xK2 = 1.0 / xK2; 29 | < xK2_2 = xK2 * xK2; 30 | < xK2_3 = xK2_2 * xK2; 31 | < xK2_4 = xK2_3 * xK2; 32 | < xK2_5 = xK2_4 * xK2; 33 | < 34 | < xLocal_1 = xK2 * 0.319381530; 35 | < xLocal_2 = xK2_2 * (-0.356563782); 36 | < xLocal_3 = xK2_3 * 1.781477937; 37 | < xLocal_2 = xLocal_2 + xLocal_3; 38 | < xLocal_3 = xK2_4 * (-1.821255978); 39 | < xLocal_2 = xLocal_2 + xLocal_3; 40 | < xLocal_3 = xK2_5 * 1.330274429; 41 | < xLocal_2 = xLocal_2 + xLocal_3; 42 | < 43 | < xLocal_1 = xLocal_2 + xLocal_1; 44 | < xLocal = xLocal_1 * xNPrimeofX; 45 | < xLocal = 1.0 - xLocal; 46 | < 47 | < OutputX = xLocal; 48 | --- 49 | > InputX = -InputX; 50 | > sign = 1; 51 | > } else { 52 | > sign = 0; 53 | > } 54 | > 55 | > xK2 = 1.0 / (1.0 + 0.2316419 * InputX); 56 | 132c98,100 57 | < OutputX = 1.0 - OutputX; 58 | --- 59 | > return (0.319381530*xK2 - 0.356563782*xK2*xK2 + 1.781477937*xK2*xK2*xK2 - 1.821255978*xK2*xK2*xK2*xK2 + 1.330274429*xK2*xK2*xK2*xK2*xK2) * exp(-0.5f * InputX * InputX) * inv_sqrt_2xPI; 60 | > } else { 61 | > return 1.0 - (0.319381530*xK2 - 0.356563782*xK2*xK2 + 1.781477937*xK2*xK2*xK2 - 1.821255978*xK2*xK2*xK2*xK2 + 1.330274429*xK2*xK2*xK2*xK2*xK2) * exp(-0.5f * InputX * InputX) * inv_sqrt_2xPI; 62 | 134,135d101 63 | < 64 | < return OutputX; 65 | 151,152d116 66 | < fptype OptionPrice; 67 | < 68 | 154,162d117 69 | < fptype xStockPrice; 70 | < fptype xStrikePrice; 71 | < fptype xRiskFreeRate; 72 | < fptype xVolatility; 73 | < fptype xTime; 74 | < fptype xSqrtTime; 75 | < 76 | < fptype logValues; 77 | < fptype xLogTerm; 78 | 165,178c120 79 | < fptype xPowerTerm; 80 | < fptype xDen; 81 | < fptype d1; 82 | < fptype d2; 83 | < fptype FutureValueX; 84 | < fptype NofXd1; 85 | < fptype NofXd2; 86 | < fptype NegNofXd1; 87 | < fptype NegNofXd2; 88 | < 89 | < xStockPrice = sptprice; 90 | < xStrikePrice = strike; 91 | < xRiskFreeRate = rate; 92 | < xVolatility = volatility; 93 | --- 94 | > fptype xDen; 95 | 180,181c122 96 | < xTime = time; 97 | < xSqrtTime = sqrt(xTime); 98 | --- 99 | > xD1 = (rate + volatility * volatility * 0.5) * time + log( sptprice / strike ); 100 | 183,195c124 101 | < logValues = log( sptprice / strike ); 102 | < 103 | < xLogTerm = logValues; 104 | < 105 | < 106 | < xPowerTerm = xVolatility * xVolatility; 107 | < xPowerTerm = xPowerTerm * 0.5; 108 | < 109 | < xD1 = xRiskFreeRate + xPowerTerm; 110 | < xD1 = xD1 * xTime; 111 | < xD1 = xD1 + xLogTerm; 112 | < 113 | < xDen = xVolatility * xSqrtTime; 114 | --- 115 | > xDen = volatility * sqrt(time); 116 | 198,205c127 117 | < 118 | < d1 = xD1; 119 | < d2 = xD2; 120 | < 121 | < NofXd1 = CNDF( d1 ); 122 | < NofXd2 = CNDF( d2 ); 123 | < 124 | < FutureValueX = strike * ( exp( -(rate)*(time) ) ); 125 | --- 126 | > 127 | 207c129 128 | < OptionPrice = (sptprice * NofXd1) - (FutureValueX * NofXd2); 129 | --- 130 | > return (sptprice * CNDF( xD1 )) - (strike * ( exp( -(rate)*(time) ) ) * CNDF( xD2 )); 131 | 209,211c131 132 | < NegNofXd1 = (1.0 - NofXd1); 133 | < NegNofXd2 = (1.0 - NofXd2); 134 | < OptionPrice = (FutureValueX * NegNofXd2) - (sptprice * NegNofXd1); 135 | --- 136 | > return (strike * ( exp( -(rate)*(time) ) ) * (1.0 - CNDF( xD1 ))) - (sptprice * (1.0 - CNDF( xD2 ))); 137 | 213,214d132 138 | < 139 | < return OptionPrice; 140 | 256a175 141 | > CAUSAL_PROGRESS; 142 | -------------------------------------------------------------------------------- /patches/dedup.patch: -------------------------------------------------------------------------------- 1 | 64,66c64,66 2 | < unsigned char* sha1name = ((CacheKey*)k)->sha1name; 3 | < for (i = 0; i < SHA1_LEN; i++) { 4 | < hash += *(((unsigned char*)sha1name) + i); 5 | --- 6 | > /*uint32_t* sha1name = ((CacheKey*)k)->sha1name;*/ unsigned char* sha1name = ((CacheKey*)k)->sha1name; 7 | > for (i = 0; /* i*4 */ i < SHA1_LEN; i++) { 8 | > /*hash ^= sha1name[i];*/ hash += *(((unsigned char*)sha1name) + i); 9 | -------------------------------------------------------------------------------- /patches/fluidanimate.patch: -------------------------------------------------------------------------------- 1 | 6a7 2 | > #include 3 | 612a614,619 4 | > /*float* dest = &cell.density[j]; 5 | > float expected = *dest; 6 | > float newval = expected + tc; 7 | > while(!__atomic_compare_exchange((uint32_t*)dest, (uint32_t*)&expected, (uint32_t*)&newval, true, __ATOMIC_RELEASE, __ATOMIC_ACQUIRE)) { 8 | > newval = expected + tc; 9 | > }*/ 10 | 621a629,634 11 | > /*float* dest = &neigh.density[iparNeigh]; 12 | > float expected = *dest; 13 | > float newval = expected + tc; 14 | > while(!__atomic_compare_exchange((uint32_t*)dest, (uint32_t*)&expected, (uint32_t*)&newval, true, __ATOMIC_RELEASE, __ATOMIC_ACQUIRE)) { 15 | > newval = expected + tc; 16 | > }*/ 17 | 783c796 18 | < 19 | --- 20 | > void wait_at_barrier() { pthread_barrier_wait(&barrier); CAUSAL_PROGRESS; } 21 | 787c800 22 | < pthread_barrier_wait(&barrier); 23 | --- 24 | > wait_at_barrier(); //pthread_barrier_wait(&barrier); 25 | 789c802 26 | < pthread_barrier_wait(&barrier); 27 | --- 28 | > wait_at_barrier(); //pthread_barrier_wait(&barrier); 29 | 791c804 30 | < pthread_barrier_wait(&barrier); 31 | --- 32 | > wait_at_barrier(); //pthread_barrier_wait(&barrier); 33 | 793c806 34 | < pthread_barrier_wait(&barrier); 35 | --- 36 | > wait_at_barrier(); //pthread_barrier_wait(&barrier); 37 | 795c808 38 | < pthread_barrier_wait(&barrier); 39 | --- 40 | > wait_at_barrier(); //pthread_barrier_wait(&barrier); 41 | 797c810 42 | < pthread_barrier_wait(&barrier); 43 | --- 44 | > wait_at_barrier(); //pthread_barrier_wait(&barrier); 45 | 799c812 46 | < pthread_barrier_wait(&barrier); 47 | --- 48 | > wait_at_barrier(); //pthread_barrier_wait(&barrier); 49 | 801c814 50 | < pthread_barrier_wait(&barrier); 51 | --- 52 | > wait_at_barrier(); //pthread_barrier_wait(&barrier); 53 | -------------------------------------------------------------------------------- /patches/streamcluster.patch: -------------------------------------------------------------------------------- 1 | 21c21 2 | < #include "parsec_barrier.hpp" 3 | --- 4 | > //#include "parsec_barrier.hpp" 5 | -------------------------------------------------------------------------------- /patches/swaptions.patch: -------------------------------------------------------------------------------- 1 | *** /home/charlie/Projects/benchmarks/parsec2.1-unmodified/pkgs/apps/swaptions/src/HJM_SimPath_Forward_Blocking.cpp 2008-11-11 15:23:28.000000000 -0500 2 | --- HJM_SimPath_Forward_Blocking.cpp 2015-03-23 12:37:56.687945058 -0400 3 | *************** 4 | *** 62,69 **** 5 | 6 | 7 | for(int l=0;l<=iFactors-1;++l){ 8 | ! for(int b=0; b"] 5 | edition = "2018" 6 | repository = "https://github.com/plasma-umass/coz" 7 | license-file = "../LICENSE.md" 8 | readme = "README.md" 9 | description = """ 10 | Rust support for the `coz` Causal Profiler: https://github.com/plasma-umass/coz 11 | """ 12 | 13 | [dependencies] 14 | libc = "0.2" 15 | once_cell = "1.1" 16 | 17 | [profile.release] 18 | debug = 1 19 | -------------------------------------------------------------------------------- /rust/README.md: -------------------------------------------------------------------------------- 1 | # coz-rs 2 | 3 | Rust support for the [`coz` Causal Profiler](https://github.com/plasma-umass/coz) 4 | 5 | [![Rust crate downloads](https://img.shields.io/crates/d/coz)](https://img.shields.io/crates/d/coz)[![Documentation](https://docs.rs/coz/badge.svg)](https://docs.rs/coz) 6 | 7 | ## Usage 8 | 9 | First, follow the instructions in [`coz`] to install the `coz` command. 10 | 11 | [`coz`]: https://github.com/plasma-umass/coz/#installation 12 | 13 | Next, `coz` is a profiler that, for the best results, typically requires 14 | source-level modifications of your code. To do this first add this to your 15 | `Cargo.toml` 16 | 17 | ```toml 18 | [dependencies] 19 | coz = "0.1" 20 | ``` 21 | 22 | Then you'll want to either add throughput or latency tracepoints. More 23 | information on this [can be found 24 | upstream](https://github.com/plasma-umass/coz/#profiling-modes). If you have 25 | something you'd wish would execute more often, you can add: 26 | 27 | ```rust 28 | fn main() { 29 | loop { 30 | // ... 31 | 32 | // For example you wish this `loop` executed more iterations 33 | coz::progress!(); // equivalent of `COZ_PROGRESS` 34 | } 35 | } 36 | ``` 37 | 38 | Note that `coz::progress!("name")` is the equivalent of `COZ_PROGRESS_NAMED` as 39 | well. 40 | 41 | If you'd like to profile the latency of an operation you can instead use: 42 | 43 | ```rust 44 | // Boy I wish this function executed more quickly... 45 | fn foo() { 46 | coz::scope!("foo"); 47 | } 48 | ``` 49 | 50 | Instead of `scope!` you may also use `coz::begin!("foo"); ... coz::end!("foo");`. 51 | 52 | After you've instrumented your code, you need to also ensure that you're 53 | compiling with DWARF debug information. To do this you'll want to configure 54 | `Cargo.toml` again: 55 | 56 | ```toml 57 | [profile.release] 58 | debug = 1 59 | ``` 60 | 61 | Next up you'll build your application with `cargo build --release`, and then 62 | finally you can run it with `coz run --- ./target/release/$your_binary`. 63 | 64 | ## Caveats 65 | 66 | Known caveats so far to generate a report that collects information are: 67 | 68 | * Debug information looks to be critical to get a report from `coz`. Make sure 69 | that your program is compiled with at least line-table information (`debug = 70 | 1`) to ensure you get the best experience using `coz`. 71 | 72 | * Currently `coz` only works on Linux, and while this crate should compile on 73 | all platforms it only actually does something on Linux. 74 | 75 | ## Examples 76 | 77 | You can find an example toy program at `rust/examples/toy.rs` in this repository, and we can execute it with `coz`: 78 | 79 | NOTE: If Rust is not yet installed, first run `sudo apt install curl` and then `curl --proto '=https' --tlsv1.3 https://sh.rustup.rs -sSf | sh`. 80 | 81 | ``` 82 | $ cargo build --release --examples 83 | $ coz run --- ./target/release/examples/toy 84 | ... 85 | [profiler.cpp:75] Starting profiler thread 86 | $ 87 | ``` 88 | 89 | That should generate `profile.coz` in the current directory, which if you plot with `coz plot` should look something like this: 90 | 91 | ![plot of `toy.rs`](toy.png) 92 | 93 | -------------------------------------------------------------------------------- /rust/examples/toy.rs: -------------------------------------------------------------------------------- 1 | const A: usize = 2_000_000_000; 2 | const B: usize = (A as f64 * 1.2) as usize; 3 | 4 | fn main() { 5 | let a = std::thread::spawn(move || { 6 | for _ in 0..A { 7 | coz::progress!("a"); 8 | } 9 | }); 10 | let b = std::thread::spawn(move || { 11 | for _ in 0..B { 12 | coz::progress!("b"); 13 | } 14 | }); 15 | a.join().unwrap(); 16 | b.join().unwrap(); 17 | } 18 | -------------------------------------------------------------------------------- /rust/src/lib.rs: -------------------------------------------------------------------------------- 1 | //! Rust support for the `coz` Causal Profiler 2 | //! 3 | //! This crate is a translation of the `coz.h` header file provided by `coz` to 4 | //! Rust, and enables profiling Rust programs with `coz` to profile throughput 5 | //! and latency. 6 | //! 7 | //! For usage information, consult the [`README.md` for the `coz` 8 | //! repository][coz-readme] as well as the [`README.md` for 9 | //! `coz-rs`][rust-readme]. 10 | //! 11 | //! [coz-readme]: https://github.com/plasma-umass/coz/blob/master/README.md 12 | //! [rust-readme]: https://github.com/alexcrichton/coz-rs/blob/master/README.md 13 | 14 | use once_cell::sync::OnceCell; 15 | use std::ffi::{CStr, CString}; 16 | use std::mem; 17 | use std::sync::atomic::{AtomicUsize, Ordering::SeqCst}; 18 | 19 | /// Equivalent of the `COZ_PROGRESS` and `COZ_PROGRESS_NAMED` macros 20 | /// 21 | /// This can be executed as: 22 | /// 23 | /// ``` 24 | /// coz::progress!(); 25 | /// ``` 26 | /// 27 | /// or ... 28 | /// 29 | /// ``` 30 | /// coz::progress!("my unique name"); 31 | /// ``` 32 | #[macro_export] 33 | macro_rules! progress { 34 | () => {{ 35 | static COUNTER: $crate::Counter = $crate::Counter::progress(concat!(file!(), ":", line!())); 36 | COUNTER.increment(); 37 | }}; 38 | ($name:expr) => {{ 39 | static COUNTER: $crate::Counter = $crate::Counter::progress($name); 40 | COUNTER.increment(); 41 | }}; 42 | } 43 | 44 | /// Equivalent of the `COZ_BEGIN` macro 45 | /// 46 | /// This can be executed as: 47 | /// 48 | /// ``` 49 | /// coz::begin!("foo"); 50 | /// ``` 51 | #[macro_export] 52 | macro_rules! begin { 53 | ($name:expr) => {{ 54 | static COUNTER: $crate::Counter = $crate::Counter::begin($name); 55 | COUNTER.increment(); 56 | }}; 57 | } 58 | 59 | /// Equivalent of the `COZ_END` macro 60 | /// 61 | /// This can be executed as: 62 | /// 63 | /// ``` 64 | /// coz::end!("foo"); 65 | /// ``` 66 | #[macro_export] 67 | macro_rules! end { 68 | ($name:expr) => {{ 69 | static COUNTER: $crate::Counter = $crate::Counter::end($name); 70 | COUNTER.increment(); 71 | }}; 72 | } 73 | 74 | /// Marks a lexical scope with `coz::begin!` and `coz::end!` which are executed 75 | /// even on early exit (e.g. via `return`, `?` or `panic!`). 76 | /// 77 | /// Where this macro is invoked is where a `begin` counter is placed, and then 78 | /// at the end of the lexical scope (when this macro's local variable goes out 79 | /// of scope) an `end` counter is placed. 80 | /// 81 | /// # Examples 82 | /// 83 | /// ```rust 84 | /// coz::scope!("outer"); 85 | /// { 86 | /// coz::scope!("inner"); 87 | /// } 88 | /// ``` 89 | #[macro_export] 90 | macro_rules! scope { 91 | ($name:expr) => { 92 | static BEGIN_COUNTER: $crate::Counter = $crate::Counter::begin($name); 93 | static END_COUNTER: $crate::Counter = $crate::Counter::end($name); 94 | BEGIN_COUNTER.increment(); 95 | let _coz_scope_guard = $crate::Guard::new(&END_COUNTER); 96 | }; 97 | } 98 | 99 | /// A `coz`-counter which is either intended for throughput or `begin`/`end` 100 | /// points. 101 | /// 102 | /// This is typically created by macros above via `progress!()`, `begin!()`, or 103 | /// `end!()`, but if necessary you can also create one of these manually in your 104 | /// own application for your own macros. 105 | pub struct Counter { 106 | slot: OnceCell>, 107 | ty: libc::c_int, 108 | name: &'static str, 109 | } 110 | 111 | const COZ_COUNTER_TYPE_THROUGHPUT: libc::c_int = 1; 112 | const COZ_COUNTER_TYPE_BEGIN: libc::c_int = 2; 113 | const COZ_COUNTER_TYPE_END: libc::c_int = 3; 114 | 115 | impl Counter { 116 | /// Creates a throughput coz counter with the given name. 117 | pub const fn progress(name: &'static str) -> Counter { 118 | Counter::new(COZ_COUNTER_TYPE_THROUGHPUT, name) 119 | } 120 | 121 | /// Creates a latency coz counter with the given name, used for when an 122 | /// operation begins. 123 | /// 124 | /// Note that this counter should be paired with an `end` counter of the 125 | /// same name. 126 | pub const fn begin(name: &'static str) -> Counter { 127 | Counter::new(COZ_COUNTER_TYPE_BEGIN, name) 128 | } 129 | 130 | /// Creates a latency coz counter with the given name, used for when an 131 | /// operation ends. 132 | /// 133 | /// Note that this counter should be paired with an `begin` counter of the 134 | /// same name. 135 | pub const fn end(name: &'static str) -> Counter { 136 | Counter::new(COZ_COUNTER_TYPE_END, name) 137 | } 138 | 139 | const fn new(ty: libc::c_int, name: &'static str) -> Counter { 140 | Counter { 141 | slot: OnceCell::new(), 142 | ty, 143 | name, 144 | } 145 | } 146 | 147 | /// Increment that an operation happened on this counter. 148 | /// 149 | /// For throughput counters this should be called in a location where you 150 | /// want something to happen more often. 151 | /// 152 | /// For latency-based counters this should be called before and after the 153 | /// operation you'd like to measure the latency of. 154 | pub fn increment(&self) { 155 | let counter = self.slot.get_or_init(|| self.create_counter()); 156 | if let Some(counter) = counter { 157 | assert_eq!( 158 | mem::size_of_val(&counter.count), 159 | mem::size_of::() 160 | ); 161 | counter.count.fetch_add(1, SeqCst); 162 | } 163 | } 164 | 165 | fn create_counter(&self) -> Option<&'static coz_counter_t> { 166 | let name = CString::new(self.name).unwrap(); 167 | let ptr = coz_get_counter(self.ty, &name); 168 | match ptr { 169 | // SAFETY: Pointer to counter returned by `coz_get_counter` is not null and aligned. 170 | Some(ptr) if !ptr.is_null() => Some(unsafe { &*ptr }), 171 | _ => None, 172 | } 173 | } 174 | } 175 | 176 | /// A type that increments a counter on drop. This allows us to issue the right 177 | /// coz calls to `begin` and `end` for the duration of a scope, regardless of how 178 | /// the scope was exited (e.g. by early return, `?` or panic). 179 | pub struct Guard<'t> { 180 | counter: &'t Counter, 181 | } 182 | 183 | impl<'t> Guard<'t> { 184 | pub fn new(counter: &'t Counter) -> Self { 185 | Guard { counter } 186 | } 187 | } 188 | 189 | impl<'t> Drop for Guard<'t> { 190 | fn drop(&mut self) { 191 | self.counter.increment(); 192 | } 193 | } 194 | 195 | #[repr(C)] 196 | struct coz_counter_t { 197 | count: AtomicUsize, 198 | backoff: libc::size_t, 199 | } 200 | 201 | /// The type of `_coz_get_counter` as defined in `include/coz.h` 202 | /// 203 | /// `typedef coz_counter_t* (*coz_get_counter_t)(int, const char*);` 204 | type GetCounterFn = unsafe extern "C" fn(libc::c_int, *const libc::c_char) -> *mut coz_counter_t; 205 | 206 | #[cfg(target_os = "linux")] 207 | fn coz_get_counter(ty: libc::c_int, name: &CStr) -> Option<*mut coz_counter_t> { 208 | static GET_COUNTER: OnceCell> = OnceCell::new(); 209 | let func = GET_COUNTER.get_or_init(|| { 210 | let name = CStr::from_bytes_with_nul(b"_coz_get_counter\0").unwrap(); 211 | // SAFETY: We are calling an external function that does exist in Linux. 212 | // No specific invariants that we must uphold have been defined. 213 | let func = unsafe { libc::dlsym(libc::RTLD_DEFAULT, name.as_ptr()) }; 214 | if func.is_null() { 215 | None 216 | } else { 217 | // SAFETY: If the pointer returned by dlsym is not null it is a valid pointer to the function 218 | // identified by the provided symbol. The type of `_coz_get_counter` is defined in `include/coz.h` 219 | // as [GetCounterFn]. 220 | Some(unsafe { mem::transmute(func) }) 221 | } 222 | }); 223 | 224 | // SAFETY: We are calling an external function which exists as it is not None 225 | // No specific invariants that we must uphold have been defined. 226 | func.map(|f| unsafe { f(ty, name.as_ptr()) }) 227 | } 228 | 229 | #[cfg(not(target_os = "linux"))] 230 | fn coz_get_counter(_ty: libc::c_int, _name: &CStr) -> Option<*mut coz_counter_t> { 231 | None 232 | } 233 | -------------------------------------------------------------------------------- /rust/tests/smoke.rs: -------------------------------------------------------------------------------- 1 | #[test] 2 | fn smoke() { 3 | coz::progress!(); 4 | coz::progress!("foo"); 5 | coz::begin!("foo"); 6 | coz::end!("foo"); 7 | } 8 | 9 | #[test] 10 | fn smoke_scoped() { 11 | coz::scope!("scope"); 12 | let mut x = 1u32; 13 | x = x + 1; 14 | assert!(x == 2); 15 | } 16 | -------------------------------------------------------------------------------- /rust/toy.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/plasma-umass/coz/3d711c847ee9c3da9ceb9cc9acc7e43c82d53b18/rust/toy.png -------------------------------------------------------------------------------- /viewer/Makefile: -------------------------------------------------------------------------------- 1 | ROOT := .. 2 | 3 | include $(ROOT)/common.mk 4 | 5 | all:: js/ui.js 6 | 7 | js/ui.js: $(wildcard ts/*.ts) tsconfig.json 8 | @echo $(LOG_PREFIX) Building profile viewer $(LOG_SUFFIX) 9 | @npm install > /dev/null 10 | -------------------------------------------------------------------------------- /viewer/README.md: -------------------------------------------------------------------------------- 1 | # Causal Profile Viewer 2 | 3 | Prerequisites for building: 4 | 5 | * Install NodeJS. 6 | 7 | To build, run `npm install`. 8 | 9 | To use, simply run an HTTP server from the directory. For example: 10 | 11 | 1. Install `http-server`: `npm i -g http-server` 12 | 2. Run `http-server` in this directory 13 | 3. Open a browser to `http://localhost:8080/` 14 | 15 | -------------------------------------------------------------------------------- /viewer/css/plot.css: -------------------------------------------------------------------------------- 1 | 2 | div.plot { 3 | position: absolute; 4 | } 5 | 6 | div.plot-title { 7 | overflow: hidden; 8 | text-overflow: ellipsis; 9 | font-size: 12px; 10 | text-align: center; 11 | white-space: nowrap; 12 | margin: 0.75em 0 0 0; 13 | font-weight: bold; 14 | color: black; 15 | z-index: 0; 16 | } 17 | 18 | div.plot-message { 19 | color: #EEE; 20 | 21 | } 22 | 23 | .xaxis path, 24 | .xaxis line, 25 | .yaxis path, 26 | .yaxis line { 27 | fill: none; 28 | stroke: #ddd; 29 | stroke-width: 1; 30 | shape-rendering: crispEdges; 31 | } 32 | 33 | .xaxis text, 34 | .yaxis text { 35 | font-family: sans-serif; 36 | font-size: 11px; 37 | } 38 | 39 | .xaxis path.domain, 40 | .yaxis path.domain { 41 | stroke-width: 0; 42 | } 43 | 44 | text.xtitle, 45 | text.ytitle { 46 | font-family: sans-serif; 47 | font-size: 12px; 48 | } 49 | 50 | .xgrid .tick, 51 | .ygrid .tick { 52 | stroke: #ddd; 53 | stroke-width: 1; 54 | shape-rendering: crispEdges; 55 | } 56 | 57 | line.xzero, 58 | line.yzero { 59 | fill: none; 60 | stroke: #888; 61 | stroke-width: 1; 62 | shape-rendering: crispEdges; 63 | } 64 | 65 | .series circle { 66 | stroke: none; 67 | } 68 | 69 | .series path { 70 | stroke-width: 2; 71 | fill: none; 72 | } 73 | 74 | .series circle.highlight { 75 | fill: white; 76 | stroke-width: 2; 77 | } 78 | 79 | /* Series colors from colorbrewer.org */ 80 | .series0 circle { fill: rgba(31,120,180,1); } 81 | .series0 path { stroke: rgba(31,120,180,0.75); } 82 | .series0 circle.highlight { stroke: rgba(31,120,180,1); } 83 | i.series0 { color: rgba(31,120,180,1); } 84 | 85 | .series1 circle { fill: rgba(51,160,44,1); } 86 | .series1 path { stroke: rgba(51,160,44,0.75); } 87 | .series1 circle.highlight { stroke: rgba(51,160,44,1); } 88 | i.series1 { color: rgba(51,160,44,1); } 89 | 90 | .series2 circle { fill: rgba(227,26,28,1); } 91 | .series2 path { stroke: rgba(227,26,28,0.75); } 92 | .series2 circle.highlight { stroke: rgba(227,26,28,1); } 93 | i.series2 { color: rgba(227,26,28,1); } 94 | 95 | .series3 circle { fill: rgba(255,127,0,1); } 96 | .series3 path { stroke: rgba(255,127,0,0.75); } 97 | .series3 circle.highlight { stroke: rgba(255,127,0,1); } 98 | i.series3 { color: rgba(255,127,0,1); } 99 | 100 | .series4 circle { fill: rgba(106,61,154,1); } 101 | .series4 path { stroke: rgba(106,61,154,0.75); } 102 | .series4 circle.highlight { stroke: rgba(106,61,154,1); } 103 | i.series4 { color: rgba(106,61,154,1); } 104 | 105 | /* Additional legend styles */ 106 | p.legend-entry i { 107 | margin-right: 0.5em; 108 | } 109 | 110 | p.noseries { color: gray; } 111 | 112 | /* Tooltips displayed on points */ 113 | .d3-tip { 114 | font-size: 12px; 115 | padding: 6px; 116 | background: rgba(0, 0, 0, 0.8); 117 | color: #fff; 118 | border-radius: 3px; 119 | z-index: 100; 120 | } 121 | -------------------------------------------------------------------------------- /viewer/css/ui.css: -------------------------------------------------------------------------------- 1 | /* Reduce heading sizes */ 2 | h1 { font-size: 2.0em; } 3 | h2 { font-size: 1.8em; } 4 | h3 { font-size: 1.5em; } 5 | 6 | /* Show sidebar on left up to bootstrap md size */ 7 | @media (min-width: 768px) { 8 | .sidebar { 9 | position: fixed; 10 | top: 0; 11 | bottom: 0; 12 | left: 0; 13 | z-index: 50; 14 | display: block; 15 | overflow-x: hidden; 16 | overflow-y: auto; 17 | background-color: #f5f5f5; 18 | border-right: 1px solid #eee; 19 | } 20 | } 21 | 22 | /* Margin on sidebar headings */ 23 | .sidebar h4 { 24 | margin-top: 1em; 25 | } 26 | 27 | /* Padding around sample profile buttons */ 28 | button.sample-profile { 29 | margin: 0.5em; 30 | } 31 | 32 | /* Use larger, styled slider for mobile devices */ 33 | @media (max-width: 767px) { 34 | input[type=range] { 35 | -webkit-appearance: none; 36 | margin: 10px 0; 37 | width: 100%; 38 | } 39 | 40 | input[type=range]:focus { 41 | outline: none; 42 | } 43 | 44 | input[type=range]::-webkit-slider-thumb { 45 | -webkit-appearance: none; 46 | width: 24px; 47 | height: 24px; 48 | border-radius: 50%; 49 | background: #f8f8f8; 50 | border: 0.5px solid #010101; 51 | box-shadow: 1px 1px 1px #000000, 0px 0px 0.5px #0d0d0d; 52 | margin-top: -9px; 53 | } 54 | 55 | input[type=range]::-webkit-slider-runnable-track { 56 | width: 100%; 57 | height: 6px; 58 | cursor: pointer; 59 | background: #444; 60 | border-radius: 3px; 61 | } 62 | } -------------------------------------------------------------------------------- /viewer/index.htm: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | coz plot 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 |
17 |
18 | 54 | 55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |

Getting Started

63 |

64 | Welcome to the causal profile viewer. To make use of this profile viewer you'll first need a causal profile. You will need to use the coz program to collect a causal profile from your program. For this to work, you will need to add at least one progress point to your program, and then build it with debug information. Next, run your program with coz: 65 |

66 |
 67 | $ coz run --- ./myprogram arg1 arg2
 68 | 
69 |

70 | Next, you will need to load your profile into this viewer. Click the Load Profile button on this page and browse to your file. There are some sample profiles available as well if you want to see what a causal profile looks like. 71 |

72 |
73 |
74 |
75 |
76 | 77 |
78 |
79 | 80 | 81 | 109 | 110 | 111 | 112 | 113 | 114 | 115 | 116 | 117 | 118 | 119 | 120 | 121 | 122 | 123 | -------------------------------------------------------------------------------- /viewer/js/ui.js: -------------------------------------------------------------------------------- 1 | // Ensure the brower supports the File API 2 | if (!window.File || !window.FileReader) { 3 | alert('The File APIs are not fully supported in this browser.'); 4 | } 5 | var current_profile = undefined; 6 | function get_min_points() { 7 | return d3.select('#minpoints_field').node().value; 8 | } 9 | // Returns the minimum number of path parts to include starting from the 10 | // end of the path, in order for the resulting string to be unique. 11 | function get_minimum_parts_for_unique_path(paths) { 12 | if (paths.length <= 1) { 13 | return 1; 14 | } 15 | var minimum = 1; 16 | var shortest_parts = Infinity; 17 | var is_unique = false; 18 | // Remove line numbers from paths 19 | paths = paths.map(function (path) { return path.replace(/:[0-9]*/, ''); }); 20 | // Remove duplicate fully qualified path names 21 | paths = remove_duplicates(paths); 22 | // Special case: all of the paths are the same file. In that case, then we 23 | // only need to return the file name. 24 | var all_identical_paths = paths.every(function (path) { return path == paths[0]; }); 25 | if (all_identical_paths) { 26 | return 1; 27 | } 28 | while (true) { 29 | var trimmed_paths = paths 30 | .map(function (path) { 31 | var parts = path.split('/'); 32 | shortest_parts = Math.min(shortest_parts, parts.length); 33 | return parts.slice(parts.length - minimum, parts.length).join('/'); 34 | }); 35 | is_unique = !has_duplicates(trimmed_paths); 36 | if (is_unique) { 37 | return minimum; 38 | } 39 | else if (minimum >= shortest_parts) { 40 | // We can't possibly return a minimum parts needed that is greater than 41 | // the smallest parts possible 42 | return shortest_parts; 43 | } 44 | else { 45 | minimum += 1; 46 | } 47 | } 48 | } 49 | // Returns the last number of parts of a slash-separated path. 50 | function get_last_path_parts(num_parts, path) { 51 | // Just return the path if it does not have any slash-separated parts 52 | if (path.indexOf('/') === -1) { 53 | return path; 54 | } 55 | var parts = path.split('/'); 56 | return parts.slice(parts.length - num_parts, parts.length).join('/'); 57 | } 58 | // This could be made simpler by using ES2015 Set instead. 59 | function has_duplicates(array) { 60 | var seen = Object.create(null); 61 | for (var _i = 0, array_1 = array; _i < array_1.length; _i++) { 62 | var value = array_1[_i]; 63 | if (value in seen) { 64 | return true; 65 | } 66 | seen[value] = true; 67 | } 68 | return false; 69 | } 70 | function remove_duplicates(array) { 71 | var uniq = {}; 72 | for (var _i = 0, array_2 = array; _i < array_2.length; _i++) { 73 | var value = array_2[_i]; 74 | uniq[value + '::' + typeof value] = value; 75 | } 76 | return Object.keys(uniq).map(function (key) { return uniq[key]; }); 77 | } 78 | function display_warning(title, text) { 79 | var warning = $("
\n \n " + title + ": " + text + "\n
"); 80 | $('#warning-area').append(warning); 81 | // Fade out after 5 seconds. 82 | setTimeout(function () { 83 | warning.fadeOut(500, function () { 84 | warning.alert('close'); 85 | }); 86 | }, 5000); 87 | } 88 | function update(resize) { 89 | if (current_profile === undefined) 90 | return; 91 | // Enable the sortby field 92 | d3.select('#sortby_field').attr('disabled', null); 93 | // Draw plots 94 | var num_plots = current_profile.drawPlots(resize); 95 | // Clear the message area 96 | d3.select('#plot-message').text(''); 97 | // Display a warning if there are no plots 98 | if (num_plots == 0) { 99 | d3.select('#plot-message').html('

No Data to Plot

Your profile does not contain enough observations to generate any plots. Try reducing the minimum number of points required to show a plot using the slider, or run your program for a longer time to collect more data.

'); 100 | } 101 | // Draw the legend 102 | current_profile.drawLegend(); 103 | var tooltip = d3.select("body") 104 | .append("div") 105 | .style("position", "absolute") 106 | .style("z-index", "10") 107 | .style("visibility", "hidden"); 108 | var all_paths = []; 109 | // Collect all of the paths that we have, in order to calculate what the 110 | // common path prefix is among all of the paths. 111 | d3.selectAll('.path').text(function (path) { 112 | // Filter out any paths which do not contain slash-separated parts 113 | if (path.indexOf('/') !== -1) { 114 | all_paths.push(path); 115 | } 116 | return path; 117 | }); 118 | var minimum_parts = get_minimum_parts_for_unique_path(all_paths); 119 | // Shorten path strings 120 | var paths = d3.selectAll('.path') 121 | .classed('path', false).classed('shortpath', true) 122 | .text(function (path) { return get_last_path_parts(minimum_parts, path); }) 123 | .attr('title', function (datum, index, outerIndex) { 124 | return datum; 125 | }); 126 | } 127 | // Set a handler for the load profile button 128 | d3.select('#load-profile-btn').on('click', function () { 129 | // Reset the filename field 130 | d3.select('#load-profile-filename').attr('value', ''); 131 | // Disable the open button 132 | d3.select('#load-profile-open-btn').classed('disabled', true); 133 | }); 134 | // Set a handler for the fake browse button 135 | d3.select('#load-profile-browse-btn').on('click', function () { 136 | $('#load-profile-file').trigger('click'); 137 | }); 138 | // Set a handler for file selection 139 | d3.select('#load-profile-file').on('change', function () { 140 | var file_browser = this; 141 | var open_button = d3.select('#load-profile-open-btn'); 142 | d3.select('#load-profile-filename').attr('value', file_browser.value.replace(/C:\\fakepath\\/i, '')); 143 | open_button.classed('disabled', false) 144 | .on('click', function () { 145 | var reader = new FileReader(); 146 | reader.onload = function (event) { 147 | var contents = event.target.result; 148 | current_profile = new Profile(contents, d3.select('#plot-area'), d3.select('#legend'), get_min_points, display_warning); 149 | update(); 150 | }; 151 | reader.onerror = function (event) { 152 | console.error("Unable to read file. Error code: " + event.target.error.code); 153 | }; 154 | // Read the profile 155 | reader.readAsText(file_browser.files[0]); 156 | // Clear the file browser value 157 | file_browser.value = ''; 158 | }); 159 | }); 160 | // Update the plots and minpoints display when dragged or clicked 161 | d3.select('#minpoints_field').on('input', function () { 162 | d3.select('#minpoints_display').text(this.value); 163 | update(); 164 | }); 165 | d3.select('#sortby_field').on('change', update); 166 | d3.select(window).on('resize', function () { update(true); }); 167 | var sample_profiles = ['blackscholes', 'dedup', 'ferret', 'fluidanimate', 'sqlite', 'swaptions']; 168 | var sample_profile_objects = {}; 169 | var samples_sel = d3.select('#samples').selectAll('.sample-profile').data(sample_profiles) 170 | .enter().append('button') 171 | .attr('class', 'btn btn-sm btn-default sample-profile') 172 | .attr('data-dismiss', 'modal') 173 | .attr('loaded', 'no') 174 | .text(function (d) { return d; }) 175 | .on('click', function (d) { 176 | var sel = d3.select(this); 177 | if (sel.attr('loaded') !== 'yes') { 178 | // Avoid race condition: Set first. 179 | sel.attr('loaded', 'yes'); 180 | var xhr_1 = new XMLHttpRequest(); 181 | xhr_1.open('GET', "profiles/" + d + ".coz"); 182 | xhr_1.onload = function () { 183 | current_profile = sample_profile_objects[d] = 184 | new Profile(xhr_1.responseText, d3.select('#plot-area'), d3.select('#legend'), get_min_points, display_warning); 185 | update(); 186 | }; 187 | xhr_1.onerror = function () { 188 | sel.attr('loaded', 'no'); 189 | display_warning("Error", "Failed to load profile for " + d + "."); 190 | }; 191 | xhr_1.send(); 192 | } 193 | else { 194 | current_profile = sample_profile_objects[d]; 195 | update(); 196 | } 197 | }); 198 | //# sourceMappingURL=ui.js.map -------------------------------------------------------------------------------- /viewer/js/ui.js.map: -------------------------------------------------------------------------------- 1 | {"version":3,"file":"ui.js","sourceRoot":"","sources":["../ts/ui.ts"],"names":[],"mappings":"AAAA,0CAA0C;AAC1C,IAAI,CAAQ,MAAO,CAAC,IAAI,IAAI,CAAQ,MAAO,CAAC,UAAU,EAAE;IACtD,KAAK,CAAC,wDAAwD,CAAC,CAAC;CACjE;AAED,IAAI,eAAe,GAAY,SAAS,CAAC;AAEzC,SAAS,cAAc;IACrB,OAAc,EAAE,CAAC,MAAM,CAAC,kBAAkB,CAAC,CAAC,IAAI,EAAG,CAAC,KAAK,CAAC;AAC5D,CAAC;AAED,wEAAwE;AACxE,mEAAmE;AACnE,SAAS,iCAAiC,CAAC,KAAe;IACxD,IAAI,KAAK,CAAC,MAAM,IAAI,CAAC,EAAE;QACrB,OAAO,CAAC,CAAC;KACV;IAED,IAAI,OAAO,GAAG,CAAC,CAAC;IAChB,IAAI,cAAc,GAAG,QAAQ,CAAC;IAC9B,IAAI,SAAS,GAAG,KAAK,CAAC;IAEtB,iCAAiC;IACjC,KAAK,GAAG,KAAK,CAAC,GAAG,CAAC,UAAA,IAAI,IAAI,OAAA,IAAI,CAAC,OAAO,CAAC,SAAS,EAAE,EAAE,CAAC,EAA3B,CAA2B,CAAC,CAAC;IAEvD,8CAA8C;IAC9C,KAAK,GAAG,iBAAiB,CAAC,KAAK,CAAC,CAAC;IAEjC,0EAA0E;IAC1E,qCAAqC;IACrC,IAAM,mBAAmB,GAAG,KAAK,CAAC,KAAK,CAAC,UAAA,IAAI,IAAI,OAAA,IAAI,IAAI,KAAK,CAAC,CAAC,CAAC,EAAhB,CAAgB,CAAC,CAAC;IAClE,IAAI,mBAAmB,EAAE;QACvB,OAAO,CAAC,CAAC;KACV;IAED,OAAO,IAAI,EAAE;QACX,IAAM,aAAa,GAAG,KAAK;aACxB,GAAG,CAAC,UAAA,IAAI;YACP,IAAM,KAAK,GAAa,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;YACxC,cAAc,GAAG,IAAI,CAAC,GAAG,CAAC,cAAc,EAAE,KAAK,CAAC,MAAM,CAAC,CAAC;YACxD,OAAO,KAAK,CAAC,KAAK,CAAC,KAAK,CAAC,MAAM,GAAG,OAAO,EAAE,KAAK,CAAC,MAAM,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;QACrE,CAAC,CAAC,CAAA;QAEJ,SAAS,GAAG,CAAC,cAAc,CAAC,aAAa,CAAC,CAAC;QAE3C,IAAI,SAAS,EAAE;YACb,OAAO,OAAO,CAAC;SAChB;aAAM,IAAI,OAAO,IAAI,cAAc,EAAE;YACpC,uEAAuE;YACvE,8BAA8B;YAC9B,OAAO,cAAc,CAAC;SACvB;aAAM;YACL,OAAO,IAAI,CAAC,CAAC;SACd;KACF;AACH,CAAC;AAED,8DAA8D;AAC9D,SAAS,mBAAmB,CAAC,SAAiB,EAAE,IAAY;IAC1D,qEAAqE;IACrE,IAAI,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC,EAAE;QAC5B,OAAO,IAAI,CAAC;KACb;IACD,IAAM,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;IAC9B,OAAO,KAAK,CAAC,KAAK,CAAC,KAAK,CAAC,MAAM,GAAG,SAAS,EAAE,KAAK,CAAC,MAAM,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;AACvE,CAAC;AAED,0DAA0D;AAC1D,SAAS,cAAc,CAAC,KAAe;IACrC,IAAI,IAAI,GAAG,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC;IAC/B,KAAkB,UAAK,EAAL,eAAK,EAAL,mBAAK,EAAL,IAAK,EAAE;QAApB,IAAI,KAAK,cAAA;QACZ,IAAI,KAAK,IAAI,IAAI,EAAE;YACjB,OAAO,IAAI,CAAC;SACb;QACD,IAAI,CAAC,KAAK,CAAC,GAAG,IAAI,CAAC;KACpB;IACD,OAAO,KAAK,CAAC;AACf,CAAC;AAED,SAAS,iBAAiB,CAAC,KAAe;IACxC,IAAI,IAAI,GAA4B,EAAE,CAAC;IAEvC,KAAkB,UAAK,EAAL,eAAK,EAAL,mBAAK,EAAL,IAAK,EAAE;QAApB,IAAI,KAAK,cAAA;QACZ,IAAI,CAAC,KAAK,GAAG,IAAI,GAAG,OAAO,KAAK,CAAC,GAAG,KAAK,CAAC;KAC3C;IAED,OAAO,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,GAAG,CAAC,UAAA,GAAG,IAAI,OAAA,IAAI,CAAC,GAAG,CAAC,EAAT,CAAS,CAAC,CAAC;AACjD,CAAC;AAED,SAAS,eAAe,CAAC,KAAa,EAAE,IAAY;IAClD,IAAM,OAAO,GAAG,CAAC,CACf,uOAEY,KAAK,mBAAc,IAAI,iBAC5B,CAAC,CAAC;IACX,CAAC,CAAC,eAAe,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC;IAEnC,4BAA4B;IAC5B,UAAU,CAAC;QACT,OAAO,CAAC,OAAO,CAAC,GAAG,EAAE;YACnB,OAAO,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC;QACzB,CAAC,CAAC,CAAC;IACL,CAAC,EAAE,IAAI,CAAC,CAAC;AACX,CAAC;AAED,SAAS,MAAM,CAAC,MAAgB;IAC9B,IAAI,eAAe,KAAK,SAAS;QAAE,OAAO;IAE1C,0BAA0B;IAC1B,EAAE,CAAC,MAAM,CAAC,eAAe,CAAC,CAAC,IAAI,CAAC,UAAU,EAAE,IAAI,CAAC,CAAC;IAElD,aAAa;IACb,IAAI,SAAS,GAAG,eAAe,CAAC,SAAS,CAAC,MAAM,CAAC,CAAC;IAElD,yBAAyB;IACzB,EAAE,CAAC,MAAM,CAAC,eAAe,CAAC,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;IAEpC,0CAA0C;IAC1C,IAAI,SAAS,IAAI,CAAC,EAAE;QAClB,EAAE,CAAC,MAAM,CAAC,eAAe,CAAC,CAAC,IAAI,CAAC,yPAAyP,CAAC,CAAC;KAC5R;IAED,kBAAkB;IAClB,eAAe,CAAC,UAAU,EAAE,CAAC;IAE7B,IAAI,OAAO,GAAG,EAAE,CAAC,MAAM,CAAC,MAAM,CAAC;SAC7B,MAAM,CAAC,KAAK,CAAC;SACb,KAAK,CAAC,UAAU,EAAE,UAAU,CAAC;SAC7B,KAAK,CAAC,SAAS,EAAE,IAAI,CAAC;SACtB,KAAK,CAAC,YAAY,EAAE,QAAQ,CAAC,CAAC;IAEhC,IAAI,SAAS,GAAa,EAAE,CAAC;IAE7B,wEAAwE;IACxE,gDAAgD;IAChD,EAAE,CAAC,SAAS,CAAC,OAAO,CAAC,CAAC,IAAI,CAAC,UAAA,IAAI;QAC7B,kEAAkE;QAClE,IAAI,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC,EAAE;YAC5B,SAAS,CAAC,IAAI,CAAC,IAAI,CAAC,CAAA;SACrB;QACD,OAAO,IAAI,CAAC;IACd,CAAC,CAAC,CAAC;IAEH,IAAI,aAAa,GAAG,iCAAiC,CAAC,SAAS,CAAC,CAAC;IAEjE,uBAAuB;IACvB,IAAI,KAAK,GAAG,EAAE,CAAC,SAAS,CAAC,OAAO,CAAC;SAC9B,OAAO,CAAC,MAAM,EAAE,KAAK,CAAC,CAAC,OAAO,CAAC,WAAW,EAAE,IAAI,CAAC;SACjD,IAAI,CAAC,UAAC,IAAY,IAAK,OAAA,mBAAmB,CAAC,aAAa,EAAE,IAAI,CAAC,EAAxC,CAAwC,CAAC;SAChE,IAAI,CAAC,OAAO,EAAE,UAAC,KAAa,EAAE,KAAa,EAAE,UAAkB;QAC9D,OAAO,KAAK,CAAC;IACf,CAAC,CAAC,CAAC;AACP,CAAC;AAED,4CAA4C;AAC5C,EAAE,CAAC,MAAM,CAAC,mBAAmB,CAAC,CAAC,EAAE,CAAC,OAAO,EAAE;IACzC,2BAA2B;IAC3B,EAAE,CAAC,MAAM,CAAC,wBAAwB,CAAC,CAAC,IAAI,CAAC,OAAO,EAAE,EAAE,CAAC,CAAC;IAEtD,0BAA0B;IAC1B,EAAE,CAAC,MAAM,CAAC,wBAAwB,CAAC,CAAC,OAAO,CAAC,UAAU,EAAE,IAAI,CAAC,CAAC;AAChE,CAAC,CAAC,CAAC;AAEH,2CAA2C;AAC3C,EAAE,CAAC,MAAM,CAAC,0BAA0B,CAAC,CAAC,EAAE,CAAC,OAAO,EAAE;IAChD,CAAC,CAAC,oBAAoB,CAAC,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC;AAC3C,CAAC,CAAC,CAAC;AAEH,mCAAmC;AACnC,EAAE,CAAC,MAAM,CAAC,oBAAoB,CAAC,CAAC,EAAE,CAAC,QAAQ,EAAE;IAC3C,IAAI,YAAY,GAAG,IAAI,CAAC;IACxB,IAAI,WAAW,GAAG,EAAE,CAAC,MAAM,CAAC,wBAAwB,CAAC,CAAC;IAEtD,EAAE,CAAC,MAAM,CAAC,wBAAwB,CAAC,CAAC,IAAI,CAAC,OAAO,EAAE,YAAY,CAAC,KAAK,CAAC,OAAO,CAAC,iBAAiB,EAAE,EAAE,CAAC,CAAC,CAAC;IAErG,WAAW,CAAC,OAAO,CAAC,UAAU,EAAE,KAAK,CAAC;SACnC,EAAE,CAAC,OAAO,EAAE;QACX,IAAI,MAAM,GAAG,IAAI,UAAU,EAAE,CAAC;QAC9B,MAAM,CAAC,MAAM,GAAG,UAAS,KAAK;YAC5B,IAAI,QAAQ,GAAkB,KAAK,CAAC,MAAO,CAAC,MAAM,CAAC;YACnD,eAAe,GAAG,IAAI,OAAO,CAAC,QAAQ,EAAE,EAAE,CAAC,MAAM,CAAC,YAAY,CAAC,EAAE,EAAE,CAAC,MAAM,CAAC,SAAS,CAAC,EAAE,cAAc,EAAE,eAAe,CAAC,CAAC;YACxH,MAAM,EAAE,CAAC;QACX,CAAC,CAAC;QAEF,MAAM,CAAC,OAAO,GAAG,UAAS,KAAK;YAC7B,OAAO,CAAC,KAAK,CAAC,mCAAmC,GAAU,KAAK,CAAC,MAAO,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;QACvF,CAAC,CAAC;QAEF,mBAAmB;QACnB,MAAM,CAAC,UAAU,CAAC,YAAY,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC;QAEzC,+BAA+B;QAC/B,YAAY,CAAC,KAAK,GAAG,EAAE,CAAC;IAC1B,CAAC,CAAC,CAAC;AACP,CAAC,CAAC,CAAC;AAEH,iEAAiE;AACjE,EAAE,CAAC,MAAM,CAAC,kBAAkB,CAAC,CAAC,EAAE,CAAC,OAAO,EAAE;IACxC,EAAE,CAAC,MAAM,CAAC,oBAAoB,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;IACjD,MAAM,EAAE,CAAC;AACX,CAAC,CAAC,CAAC;AAEH,EAAE,CAAC,MAAM,CAAC,eAAe,CAAC,CAAC,EAAE,CAAC,QAAQ,EAAE,MAAM,CAAC,CAAC;AAEhD,EAAE,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,EAAE,CAAC,QAAQ,EAAE,cAAa,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;AAE7D,IAAI,eAAe,GAAG,CAAC,cAAc,EAAE,OAAO,EAAE,QAAQ,EAAE,cAAc,EAAE,QAAQ,EAAE,WAAW,CAAC,CAAC;AACjG,IAAI,sBAAsB,GAA8B,EAAE,CAAC;AAE3D,IAAI,WAAW,GAAG,EAAE,CAAC,MAAM,CAAC,UAAU,CAAC,CAAC,SAAS,CAAC,iBAAiB,CAAC,CAAC,IAAI,CAAC,eAAe,CAAC;KACvF,KAAK,EAAE,CAAC,MAAM,CAAC,QAAQ,CAAC;KACtB,IAAI,CAAC,OAAO,EAAE,uCAAuC,CAAC;KACtD,IAAI,CAAC,cAAc,EAAE,OAAO,CAAC;KAC7B,IAAI,CAAC,QAAQ,EAAE,IAAI,CAAC;KACpB,IAAI,CAAC,UAAS,CAAC,IAAI,OAAO,CAAC,CAAC,CAAC,CAAC,CAAC;KAC/B,EAAE,CAAC,OAAO,EAAE,UAAS,CAAC;IACrB,IAAI,GAAG,GAAG,EAAE,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC;IAC1B,IAAI,GAAG,CAAC,IAAI,CAAC,QAAQ,CAAC,KAAK,KAAK,EAAE;QAChC,mCAAmC;QACnC,GAAG,CAAC,IAAI,CAAC,QAAQ,EAAE,KAAK,CAAC,CAAC;QAC1B,IAAM,KAAG,GAAG,IAAI,cAAc,EAAE,CAAC;QACjC,KAAG,CAAC,IAAI,CAAC,KAAK,EAAE,cAAY,CAAC,SAAM,CAAC,CAAC;QACrC,KAAG,CAAC,MAAM,GAAG;YACX,eAAe,GAAG,sBAAsB,CAAC,CAAC,CAAC;gBACzC,IAAI,OAAO,CAAC,KAAG,CAAC,YAAY,EAAE,EAAE,CAAC,MAAM,CAAC,YAAY,CAAC,EAAE,EAAE,CAAC,MAAM,CAAC,SAAS,CAAC,EAAE,cAAc,EAAE,eAAe,CAAC,CAAC;YAChH,MAAM,EAAE,CAAC;QACX,CAAC,CAAC;QACF,KAAG,CAAC,OAAO,GAAG;YACZ,GAAG,CAAC,IAAI,CAAC,QAAQ,EAAE,IAAI,CAAC,CAAC;YACzB,eAAe,CAAC,OAAO,EAAE,gCAA8B,CAAC,MAAG,CAAC,CAAC;QAC/D,CAAC,CAAC;QACF,KAAG,CAAC,IAAI,EAAE,CAAC;KACZ;SAAM;QACL,eAAe,GAAG,sBAAsB,CAAC,CAAC,CAAC,CAAC;QAC5C,MAAM,EAAE,CAAC;KACV;AACH,CAAC,CAAC,CAAC"} -------------------------------------------------------------------------------- /viewer/lib/d3/d3-tip.min.js: -------------------------------------------------------------------------------- 1 | d3.tip=function(){function t(t){v=d(t),w=v.createSVGPoint(),document.body.appendChild(x)}function e(){return"n"}function n(){return[0,0]}function r(){return" "}function o(){var t=y();return{top:t.n.y-x.offsetHeight,left:t.n.x-x.offsetWidth/2}}function l(){var t=y();return{top:t.s.y,left:t.s.x-x.offsetWidth/2}}function s(){var t=y();return{top:t.e.y-x.offsetHeight/2,left:t.e.x}}function f(){var t=y();return{top:t.w.y-x.offsetHeight/2,left:t.w.x-x.offsetWidth}}function i(){var t=y();return{top:t.nw.y-x.offsetHeight,left:t.nw.x-x.offsetWidth}}function u(){var t=y();return{top:t.ne.y-x.offsetHeight,left:t.ne.x}}function a(){var t=y();return{top:t.sw.y,left:t.sw.x-x.offsetWidth}}function c(){var t=y();return{top:t.se.y,left:t.e.x}}function p(){var t=d3.select(document.createElement("div"));return t.style({position:"absolute",opacity:0,pointerEvents:"none",boxSizing:"border-box"}),t.node()}function d(t){return t=t.node(),"svg"==t.tagName.toLowerCase()?t:t.ownerSVGElement}function y(){var t=T||d3.event.target,e={},n=t.getScreenCTM(),r=t.getBBox(),o=r.width,l=r.height,s=r.x,f=r.y,i=document.documentElement.scrollTop||document.body.scrollTop,u=document.documentElement.scrollLeft||document.body.scrollLeft;return w.x=s+u,w.y=f+i,e.nw=w.matrixTransform(n),w.x+=o,e.ne=w.matrixTransform(n),w.y+=l,e.se=w.matrixTransform(n),w.x-=o,e.sw=w.matrixTransform(n),w.y-=l/2,e.w=w.matrixTransform(n),w.x+=o,e.e=w.matrixTransform(n),w.x-=o/2,w.y-=l/2,e.n=w.matrixTransform(n),w.y+=l,e.s=w.matrixTransform(n),e}var m=e,g=n,h=r,x=p(),v=null,w=null,T=null;t.show=function(){var e=Array.prototype.slice.call(arguments);e[e.length-1]instanceof SVGElement&&(T=e.pop());var n,r=h.apply(this,e),o=g.apply(this,e),l=m.apply(this,e),s=d3.select(x),f=0;for(s.html(r).style({opacity:1,"pointer-events":"all"});f--;)s.classed(E[f],!1);return n=b.get(l).apply(this),s.classed(l,!0).style({top:n.top+o[0]+"px",left:n.left+o[1]+"px"}),t},t.hide=function(){return nodel=d3.select(x),nodel.style({opacity:0,"pointer-events":"none"}),t},t.attr=function(e){if(arguments.length<2&&"string"==typeof e)return d3.select(x).attr(e);var n=Array.prototype.slice.call(arguments);return d3.selection.prototype.attr.apply(d3.select(x),n),t},t.style=function(e){if(arguments.length<2&&"string"==typeof e)return d3.select(x).style(e);var n=Array.prototype.slice.call(arguments);return d3.selection.prototype.style.apply(d3.select(x),n),t},t.direction=function(e){return arguments.length?(m=null==e?e:d3.functor(e),t):m},t.offset=function(e){return arguments.length?(g=null==e?e:d3.functor(e),t):g},t.html=function(e){return arguments.length?(h=null==e?e:d3.functor(e),t):h};var b=d3.map({n:o,s:l,e:s,w:f,nw:i,ne:u,sw:a,se:c}),E=b.keys();return t}; -------------------------------------------------------------------------------- /viewer/lib/font-awesome/fonts/FontAwesome.otf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/plasma-umass/coz/3d711c847ee9c3da9ceb9cc9acc7e43c82d53b18/viewer/lib/font-awesome/fonts/FontAwesome.otf -------------------------------------------------------------------------------- /viewer/lib/font-awesome/fonts/fontawesome-webfont.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/plasma-umass/coz/3d711c847ee9c3da9ceb9cc9acc7e43c82d53b18/viewer/lib/font-awesome/fonts/fontawesome-webfont.eot -------------------------------------------------------------------------------- /viewer/lib/font-awesome/fonts/fontawesome-webfont.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/plasma-umass/coz/3d711c847ee9c3da9ceb9cc9acc7e43c82d53b18/viewer/lib/font-awesome/fonts/fontawesome-webfont.ttf -------------------------------------------------------------------------------- /viewer/lib/font-awesome/fonts/fontawesome-webfont.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/plasma-umass/coz/3d711c847ee9c3da9ceb9cc9acc7e43c82d53b18/viewer/lib/font-awesome/fonts/fontawesome-webfont.woff -------------------------------------------------------------------------------- /viewer/lib/font-awesome/fonts/fontawesome-webfont.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/plasma-umass/coz/3d711c847ee9c3da9ceb9cc9acc7e43c82d53b18/viewer/lib/font-awesome/fonts/fontawesome-webfont.woff2 -------------------------------------------------------------------------------- /viewer/lib/science/LICENSE.txt: -------------------------------------------------------------------------------- 1 | Copyright (c) 2011, Jason Davies 2 | All rights reserved. 3 | 4 | Redistribution and use in source and binary forms, with or without 5 | modification, are permitted provided that the following conditions are met: 6 | 7 | * Redistributions of source code must retain the above copyright notice, this 8 | list of conditions and the following disclaimer. 9 | 10 | * Redistributions in binary form must reproduce the above copyright notice, 11 | this list of conditions and the following disclaimer in the documentation 12 | and/or other materials provided with the distribution. 13 | 14 | * The name Jason Davies may not be used to endorse or promote products 15 | derived from this software without specific prior written permission. 16 | 17 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 18 | ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 19 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 20 | DISCLAIMED. IN NO EVENT SHALL JASON DAVIES BE LIABLE FOR ANY DIRECT, INDIRECT, 21 | INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 22 | LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 23 | PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 24 | LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE 25 | OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF 26 | ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 27 | -------------------------------------------------------------------------------- /viewer/package-lock.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "coz", 3 | "version": "1.0.0", 4 | "lockfileVersion": 2, 5 | "requires": true, 6 | "packages": { 7 | "": { 8 | "name": "coz", 9 | "version": "1.0.0", 10 | "license": "BSD-2-Clause", 11 | "devDependencies": { 12 | "@types/bootstrap": "^3.3.32", 13 | "@types/d3": "^3.5.36", 14 | "@types/jquery": "^2.0.33", 15 | "typescript": "^3.5.3" 16 | } 17 | }, 18 | "node_modules/@types/bootstrap": { 19 | "version": "3.4.0", 20 | "resolved": "https://registry.npmjs.org/@types/bootstrap/-/bootstrap-3.4.0.tgz", 21 | "integrity": "sha512-LS05hVAAsX86qbHg7W+ydwBlNHrVCoFw6wEP3/uW4eYmRXl08bWmPeN/+onM+8qZTFfDgUlG/OItJI8SW972oQ==", 22 | "dev": true, 23 | "dependencies": { 24 | "@types/jquery": "*" 25 | } 26 | }, 27 | "node_modules/@types/d3": { 28 | "version": "3.5.42", 29 | "resolved": "https://registry.npmjs.org/@types/d3/-/d3-3.5.42.tgz", 30 | "integrity": "sha512-jKnkXluwSAzkvR19zjCHvLYgsWuDqpeE79NrhWrqhKqrx3sgTRqqt4SKaxSy+N7mt1J04Xy4L0/cKdfIgnjzVQ==", 31 | "dev": true 32 | }, 33 | "node_modules/@types/jquery": { 34 | "version": "2.0.54", 35 | "resolved": "https://registry.npmjs.org/@types/jquery/-/jquery-2.0.54.tgz", 36 | "integrity": "sha512-D/PomKwNkDfSKD13DEVQT/pq2TUjN54c6uB341fEZanIzkjfGe7UaFuuaLZbpEiS5j7Wk2MUHAZqZIoECw29lg==", 37 | "dev": true 38 | }, 39 | "node_modules/typescript": { 40 | "version": "3.5.3", 41 | "resolved": "https://registry.npmjs.org/typescript/-/typescript-3.5.3.tgz", 42 | "integrity": "sha512-ACzBtm/PhXBDId6a6sDJfroT2pOWt/oOnk4/dElG5G33ZL776N3Y6/6bKZJBFpd+b05F3Ct9qDjMeJmRWtE2/g==", 43 | "dev": true, 44 | "bin": { 45 | "tsc": "bin/tsc", 46 | "tsserver": "bin/tsserver" 47 | }, 48 | "engines": { 49 | "node": ">=4.2.0" 50 | } 51 | } 52 | }, 53 | "dependencies": { 54 | "@types/bootstrap": { 55 | "version": "3.4.0", 56 | "resolved": "https://registry.npmjs.org/@types/bootstrap/-/bootstrap-3.4.0.tgz", 57 | "integrity": "sha512-LS05hVAAsX86qbHg7W+ydwBlNHrVCoFw6wEP3/uW4eYmRXl08bWmPeN/+onM+8qZTFfDgUlG/OItJI8SW972oQ==", 58 | "dev": true, 59 | "requires": { 60 | "@types/jquery": "*" 61 | } 62 | }, 63 | "@types/d3": { 64 | "version": "3.5.42", 65 | "resolved": "https://registry.npmjs.org/@types/d3/-/d3-3.5.42.tgz", 66 | "integrity": "sha512-jKnkXluwSAzkvR19zjCHvLYgsWuDqpeE79NrhWrqhKqrx3sgTRqqt4SKaxSy+N7mt1J04Xy4L0/cKdfIgnjzVQ==", 67 | "dev": true 68 | }, 69 | "@types/jquery": { 70 | "version": "2.0.54", 71 | "resolved": "https://registry.npmjs.org/@types/jquery/-/jquery-2.0.54.tgz", 72 | "integrity": "sha512-D/PomKwNkDfSKD13DEVQT/pq2TUjN54c6uB341fEZanIzkjfGe7UaFuuaLZbpEiS5j7Wk2MUHAZqZIoECw29lg==", 73 | "dev": true 74 | }, 75 | "typescript": { 76 | "version": "3.5.3", 77 | "resolved": "https://registry.npmjs.org/typescript/-/typescript-3.5.3.tgz", 78 | "integrity": "sha512-ACzBtm/PhXBDId6a6sDJfroT2pOWt/oOnk4/dElG5G33ZL776N3Y6/6bKZJBFpd+b05F3Ct9qDjMeJmRWtE2/g==", 79 | "dev": true 80 | } 81 | } 82 | } 83 | -------------------------------------------------------------------------------- /viewer/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "coz", 3 | "version": "1.0.0", 4 | "description": "Displays results from a causal profile.", 5 | "repository": { 6 | "type": "git", 7 | "url": "git+https://github.com/plasma-umass/coz" 8 | }, 9 | "scripts": { 10 | "prepare": "tsc --rootDir ts --outDir js" 11 | }, 12 | "license": "BSD-2-Clause", 13 | "bugs": { 14 | "url": "https://github.com/plasma-umass/coz/issues" 15 | }, 16 | "homepage": "https://github.com/plasma-umass/coz#readme", 17 | "devDependencies": { 18 | "@types/bootstrap": "^3.3.32", 19 | "@types/d3": "^3.5.36", 20 | "@types/jquery": "^2.0.33", 21 | "typescript": "^3.5.3" 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /viewer/ts/ui.ts: -------------------------------------------------------------------------------- 1 | // Ensure the brower supports the File API 2 | if (!( window).File || !( window).FileReader) { 3 | alert('The File APIs are not fully supported in this browser.'); 4 | } 5 | 6 | let current_profile: Profile = undefined; 7 | 8 | function get_min_points(): number { 9 | return ( d3.select('#minpoints_field').node()).value; 10 | } 11 | 12 | // Returns the minimum number of path parts to include starting from the 13 | // end of the path, in order for the resulting string to be unique. 14 | function get_minimum_parts_for_unique_path(paths: string[]): number { 15 | if (paths.length <= 1) { 16 | return 1; 17 | } 18 | 19 | let minimum = 1; 20 | let shortest_parts = Infinity; 21 | let is_unique = false; 22 | 23 | // Remove line numbers from paths 24 | paths = paths.map(path => path.replace(/:[0-9]*/, '')); 25 | 26 | // Remove duplicate fully qualified path names 27 | paths = remove_duplicates(paths); 28 | 29 | // Special case: all of the paths are the same file. In that case, then we 30 | // only need to return the file name. 31 | const all_identical_paths = paths.every(path => path == paths[0]); 32 | if (all_identical_paths) { 33 | return 1; 34 | } 35 | 36 | while (true) { 37 | const trimmed_paths = paths 38 | .map(path => { 39 | const parts: string[] = path.split('/'); 40 | shortest_parts = Math.min(shortest_parts, parts.length); 41 | return parts.slice(parts.length - minimum, parts.length).join('/'); 42 | }) 43 | 44 | is_unique = !has_duplicates(trimmed_paths); 45 | 46 | if (is_unique) { 47 | return minimum; 48 | } else if (minimum >= shortest_parts) { 49 | // We can't possibly return a minimum parts needed that is greater than 50 | // the smallest parts possible 51 | return shortest_parts; 52 | } else { 53 | minimum += 1; 54 | } 55 | } 56 | } 57 | 58 | // Returns the last number of parts of a slash-separated path. 59 | function get_last_path_parts(num_parts: number, path: string) { 60 | // Just return the path if it does not have any slash-separated parts 61 | if (path.indexOf('/') === -1) { 62 | return path; 63 | } 64 | const parts = path.split('/'); 65 | return parts.slice(parts.length - num_parts, parts.length).join('/'); 66 | } 67 | 68 | // This could be made simpler by using ES2015 Set instead. 69 | function has_duplicates(array: string[]) { 70 | var seen = Object.create(null); 71 | for (let value of array) { 72 | if (value in seen) { 73 | return true; 74 | } 75 | seen[value] = true; 76 | } 77 | return false; 78 | } 79 | 80 | function remove_duplicates(array: string[]) { 81 | var uniq: {[key: string]: string} = {}; 82 | 83 | for (let value of array) { 84 | uniq[value + '::' + typeof value] = value; 85 | } 86 | 87 | return Object.keys(uniq).map(key => uniq[key]); 88 | } 89 | 90 | function display_warning(title: string, text: string): void { 91 | const warning = $( 92 | ``); 96 | $('#warning-area').append(warning); 97 | 98 | // Fade out after 5 seconds. 99 | setTimeout(() => { 100 | warning.fadeOut(500, () => { 101 | warning.alert('close'); 102 | }); 103 | }, 5000); 104 | } 105 | 106 | function update(resize?: boolean) { 107 | if (current_profile === undefined) return; 108 | 109 | // Enable the sortby field 110 | d3.select('#sortby_field').attr('disabled', null); 111 | 112 | // Draw plots 113 | let num_plots = current_profile.drawPlots(resize); 114 | 115 | // Clear the message area 116 | d3.select('#plot-message').text(''); 117 | 118 | // Display a warning if there are no plots 119 | if (num_plots == 0) { 120 | d3.select('#plot-message').html('

No Data to Plot

Your profile does not contain enough observations to generate any plots. Try reducing the minimum number of points required to show a plot using the slider, or run your program for a longer time to collect more data.

'); 121 | } 122 | 123 | // Draw the legend 124 | current_profile.drawLegend(); 125 | 126 | let tooltip = d3.select("body") 127 | .append("div") 128 | .style("position", "absolute") 129 | .style("z-index", "10") 130 | .style("visibility", "hidden"); 131 | 132 | let all_paths: string[] = []; 133 | 134 | // Collect all of the paths that we have, in order to calculate what the 135 | // common path prefix is among all of the paths. 136 | d3.selectAll('.path').text(path => { 137 | // Filter out any paths which do not contain slash-separated parts 138 | if (path.indexOf('/') !== -1) { 139 | all_paths.push(path) 140 | } 141 | return path; 142 | }); 143 | 144 | let minimum_parts = get_minimum_parts_for_unique_path(all_paths); 145 | 146 | // Shorten path strings 147 | let paths = d3.selectAll('.path') 148 | .classed('path', false).classed('shortpath', true) 149 | .text((path: string) => get_last_path_parts(minimum_parts, path)) 150 | .attr('title', (datum: string, index: number, outerIndex: number) => { 151 | return datum; 152 | }); 153 | } 154 | 155 | // Set a handler for the load profile button 156 | d3.select('#load-profile-btn').on('click', function() { 157 | // Reset the filename field 158 | d3.select('#load-profile-filename').attr('value', ''); 159 | 160 | // Disable the open button 161 | d3.select('#load-profile-open-btn').classed('disabled', true); 162 | }); 163 | 164 | // Set a handler for the fake browse button 165 | d3.select('#load-profile-browse-btn').on('click', function() { 166 | $('#load-profile-file').trigger('click'); 167 | }); 168 | 169 | // Set a handler for file selection 170 | d3.select('#load-profile-file').on('change', function() { 171 | let file_browser = this; 172 | let open_button = d3.select('#load-profile-open-btn'); 173 | 174 | d3.select('#load-profile-filename').attr('value', file_browser.value.replace(/C:\\fakepath\\/i, '')); 175 | 176 | open_button.classed('disabled', false) 177 | .on('click', function() { 178 | var reader = new FileReader(); 179 | reader.onload = function(event) { 180 | let contents: string = ( event.target).result; 181 | current_profile = new Profile(contents, d3.select('#plot-area'), d3.select('#legend'), get_min_points, display_warning); 182 | update(); 183 | }; 184 | 185 | reader.onerror = function(event) { 186 | console.error("Unable to read file. Error code: " + ( event.target).error.code); 187 | }; 188 | 189 | // Read the profile 190 | reader.readAsText(file_browser.files[0]); 191 | 192 | // Clear the file browser value 193 | file_browser.value = ''; 194 | }); 195 | }); 196 | 197 | // Update the plots and minpoints display when dragged or clicked 198 | d3.select('#minpoints_field').on('input', function() { 199 | d3.select('#minpoints_display').text(this.value); 200 | update(); 201 | }); 202 | 203 | d3.select('#sortby_field').on('change', update); 204 | 205 | d3.select(window).on('resize', function() { update(true); }); 206 | 207 | let sample_profiles = ['blackscholes', 'dedup', 'ferret', 'fluidanimate', 'sqlite', 'swaptions']; 208 | let sample_profile_objects: {[name: string]: Profile} = {}; 209 | 210 | let samples_sel = d3.select('#samples').selectAll('.sample-profile').data(sample_profiles) 211 | .enter().append('button') 212 | .attr('class', 'btn btn-sm btn-default sample-profile') 213 | .attr('data-dismiss', 'modal') 214 | .attr('loaded', 'no') 215 | .text(function(d) { return d; }) 216 | .on('click', function(d) { 217 | let sel = d3.select(this); 218 | if (sel.attr('loaded') !== 'yes') { 219 | // Avoid race condition: Set first. 220 | sel.attr('loaded', 'yes'); 221 | const xhr = new XMLHttpRequest(); 222 | xhr.open('GET', `profiles/${d}.coz`); 223 | xhr.onload = function() { 224 | current_profile = sample_profile_objects[d] = 225 | new Profile(xhr.responseText, d3.select('#plot-area'), d3.select('#legend'), get_min_points, display_warning); 226 | update(); 227 | }; 228 | xhr.onerror = function() { 229 | sel.attr('loaded', 'no'); 230 | display_warning("Error", `Failed to load profile for ${d}.`); 231 | }; 232 | xhr.send(); 233 | } else { 234 | current_profile = sample_profile_objects[d]; 235 | update(); 236 | } 237 | }); 238 | -------------------------------------------------------------------------------- /viewer/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "module": "none", 4 | "target": "es5", 5 | "noImplicitAny": true, 6 | "sourceMap": true 7 | } 8 | } 9 | --------------------------------------------------------------------------------