v0.1.1
This commit is contained in:
parent
38359bd957
commit
d6eb46d310
53
CHANGELOG.md
53
CHANGELOG.md
|
@ -1,3 +1,56 @@
|
||||||
|
# 0.1.1 Third Pre-Release
|
||||||
|
|
||||||
|
- Add mappings for common MIME types
|
||||||
|
- Heavily improved resource utilization
|
||||||
|
- Removed non-cached file backend
|
||||||
|
- Updated dockerfile to remove build files after build
|
||||||
|
|
||||||
|
## Known Issues
|
||||||
|
|
||||||
|
- Benchmark program does not include resource utilization
|
||||||
|
|
||||||
|
## Benchmark Results
|
||||||
|
|
||||||
|
Each benchmark makes 1000 requests requesting a 21.9Mb file using
|
||||||
|
100 users to the webserver running in a Docker container.
|
||||||
|
|
||||||
|
The results from this benchmark vary quite a bit. About half the time,
|
||||||
|
Apache can beat anthracite.
|
||||||
|
|
||||||
|
```
|
||||||
|
=====[ Anthracite Benchmarking Tool ]=====
|
||||||
|
Requests : 1000
|
||||||
|
Users/Threads: 100
|
||||||
|
|
||||||
|
|
||||||
|
====[ anthracite ]=====
|
||||||
|
Average Response Time: 5.5128 seconds
|
||||||
|
p995 Response Time : 8.3105 seconds
|
||||||
|
p99 Response Time : 8.1796 seconds
|
||||||
|
p90 Response Time : 6.4393 seconds
|
||||||
|
p75 Response Time : 5.8587 seconds
|
||||||
|
p50 Response Time : 5.4393 seconds
|
||||||
|
Total Response Time : 5512.8397 seconds
|
||||||
|
====[ nginx ]=====
|
||||||
|
Average Response Time: 6.0201 seconds
|
||||||
|
p995 Response Time : 12.4648 seconds
|
||||||
|
p99 Response Time : 11.9635 seconds
|
||||||
|
p90 Response Time : 8.7204 seconds
|
||||||
|
p75 Response Time : 6.7331 seconds
|
||||||
|
p50 Response Time : 5.5341 seconds
|
||||||
|
Total Response Time : 6020.1369 seconds
|
||||||
|
====[ apache ]=====
|
||||||
|
Average Response Time: 5.9795 seconds
|
||||||
|
p995 Response Time : 12.8266 seconds
|
||||||
|
p99 Response Time : 11.6336 seconds
|
||||||
|
p90 Response Time : 7.1465 seconds
|
||||||
|
p75 Response Time : 6.4420 seconds
|
||||||
|
p50 Response Time : 5.8224 seconds
|
||||||
|
Total Response Time : 5979.5446 seconds
|
||||||
|
==========
|
||||||
|
Total Test Time : 179.7469 seconds
|
||||||
|
```
|
||||||
|
|
||||||
# 0.1.0 Second Pre-Release
|
# 0.1.0 Second Pre-Release
|
||||||
|
|
||||||
- Allowed multiple clients to be handled at once via multithreadding
|
- Allowed multiple clients to be handled at once via multithreadding
|
||||||
|
|
|
@ -4,4 +4,9 @@ RUN apk add --no-cache build-base
|
||||||
COPY ./src/ .
|
COPY ./src/ .
|
||||||
RUN make build-release
|
RUN make build-release
|
||||||
|
|
||||||
|
FROM alpine
|
||||||
|
RUN apk add --no-cache build-base
|
||||||
|
COPY --from=build-env /anthracite /anthracite
|
||||||
|
COPY --from=build-env /www /www
|
||||||
|
COPY --from=build-env /error_pages /error_pages
|
||||||
CMD ["/anthracite"]
|
CMD ["/anthracite"]
|
||||||
|
|
|
@ -34,6 +34,7 @@ def make_request(request_number, server_name):
|
||||||
response_times[server_name].append(response_time)
|
response_times[server_name].append(response_time)
|
||||||
else:
|
else:
|
||||||
print(f'Request {request_number}: Request failed with status code {response.status_code}')
|
print(f'Request {request_number}: Request failed with status code {response.status_code}')
|
||||||
|
|
||||||
print('=====[ Anthracite Benchmarking Tool ]=====')
|
print('=====[ Anthracite Benchmarking Tool ]=====')
|
||||||
print(f'Requests : {num_requests}')
|
print(f'Requests : {num_requests}')
|
||||||
print(f'Users/Threads: {num_users}\n\n')
|
print(f'Users/Threads: {num_users}\n\n')
|
||||||
|
|
|
@ -12,6 +12,9 @@ build-docker:
|
||||||
run: build
|
run: build
|
||||||
./anthracite 8080
|
./anthracite 8080
|
||||||
|
|
||||||
|
run-test: build
|
||||||
|
./anthracite 8080 ./test_www
|
||||||
|
|
||||||
debug: build
|
debug: build
|
||||||
gdb --args ./anthracite 8080
|
gdb --args ./anthracite 8080
|
||||||
|
|
||||||
|
|
|
@ -4,28 +4,11 @@
|
||||||
class file_backend : public backend {
|
class file_backend : public backend {
|
||||||
private:
|
private:
|
||||||
unordered_map<string, string> file_cache;
|
unordered_map<string, string> file_cache;
|
||||||
bool cache_enabled;
|
string file_dir;
|
||||||
|
|
||||||
unique_ptr<http_response> handle_request_nocache(http_request& req) {
|
|
||||||
string filename = req.path() == "/" ? "index.html" : req.path();
|
|
||||||
filename = "./www/" + filename;
|
|
||||||
ifstream stream(filename);
|
|
||||||
|
|
||||||
int status = 200;
|
|
||||||
if (!stream.is_open()) {
|
|
||||||
status = 404;
|
|
||||||
filename = "./error_pages/404.html";
|
|
||||||
stream = ifstream(filename);
|
|
||||||
}
|
|
||||||
|
|
||||||
stringstream buffer;
|
|
||||||
buffer << stream.rdbuf();
|
|
||||||
return make_unique<http_response>(buffer.str(), status);
|
|
||||||
}
|
|
||||||
|
|
||||||
unique_ptr<http_response> handle_request_cache(http_request& req) {
|
unique_ptr<http_response> handle_request_cache(http_request& req) {
|
||||||
string filename = req.path() == "/" ? "/index.html" : req.path();
|
string filename = req.path() == "/" ? "index.html" : req.path();
|
||||||
filename = "./www" + filename;
|
filename = file_dir + filename;
|
||||||
auto file_info = file_cache.find(filename);
|
auto file_info = file_cache.find(filename);
|
||||||
|
|
||||||
int status = 200;
|
int status = 200;
|
||||||
|
@ -35,7 +18,7 @@ private:
|
||||||
file_info = file_cache.find(filename);
|
file_info = file_cache.find(filename);
|
||||||
}
|
}
|
||||||
|
|
||||||
return make_unique<http_response>(file_info->second, status);
|
return make_unique<http_response>(file_info->second, filename, status);
|
||||||
}
|
}
|
||||||
|
|
||||||
void populate_cache_dir(string dir) {
|
void populate_cache_dir(string dir) {
|
||||||
|
@ -55,18 +38,16 @@ private:
|
||||||
}
|
}
|
||||||
|
|
||||||
void populate_cache() {
|
void populate_cache() {
|
||||||
populate_cache_dir("./www/");
|
populate_cache_dir(file_dir);
|
||||||
populate_cache_dir("./error_pages/");
|
populate_cache_dir("./error_pages/");
|
||||||
}
|
}
|
||||||
|
|
||||||
public:
|
public:
|
||||||
file_backend(bool enable_cache) : cache_enabled(enable_cache) {
|
file_backend(string dir = "./www") : file_dir(dir) {
|
||||||
if(cache_enabled) {
|
populate_cache();
|
||||||
populate_cache();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
unique_ptr<http_response> handle_request(http_request& req) override {
|
unique_ptr<http_response> handle_request(http_request& req) override {
|
||||||
return cache_enabled ? handle_request_cache(req) : handle_request_nocache(req);
|
return handle_request_cache(req);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
51
src/http.cpp
51
src/http.cpp
|
@ -139,6 +139,27 @@ static unordered_map<int, string> const http_status_map = {
|
||||||
{ 420, "ENHANCE YOUR CALM" }
|
{ 420, "ENHANCE YOUR CALM" }
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static unordered_map<std::string, std::string> const mime_types = {
|
||||||
|
{ "html", "text/html" },
|
||||||
|
{ "css", "text/css" },
|
||||||
|
|
||||||
|
{ "js", "application/javascript" },
|
||||||
|
{ "pdf", "application/pdf" },
|
||||||
|
|
||||||
|
{ "ico", "image/x-icon" },
|
||||||
|
{ "jpg", "image/jpeg" },
|
||||||
|
{ "jpeg", "image/jpeg" },
|
||||||
|
{ "png", "image/png" },
|
||||||
|
{ "gif", "image/gif" },
|
||||||
|
{ "bmp", "image/bmp" },
|
||||||
|
|
||||||
|
{ "mp4", "video/mp4" },
|
||||||
|
{ "avi", "video/x-msvideo" },
|
||||||
|
{ "mkv", "video/x-matroska" },
|
||||||
|
{ "mov", "video/quicktime" },
|
||||||
|
{ "wmv", "video/x-ms-wmv" },
|
||||||
|
};
|
||||||
|
|
||||||
class name_value {
|
class name_value {
|
||||||
private:
|
private:
|
||||||
string _name;
|
string _name;
|
||||||
|
@ -378,13 +399,15 @@ public:
|
||||||
class http_response {
|
class http_response {
|
||||||
private:
|
private:
|
||||||
int _status_code;
|
int _status_code;
|
||||||
string _content;
|
string& _content;
|
||||||
|
string _filename;
|
||||||
unordered_map<string, http_header> _headers; // kinda goofy, whatever
|
unordered_map<string, http_header> _headers; // kinda goofy, whatever
|
||||||
|
|
||||||
public:
|
public:
|
||||||
http_response(string content, int status_code = 200)
|
http_response(string& content, string filename, int status_code = 200)
|
||||||
: _content(std::move(content))
|
: _content(content)
|
||||||
, _status_code(status_code)
|
, _status_code(status_code)
|
||||||
|
, _filename(std::move(filename))
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -397,12 +420,22 @@ public:
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
string to_string()
|
string& content()
|
||||||
|
{
|
||||||
|
return _content;
|
||||||
|
}
|
||||||
|
|
||||||
|
string header_to_string()
|
||||||
{
|
{
|
||||||
string response = "";
|
string response = "";
|
||||||
response += "HTTP/1.1 " + ::to_string(_status_code) + " " + http_status_map.find(_status_code)->second + "\r\n";
|
response += "HTTP/1.1 " + ::to_string(_status_code) + " " + http_status_map.find(_status_code)->second + "\r\n";
|
||||||
|
string content_type = "text/html";
|
||||||
add_header(http_header("Content-Type", "text/html"), false);
|
string file_extension = _filename.substr(_filename.rfind('.') + 1);
|
||||||
|
auto mime_type = mime_types.find(file_extension);
|
||||||
|
if (mime_type != mime_types.end()) {
|
||||||
|
content_type = mime_type->second;
|
||||||
|
}
|
||||||
|
add_header(http_header("Content-Type", content_type), false);
|
||||||
add_header(http_header("Content-Length", ::to_string(_content.length())), false);
|
add_header(http_header("Content-Length", ::to_string(_content.length())), false);
|
||||||
add_header(http_header("Server", "Anthracite/0.0.1"), false);
|
add_header(http_header("Server", "Anthracite/0.0.1"), false);
|
||||||
|
|
||||||
|
@ -411,8 +444,12 @@ public:
|
||||||
}
|
}
|
||||||
|
|
||||||
response += "\r\n";
|
response += "\r\n";
|
||||||
response += _content;
|
|
||||||
|
|
||||||
return response;
|
return response;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
string to_string()
|
||||||
|
{
|
||||||
|
return header_to_string() + _content;
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
13
src/main.cpp
13
src/main.cpp
|
@ -16,6 +16,7 @@ using namespace std;
|
||||||
void log_request_and_response(http_request& req, unique_ptr<http_response>& resp);
|
void log_request_and_response(http_request& req, unique_ptr<http_response>& resp);
|
||||||
|
|
||||||
constexpr int default_port = 80;
|
constexpr int default_port = 80;
|
||||||
|
constexpr int max_worker_threads = 128;
|
||||||
|
|
||||||
int active_threads = 0;
|
int active_threads = 0;
|
||||||
mutex mtx;
|
mutex mtx;
|
||||||
|
@ -26,15 +27,15 @@ void handle_client(anthracite_socket s, file_backend& fb)
|
||||||
http_request req(s);
|
http_request req(s);
|
||||||
unique_ptr<http_response> resp = fb.handle_request(req);
|
unique_ptr<http_response> resp = fb.handle_request(req);
|
||||||
log_request_and_response(req, resp);
|
log_request_and_response(req, resp);
|
||||||
s.send_message(resp->to_string());
|
string header = resp->header_to_string();
|
||||||
|
s.send_message(header);
|
||||||
|
s.send_message(resp->content());
|
||||||
resp.reset();
|
resp.reset();
|
||||||
s.close_conn();
|
s.close_conn();
|
||||||
|
|
||||||
{
|
{
|
||||||
std::lock_guard<std::mutex> lock(mtx);
|
std::lock_guard<std::mutex> lock(mtx);
|
||||||
active_threads--;
|
active_threads--;
|
||||||
}
|
}
|
||||||
|
|
||||||
cv.notify_one();
|
cv.notify_one();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -48,14 +49,14 @@ int main(int argc, char** argv)
|
||||||
|
|
||||||
cout << "Initializing Anthracite" << endl;
|
cout << "Initializing Anthracite" << endl;
|
||||||
anthracite_socket s(port_number);
|
anthracite_socket s(port_number);
|
||||||
file_backend fb(true);
|
file_backend fb(argc > 2 ? argv[2] : "./www");
|
||||||
cout << "Initialization Complete" << endl;
|
cout << "Initialization Complete" << endl;
|
||||||
cout << "Listening for HTTP connections on port " << port_number << endl;
|
cout << "Listening for HTTP connections on port " << port_number << endl;
|
||||||
|
|
||||||
for (;;) {
|
while (true) {
|
||||||
s.wait_for_conn();
|
s.wait_for_conn();
|
||||||
std::unique_lock<std::mutex> lock(mtx);
|
std::unique_lock<std::mutex> lock(mtx);
|
||||||
cv.wait(lock, [] { return active_threads < 20; });
|
cv.wait(lock, [] { return active_threads < max_worker_threads; });
|
||||||
active_threads++;
|
active_threads++;
|
||||||
thread(handle_client, s, ref(fb)).detach();
|
thread(handle_client, s, ref(fb)).detach();
|
||||||
}
|
}
|
||||||
|
|
|
@ -56,7 +56,7 @@ public:
|
||||||
client_socket = -1;
|
client_socket = -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
void send_message(string msg)
|
void send_message(string& msg)
|
||||||
{
|
{
|
||||||
if (client_socket == -1) {
|
if (client_socket == -1) {
|
||||||
return;
|
return;
|
||||||
|
|
BIN
src/test_www/images/emma.bmp
Normal file
BIN
src/test_www/images/emma.bmp
Normal file
Binary file not shown.
After Width: | Height: | Size: 496 KiB |
BIN
src/test_www/images/favicon.ico
Normal file
BIN
src/test_www/images/favicon.ico
Normal file
Binary file not shown.
After Width: | Height: | Size: 319 B |
BIN
src/test_www/images/favicon_anim.ico
Normal file
BIN
src/test_www/images/favicon_anim.ico
Normal file
Binary file not shown.
After Width: | Height: | Size: 3.6 KiB |
BIN
src/test_www/images/lola.jpeg
Normal file
BIN
src/test_www/images/lola.jpeg
Normal file
Binary file not shown.
After Width: | Height: | Size: 38 KiB |
BIN
src/test_www/images/tini.png
Normal file
BIN
src/test_www/images/tini.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 42 KiB |
9
src/test_www/index.html
Normal file
9
src/test_www/index.html
Normal file
|
@ -0,0 +1,9 @@
|
||||||
|
<head>
|
||||||
|
<title>Anthracite</title>
|
||||||
|
<link rel="icon" type="image/x-icon" href="/images/favicon.ico">
|
||||||
|
</head>
|
||||||
|
<center>
|
||||||
|
<h1>Anthracite is Running!</h1>
|
||||||
|
<p>If you are seeing this page, then Anthracite is configured correctly!</p>
|
||||||
|
<p>Add files to the "www" directory to begin serving your website.</p>
|
||||||
|
</center>
|
18
src/test_www/test.css
Normal file
18
src/test_www/test.css
Normal file
|
@ -0,0 +1,18 @@
|
||||||
|
.cool-style {
|
||||||
|
background: linear-gradient(to right, #ef5350, #f48fb1, #7e57c2, #2196f3, #26c6da, #43a047, #eeff41, #f9a825, #ff5722);
|
||||||
|
-webkit-background-clip: text;
|
||||||
|
-webkit-text-fill-color: transparent;
|
||||||
|
}
|
||||||
|
|
||||||
|
.content {
|
||||||
|
display: flex;
|
||||||
|
flex-wrap: wrap;
|
||||||
|
justify-content: center;
|
||||||
|
align-items: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.content img {
|
||||||
|
max-width: 100%;
|
||||||
|
height: auto;
|
||||||
|
margin: 10px;
|
||||||
|
}
|
25
src/test_www/test.html
Normal file
25
src/test_www/test.html
Normal file
|
@ -0,0 +1,25 @@
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<title>Anthracite</title>
|
||||||
|
<link rel="icon" type="image/x-icon" href="/images/favicon_anim.ico">
|
||||||
|
<link rel="stylesheet" href="test.css">
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<center>
|
||||||
|
<h1 class="cool-style">Test Page!</h1>
|
||||||
|
<h2>Dogs</h2>
|
||||||
|
<div class="content">
|
||||||
|
<img src="/images/tini.png" alt="A border collie" />
|
||||||
|
<img src="/images/lola.jpeg" alt="A border collie" />
|
||||||
|
<img src="/images/emma.bmp" alt="A corgi" />
|
||||||
|
</div>
|
||||||
|
<h2>Trains</h2>
|
||||||
|
<div>
|
||||||
|
<video controls>
|
||||||
|
<source src="videos/train_vid.mp4" />
|
||||||
|
</video>
|
||||||
|
</div>
|
||||||
|
</center>
|
||||||
|
</body>
|
||||||
|
</html>
|
BIN
src/test_www/videos/train_vid.mp4
Normal file
BIN
src/test_www/videos/train_vid.mp4
Normal file
Binary file not shown.
|
@ -1,3 +1,7 @@
|
||||||
|
<head>
|
||||||
|
<title>Anthracite</title>
|
||||||
|
<link rel="icon" type="image/x-icon" href="/images/favicon.ico">
|
||||||
|
</head>
|
||||||
<center>
|
<center>
|
||||||
<h1>Anthracite is Running!</h1>
|
<h1>Anthracite is Running!</h1>
|
||||||
<p>If you are seeing this page, then Anthracite is configured correctly!</p>
|
<p>If you are seeing this page, then Anthracite is configured correctly!</p>
|
||||||
|
|
1020251
src/www/large.html
1020251
src/www/large.html
File diff suppressed because it is too large
Load diff
|
@ -1,3 +0,0 @@
|
||||||
<center>
|
|
||||||
<h1>Test Page!</h1>
|
|
||||||
</center>
|
|
Loading…
Reference in a new issue