GithubHelp home page GithubHelp logo

yukunj / turtle Goto Github PK

View Code? Open in Web Editor NEW
235.0 3.0 21.0 2.71 MB

A C++17-based lightweight high-performance network library

Home Page: https://github.com/YukunJ/Turtle

License: MIT License

CMake 7.93% C++ 80.65% Shell 0.71% C 7.95% Makefile 1.36% Roff 1.40%
webframework network http-server networking linux updating-often cpp cpp17 mysql asynchornous-logging

turtle's Introduction

✨Welcome to YukunJ's profile✨


Greetings! I am Yukun(宇昆), this is my github main page.

  • 💼 I work as a junior Software Engineer for a trading company in the U.S.
  • 🔭 I graduated from Carnegie Mellon University with M.S. in Computational Data Science (System Track)
  • 🌱 I graduated from New York University with double B.S. in Honors Mathematics and Computer Science
  • 🏠 My hometown is Shanghai, China. A metropolis ever-evolving
  • 😄 Pronouns: he/him/his
  • ✒️ Learn more about me at my website
  • ⚡ Fun fact: big fan of <Naruto> series. Uchiha Itachi is my favorite character
  • 💪 Recently been working on Turtle C++ network library

turtle's People

Contributors

mcmengde avatar yukunj avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar

turtle's Issues

Why not just use member variable in member function "SetCustomAcceptCallback"?

Code snippet at src/core/acceptor.cpp:65.

void Acceptor::SetCustomAcceptCallback(
    std::function<void(Connection *)> custom_accept_callback) {
  custom_accept_callback_ = std::move(custom_accept_callback);
  acceptor_conn->SetCallback([this](auto &&PH1) {
    BaseAcceptCallback(std::forward<decltype(PH1)>(PH1));
    GetCustomAcceptCallback()(std::forward<decltype(PH1)>(PH1));
  });
}

GetCustomAcceptCallback() returns custom_accept_callback_. Using custom_accept_callback_ may be more readable?

Feature Request: Timer

New Features Timer should be added to track those inactive client Connection and terminate them to save system socket resources.

The basic idea is to maintain a list/set of individual timers in a container use the system calls

 #include <sys/timerfd.h>

int timerfd_create(int clockid, int flags);

int timerfd_settime(int fd, int flags,
                const struct itimerspec *new_value,
                struct itimerspec *old_value);
int timerfd_gettime(int fd, struct itimerspec *curr_value);

to set the alarm to be the earliest timeout time from the whole container individual timer. Upon timeout triggered, prune the container so as to delete expired Connection. And when tackle new messages from a connection, the timer for that Connection should be refreshed, and potentially reset the timer_fd's alarm time if it happens to be the earliest timeout.

One caveat is that, we need to be careful about the life time management of Connection. Hopefully, if we terminate the connection by closing the fd, it will not appear in next round's Epoll call.

To be done in April/May when I have some free time.

Improvement: revision suggestions from reddit post

Appreciate kind net friends from reddit post to give me more revision advice.

- ✅ use TARGET_INCLUDE_DIRECTORIES instead of INCLUDE_DIRECTORIES
- ❌ FILE(GLOB) is not recommended
    Ref: https://cmake.org/cmake/help/latest/command/file.html
-✅ avoid macros wherever its applicable use const or constexpr
-✅ Follow the coding guidelines pick google style or any other popular c++ coding guidelines
- ❌ Follow the naming conventions as per the coding guidelines
    Ex: namespace TURTLE_SERVER should be in small case
- ✅ explicit not required for multi args constructor
    Ex: explicit Acceptor,explicit Connection
- [Not Applicable, use `std::vector<unsigned char>` already] Use std::array instead of C-Style arrays

Most of these suggestions seem plausible. Will carefully look over them one by one and revise once I get a moment.

✅ means already adopted and revised.
❌ means it's not to be revised in near future.
Yukun
Feb 07

Enhancement: reduce one layer of indirection in Looper's map

Currently the Looper contains a map of std::map<int, std::unique_ptr<Connection>>. However, another alternative approach is to directly store as std::map<int, Connection>.

Why I don't implement it this way during development? Because it's easier to manage the lifecycle of the Connection by using std::unique_ptr, because upon destruction Connection will close its Socket nested.

However, the alternative approach might have better performance as it reduces one layer of indirect memory access. (int to std::unique_ptr to real Connection).

It is worth experimenting, but not a high priority.

