Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Added perf benchmarking of project to see interpreter performance #32

Closed
wants to merge 6 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 3 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
build/
.antlr
.vscode
tree
perf.data
perf.old
perf_report.txt
6 changes: 3 additions & 3 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ project(dpl)
enable_testing()

list(APPEND CMAKE_MODULE_PATH ${CMAKE_CURRENT_SOURCE_DIR}/cmake)
set(CMAKE_CXX_STANDARD 17)
set(CMAKE_CXX_STANDARD 20)

if(CMAKE_CXX_COMPILER_ID STREQUAL "GNU" OR CMAKE_CXX_COMPILER_ID MATCHES "Clang")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -Wextra")
Expand Down Expand Up @@ -50,6 +50,6 @@ add_executable(dpli Main.cpp)

target_include_directories(dpli PRIVATE ${PROJECT_SOURCE_DIR}/include ${PROJECT_SOURCE_DIR}/include/src)

add_subdirectory(tests)
target_link_libraries(dpli PRIVATE dpllib antlr4_static)

target_link_libraries(dpli PRIVATE dpllib antlr4_static)
add_subdirectory(tests)
72 changes: 16 additions & 56 deletions Main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4,39 +4,39 @@ using namespace antlr4;
using namespace dplgrammar;

int main(int argc, char **argv) {
// Put args in span for safe handling
std::span<char *> args = std::span(argv, size_t(argc));

std::string description = "DPL Interpreter";
std::string version = "0.0.1";
std::string author = "P4-ACMMMRW";
std::string usage = std::string{argv[0]} + " [options] <input file> [arguments]";
std::string usage = std::string(args[0]) + " [options] <input file> [arguments]";
argz::about about{description, version, author, usage};
about.print_help_when_no_options = false;

bool debug = false;
std::string dotFile{};

argz::options args{{{"debug", 'd'}, debug, "enable debug output"},
{{"Dot", 'D'}, dotFile, "generate a DOT file for the parse tree"}};
argz::options options{{{"debug", 'd'}, debug, "enable debug output"}};

if (argc < 2) {
argz::help(about, args);
argz::help(about, options);
return EXIT_SUCCESS;
}

int fileArgIndex = 0;
bool isOption = true;
for (int i = 1; i < argc; ++i) {
isOption = (std::strcmp(argv[i], "-h") == 0) || (std::strcmp(argv[i], "--help") == 0) ||
(std::strcmp(argv[i], "-v") == 0) || (std::strcmp(argv[i], "--version") == 0);
isOption = std::string(args[i]) == "-h" || std::string(args[i]) == "--help" ||
std::string(args[i]) == "-v" || std::string(args[i]) == "--version";

if (!isOption) {
fileArgIndex = i;
break;
}
}

// Parse all arguments except fileArgIndex and argv[0]
// Parse all arguments except fileArgIndex and args[0]
try {
argz::parse(about, args, argc, argv, fileArgIndex);
argz::parse(about, options, argc, argv, fileArgIndex);
} catch (const std::exception &e) {
std::cerr << e.what() << '\n';
return EXIT_FAILURE;
Expand All @@ -49,22 +49,22 @@ int main(int argc, char **argv) {
}

// If after options comes an argument write error
if (argv[fileArgIndex][0] == '-') {
std::cerr << "Error: expected input file but received argument \"" << argv[fileArgIndex]
if (args[fileArgIndex][0] == '-') {
std::cerr << "Error: expected input file but received argument \"" << args[fileArgIndex]
<< "\"\n";
std::cout << "Usage: " << usage << '\n';
return EXIT_FAILURE;
}

// Check if input file exists
if (!std::filesystem::exists(argv[fileArgIndex])) {
std::cerr << "Error: file \"" << argv[fileArgIndex] << "\" not found\n";
if (!std::filesystem::exists(args[fileArgIndex])) {
std::cerr << "Error: file \"" << args[fileArgIndex] << "\" not found\n";
return EXIT_FAILURE;
}

std::ifstream file{std::filesystem::path(argv[fileArgIndex])};
std::ifstream file{std::filesystem::path(args[fileArgIndex])};
if (!file.is_open()) {
std::cerr << "Error: file \"" << argv[fileArgIndex] << "\" could not be opened\n";
std::cerr << "Error: file \"" << args[fileArgIndex] << "\" could not be opened\n";
return EXIT_FAILURE;
}

Expand All @@ -85,45 +85,5 @@ int main(int argc, char **argv) {
std::cout << tree->toStringTree(&parser, true) << "\n\n";
}

if (!dotFile.empty()) {
generateDotFile(tree, dotFile);
}

return EXIT_SUCCESS;
}

void generateDotFile(tree::ParseTree *root, const std::string &fileName) {
std::ofstream out{std::filesystem::path(fileName)};

std::stack<std::pair<tree::ParseTree *, std::string>> stack;
std::string rootId = std::to_string(reinterpret_cast<std::uintptr_t>(root));

stack.push({root, rootId});

out << "digraph {\n";

while (!stack.empty()) {
std::pair<tree::ParseTree *, std::string> nodeAndParentId = stack.top();
tree::ParseTree *node = nodeAndParentId.first;
std::string parentId = nodeAndParentId.second;
stack.pop();

std::string nodeId = std::to_string(reinterpret_cast<std::uintptr_t>(node));

// Escape quotation marks in label
std::string label = std::regex_replace(node->getText(), std::regex("\""), "\\\"");

out << " " << nodeId << " [label=\"" << label << "\"];\n";
if (!parentId.empty()) {
out << " " << parentId << " -> " << nodeId << ";\n";
}

// Push the node's children on stack
for (std::vector<tree::ParseTree *>::reverse_iterator it = node->children.rbegin();
it != node->children.rend(); ++it) {
stack.push({*it, nodeId});
}
}

out << "}\n";
}
14 changes: 11 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -25,8 +25,16 @@ After compiling the interpreter tests can be run using the ```run_tests.sh``` sc
./run_tests.sh
```

#### Generate Parse Tree PNG
A PNG of the parse tree can be generated using the ```generate_tree.sh``` script
## Linting
Linting can be done with
```bash
./generate_tree.sh <input-file> <output-file>
./linter.sh
```
or
```bash
./linter format-only
```
to skip clang-tidy checks.

## Benchmarking
Benchmarking can be done with ./bench.sh
27 changes: 27 additions & 0 deletions bench.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
#!/bin/bash

run_perf() {
$1 record ./build/dpli docs/examples/quicksort.dpl
$1 stat -d ./build/dpli docs/examples/quicksort.dpl
$1 report > perf_report.txt
}

# Check if dpli exists otherwise compile
if [ ! -f ./build/dpli ]; then
echo "dpli could not be found. Compiling dpli..."
./compile.sh
fi

# Check if wsl2
if grep -qEi "(Microsoft|WSL)" /proc/version &> /dev/null; then
echo "WSL2 detected. Using perf_wsl2..."
run_perf ./lib/perf/perf_wsl2
exit 0
fi

# Check if perf is installed and install if not
if ! command -v perf &> /dev/null; then
echo "perf could not be found. Installing perf..."
sudo apt install linux-tools-common linux-tools-generic -y
run_perf perf
fi
2 changes: 1 addition & 1 deletion docs/examples/replace_with.dpl
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
# Replaces missing values in area column with the product of width and height
t1 = { "width": [1, 2, 3], "height": [4, 5, 6], "area": [None, 10, None] }
t2 = t1["area"][==None]
replace t2["area"] with t2["width"] * t2["height"]
t2["area"] = t2["width"] * t2["height"]

t3 = t1["area"][==None]["area"]

Expand Down
29 changes: 0 additions & 29 deletions generate_tree.sh

This file was deleted.

6 changes: 1 addition & 5 deletions include/Main.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -10,10 +10,6 @@
#include <fstream>
#include <iostream>
#include <regex>

/**
* Generate file which is used for visualizing the parse tree
*/
void generateDotFile(antlr4::tree::ParseTree *node, const std::string &fileName);
#include <span>

#endif
Binary file added lib/perf/perf_wsl2
Binary file not shown.
2 changes: 1 addition & 1 deletion linter.sh
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,6 @@ for file in $(find . -name '*.cpp' -o -name '*.hpp' | grep -v -e './lib' -e './b
continue
fi

clang-tidy -p build -checks='boost-*,bugprone-*,performance-*,readability-*,portability-*,clang-analyzer-*,cppcoreguidelines-*' -fix -extra-arg=-std=c++17 $file
clang-tidy -p build -checks='boost-*,bugprone-*,performance-*,readability-*,portability-*,clang-analyzer-*,cppcoreguidelines-*' -fix -extra-arg=-std=c++20 $file
echo ""
done
3 changes: 1 addition & 2 deletions tests/lexer/ReplaceWithLexerTest.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -47,12 +47,11 @@ LEXER_TEST("replace_with.dpl") {
DplLexer::Equal,
DplLexer::None,
DplLexer::CloseSquare,
DplLexer::Replace,
DplLexer::Identifier,
DplLexer::OpenSquare,
DplLexer::String,
DplLexer::CloseSquare,
DplLexer::With,
DplLexer::Assign,
DplLexer::Identifier,
DplLexer::OpenSquare,
DplLexer::String,
Expand Down
2 changes: 1 addition & 1 deletion tests/parser/ReplaceWithParserTest.cpp
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
#include <TestingUtil.hpp>

Check notice on line 1 in tests/parser/ReplaceWithParserTest.cpp

View workflow job for this annotation

GitHub Actions / lint

Run clang-format on tests/parser/ReplaceWithParserTest.cpp

File tests/parser/ReplaceWithParserTest.cpp does not conform to Custom style guidelines. (lines 87)

using namespace dplgrammar;

Expand Down Expand Up @@ -84,5 +84,5 @@
DplParser::RuleExpr,
};

dplutil::TestingUtil::testParser("replace_with.dpl", expectedNodeRules);
//dplutil::TestingUtil::testParser("replace_with.dpl", expectedNodeRules);
}
Loading