Skip to content

Commit

Permalink
scheme::known_port + ada benchmark
Browse files Browse the repository at this point in the history
  • Loading branch information
the-moisrex committed Oct 7, 2023
1 parent 36d533d commit 66f71d8
Show file tree
Hide file tree
Showing 7 changed files with 285 additions and 4 deletions.
30 changes: 30 additions & 0 deletions benchmarks/ada/Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
flags = -std=c++20 -isystem /usr/local/include -L/usr/local/lib -lpthread -lbenchmark_main -lbenchmark
optflags = -flto -Ofast -DNDEBUG -march=native
files = ada_benchmark.cpp

all: gcc
.PHONY: all

gcc: $(files)
g++ $(flags) $(optflags) $(files)

clang: $(files)
clang++ $(flags) $(optflags) $(files)

gcc-noopt: $(files)
g++ $(flags) $(files)

clang-noopt: $(files)
clang++ $(flags) $(files)

gcc-profile-generate: $(files)
g++ $(flags) $(optflags) -fprofile-generate $(files)

clang-profile-generate: $(files)
clang++ $(flags) $(optflags) -fprofile-generate $(files)

gcc-profile-use: $(files)
g++ $(flags) $(optflags) -fprofile-use $(files)

clang-profile-use: $(files)
clang++ $(flags) $(optflags) -fprofile-use $(files)
36 changes: 36 additions & 0 deletions benchmarks/ada/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
# Ada URL vs Web++'s implementation of URL

As of writing this, ada's url parser has more features than our implementation. In an effort to better our impl, we're
going to benchmark our features against theirs.


GCC:

```
2023-10-07T07:33:24-08:00
Running ./a.out
Run on (8 X 3176.74 MHz CPU s)
CPU Caches:
L1 Data 32 KiB (x4)
L1 Instruction 32 KiB (x4)
L2 Unified 256 KiB (x4)
L3 Unified 6144 KiB (x1)
Load Average: 2.37, 4.32, 4.17
----------------------------------------------------------
Benchmark Time CPU Iterations
----------------------------------------------------------
WebppSchemePort 10.6 ns 10.5 ns 70043092
AdaSchemePort 12.6 ns 12.5 ns 46552076
```

Clang:

```
2023-10-07T07:32:37-08:00
Load Average: 2.60, 4.65, 4.27
----------------------------------------------------------
Benchmark Time CPU Iterations
----------------------------------------------------------
WebppSchemePort 6.24 ns 6.23 ns 115267454
AdaSchemePort 8.74 ns 8.67 ns 83124377
```
51 changes: 51 additions & 0 deletions benchmarks/ada/ada_benchmark.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
#include "../../webpp/std/string_view.hpp"
#include "../benchmark.hpp"
#include "./ada_scheme.hpp"
#include "./webpp_scheme.hpp"

using namespace webpp;


static std::vector<std::string_view> schemes{{"one",
"two",
"three",
"http",
"five",
"https",
"https",
"ftp",
"ftps",
"wss",
"file",
"ssh",
"scheme",
"nonsense",
"",
" ",
"d;klasjfd;alsjf",
"2408372-54",
" @#$@fdsafd"}};

static void WebppSchemePort(benchmark::State& state) {
std::size_t i = 0;
for (auto _ : state) {
auto scheme = schemes[i++ % schemes.size()];
benchmark::DoNotOptimize(scheme);
auto w_scheme = webpp::v1::basic_scheme<std::string_view>{scheme};
auto port = w_scheme.known_port();
benchmark::DoNotOptimize(port);
}
}
BENCHMARK(WebppSchemePort);


static void AdaSchemePort(benchmark::State& state) {
std::size_t i = 0;
for (auto _ : state) {
auto scheme = schemes[i++ % schemes.size()];
benchmark::DoNotOptimize(scheme);
auto port = ada::scheme::get_special_port(scheme);
benchmark::DoNotOptimize(port);
}
}
BENCHMARK(AdaSchemePort);
48 changes: 48 additions & 0 deletions benchmarks/ada/ada_scheme.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
// Created by moisrex on 10/7/23.
// source of this file: ada project / scheme-inl.h

#ifndef WEBPP_ADA_SCHEME_HPP
#define WEBPP_ADA_SCHEME_HPP

#include <cstdint>
#include <string_view>

namespace ada::scheme {

/**
* @namespace ada::scheme::details
* @brief Includes the definitions for scheme specific entities
*/
namespace details {
// for use with is_special and get_special_port
// Spaces, if present, are removed from URL.
constexpr std::string_view is_special_list[] =
{"http", " ", "https", "ws", "ftp", "wss", "file", " "};
// for use with get_special_port
constexpr uint16_t special_ports[] = {80, 0, 443, 80, 21, 443, 0, 0};
} // namespace details

constexpr bool is_special(std::string_view scheme) {
if (scheme.empty()) {
return false;
}
int hash_value = (2 * scheme.size() + (unsigned) (scheme[0])) & 7;
const std::string_view target = details::is_special_list[hash_value];
return (target[0] == scheme[0]) && (target.substr(1) == scheme.substr(1));
}
constexpr uint16_t get_special_port(std::string_view scheme) noexcept {
if (scheme.empty()) {
return 0;
}
int hash_value = (2 * scheme.size() + (unsigned) (scheme[0])) & 7;
const std::string_view target = details::is_special_list[hash_value];
if ((target[0] == scheme[0]) && (target.substr(1) == scheme.substr(1))) {
return details::special_ports[hash_value];
} else {
return 0;
}
}

} // namespace ada::scheme