Yukun
Feb 07

Enhancement: strip off the std::map,use std::unordered_map instead

Thanks to Cppers on reddit here.

Currently the Looper use std::map<int, std::unique_ptr<Connection>> to keep track of which connection's lifecycle is under its monitoring.

/**
 * This Looper acts as the executor on a single thread
 * adopt the philosophy of 'one looper per thread'
 * */
class Looper {
 public:
  ...
 private:
  ...
  std::map<int, std::unique_ptr<Connection>> connections_;
  ...
};

However, since we don't required the ordered property provided by std::map, a better performance could be achieved by using std::unordered_map. Typically given the fact that currently any access to this connections_ variable requires mutex for synchronization.

I plan to implement this feature shortly.

Yukun
Feb 07

Enhancement: Add clang-tidy support in build

As suggested by my net friend, it's best to have clang-tidy built into the project, which can help reveal many potential bugs in the source code.

Should be an easy fix to do.

Yukun
Feb 07

confusion about `sockaddr` in class `net_address`

What if use sockaddr_storage instead of sockaddr for both IPv4 and IPv6?
Seems sockaddr and sockaddr_in are both 16bytes, however sockaddr_in6 is 28 bytes, would it access illegal address after converting sockaddr* into sockaddr_in6* for IPv6?

Wrong Event Macro

In the Acceptor's event setter, used EPOLL_CTL_ADD instead of EPOLLIN as the read event signal. This is incorrect. It works before because they share the same value. But this is not portable.

Should distinguish the "operator" EPOLL_CTL_ADD and event signal EPOLLIN.

Same applies to MacOS Kqueue part.

Thanks to "大橘为重" on Zhihu platform for raising this issue to my attention.

Improvement: Save DiskFile Directly into Response When Cold Cache Miss

One commenter 忘机 on Zhihu points out that:

On http_server.cc:78

          auto resource_cached = cache->TryLoad(resource_full_path, cache_buf);
          response.SetShouldTransferContent(
              request.GetMethod() != Method::HEAD && !resource_cached);
          no_more_parse = request.ShouldClose();
          response.Serialize(response_buf);
          if (resource_cached) {
            // content directly from cache, not disk file I/P
            response_buf.insert(response_buf.end(), cache_buf.begin(),
                                cache_buf.end());
          } else {
            // content not in cache, try store it
            LoadFile(resource_full_path, cache_buf);
            cache->TryInsert(resource_full_path, cache_buf);
          }

Here when the requested file is not in the cache,response.Serialize(response_buf); will load the content into response_buf. But then the same file is loaded from Disk again to be saved in the cache.

In short, currently on a cold miss, the file is fetched from Disk twice. It could have directly saved from the response_buf into cache the first time of loading, to save 1 disk I/O.

To be fixed soon, preferably in March.

Yukun

Enhancement: allow socket send to be "asynchronous" if data size too large

The following is the cope snippet for the Connection::Send() which outwrites all the data stored in the Buffer, it will stay in this function loop until all data has been sent out. In this sense, this code snippet is correct.

void Connection::Send() {
  // robust write
  ssize_t curr_write = 0;
  ssize_t write;
  const ssize_t to_write = GetWriteBufferSize();
  const unsigned char *buf = write_buffer_->Data();
  while (curr_write < to_write) {
    if ((write = send(GetFd(), buf + curr_write, to_write - curr_write, 0)) <=
        0) {
      if (errno != EINTR && errno != EAGAIN && errno != EWOULDBLOCK) {
        perror("Error in Connection::Send()");
        ClearWriteBuffer();
        return;
      }
      write = 0;
    }
    curr_write += write;
  }
  ClearWriteBuffer();
}

However, one thing to be optimized is that: when the data to sent is large in size, the underlying socket buffer allocated by the operating system might be full and throws back EAGAIN/EWOULDBLOCK to the send() calls. In current version, the code just sit and wait until the buffer is empty enough to keep sending.

However, a better approach would be to register to the Poller that "We are interested in the being able to write more event of this TCP connection", and this worker thread could go to work on other client's callbacks. When the write buffer is empty enough, OS will notifies the Poller in the next round and it could continue sending the leftover bits.

Most likely, the above approach could achieve a better overall performance of the server, at the little cost of that "overloaded outwrite" connection might experience a short delay of full response since it might need to wait for next round of polling.

I plan to implement this feature in the near future.

Yukun
Feb 06, 2023

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.