#endif // WEBPP_ADA_SCHEME_HPP
62 changes: 62 additions & 0 deletions benchmarks/ada/webpp_scheme.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
// Created by moisrex on 10/7/23.

#ifndef WEBPP_WEBPP_SCHEME_HPP
#define WEBPP_WEBPP_SCHEME_HPP

#include "../../webpp/std/string.hpp"
#include "../../webpp/std/string_view.hpp"

#include <cstdint>

namespace webpp::v1 {

template <typename StringType = stl::string>
requires(istl::String<StringType> || istl::StringView<StringType>)
struct basic_scheme : stl::remove_cvref_t<StringType> {
using string_type = stl::remove_cvref_t<StringType>;

template <typename... T>
constexpr basic_scheme(T&&... args) : string_type{stl::forward<T>(args)...} {}



/**
* @brief checks if the URI is a relative reference
*/
[[nodiscard]] constexpr bool is_relative_reference() const noexcept {
return this->empty();
}

/**
* @return 0 if unknown, otherwise return the port
*/
[[nodiscard]] constexpr stl::uint16_t known_port() const noexcept {
// NOLINTBEGIN(*-avoid-magic-numbers)
switch (this->size()) {
case 2:
if (this->operator[](0) == 'w' && this->operator[](1) == 's')
return 80u;
break;
case 3:
if (*this == "wss")
return 443u;
else if (*this == "ftp")
return 21;
break;
case 4:
if (*this == "http")
return 80u;
break;
case 5:
if (*this == "https")
return 443;
break;
}
return 0u;
// NOLINTEND(*-avoid-magic-numbers)
}
};

} // namespace webpp::v1

#endif // WEBPP_WEBPP_SCHEME_HPP
8 changes: 4 additions & 4 deletions webpp/http/headers/host.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -108,7 +108,7 @@ namespace webpp::http {
// first try to parse it as ipv4:
ipv4_octets octets;
auto host_ptr = hostname.data();
auto const host_end = host_ptr + hostname.size();
auto const host_end = host_ptr + hostname.size(); // NOLINT(*-pro-bounds-pointer-arithmetic)
auto const res = inet_pton4(host_ptr, host_end, octets.data());
switch (res) {
using enum inet_pton4_status;
Expand Down Expand Up @@ -304,7 +304,7 @@ namespace webpp::http {
if (port_ptr == port_end) {
return; // no port here
}
if (*port_ptr++ != ':') {
if (*port_ptr++ != ':') { // NOLINT(*-pro-bounds-pointer-arithmetic)
status_code = host_status::invalid_host;
return;
}
Expand Down Expand Up @@ -354,8 +354,8 @@ namespace webpp::http {

using endpoint_variant_type = stl::variant<stl::monostate, struct ipv4, struct ipv6, domain_type>;
endpoint_variant_type endpoint{stl::monostate{}};
stl::uint16_t port_value = 0;
host_status status_code;
stl::uint16_t port_value = 0;
host_status status_code = host_status::invalid_host;
};

} // namespace webpp::http
Expand Down
54 changes: 54 additions & 0 deletions webpp/uri/scheme.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,30 @@
#define WEBPP_SCHEME_HPP

#include "../std/string.hpp"
#include "./details/uri_status.hpp"

namespace webpp::uri {

enum struct scheme_status {
#define webpp_def(status) status = stl::to_underlying(uri::uri_status::status)
webpp_def(valid), // valid scheme
#undef webpp_def
};

/**
* Get the error message as a string view
*/
static constexpr stl::string_view to_string(scheme_status status) noexcept {
switch (status) {
using enum scheme_status;
case valid: return "Valid Scheme";
}
stl::unreachable();
}




template <istl::String StringType = stl::string>
struct basic_scheme : stl::remove_cvref_t<StringType> {
using string_type = stl::remove_cvref_t<StringType>;
Expand All @@ -23,6 +44,39 @@ namespace webpp::uri {
return this->empty();
}

/**
* @return 0 if unknown, otherwise return the port
*/
[[nodiscard]] constexpr stl::uint16_t known_port() const noexcept {
// NOLINTBEGIN(*-avoid-magic-numbers)
switch (this->size()) {
case 2:
if (this->operator[](0) == 'w' && this->operator[](1) == 's')
return 80u;
break;
case 3:
if (*this == "wss")
return 443u;
else if (*this == "ftp")
return 21;
break;
case 4:
if (*this == "http")
return 80u;
break;
case 5:
if (*this == "https")
return 443;
break;
}
return 0u;
// NOLINTEND(*-avoid-magic-numbers)
}

[[nodiscard]] constexpr bool is_known() const noexcept {
return known_port() != 0u;
}

void append_to(istl::String auto& out) const {
if (!this->empty()) {
// out.reserve(out.size() + this->size() + 1);
Expand Down

0 comments on commit 66f71d8

Please sign in to comment.