diff --git a/.gitmodules b/.gitmodules index a6727c9..f09226a 100644 --- a/.gitmodules +++ b/.gitmodules @@ -1,3 +1,3 @@ -[submodule "external/quill"] - path = external/quill - url = https://github.com/odygrd/quill +[submodule "external/tracy"] + path = external/tracy + url = https://github.com/wolfpld/tracy diff --git a/CMakeLists.txt b/CMakeLists.txt index 9748f49..3f6b850 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -5,24 +5,14 @@ set(CMAKE_CXX_STANDARD 20) set(CMAKE_CXX_STANDARD_REQUIRED ON) set(CMAKE_EXPORT_COMPILE_COMMANDS ON) -# pass cmake configs to build tests or not by default -option(BUILD_BINARY "Build binary" ON) option(BUILD_TESTS "Build tests" ON) +option(BUILD_EXAMPLES "Build examples" ON) -add_subdirectory(external) +add_subdirectory(libflux) -set(SOURCES - src/main.cpp - src/thread.cpp - src/reactor.cpp - src/backends/darwin.cpp) - -if (BUILD_BINARY) - message(STATUS "Building binary") - include_directories(include) - add_executable(${PROJECT_NAME} ${SOURCES}) - target_include_directories(${PROJECT_NAME} PUBLIC include) - target_link_libraries(${PROJECT_NAME} PUBLIC external) +if (BUILD_EXAMPLES) + message(STATUS "Building examples") + add_subdirectory(examples) endif () if (BUILD_TESTS) diff --git a/README.md b/README.md index ca99220..4c18558 100644 --- a/README.md +++ b/README.md @@ -41,4 +41,7 @@ https://webflow.com/made-in-webflow/website/Apple-Style-Grid Can make this as th and `kqueue`, we just make the edge triggered the default. -## Desgi \ No newline at end of file +## Ideas + +- [ ] Inject tracy profiling before functions during build step using AST transformations +- [ ] Use `eventfd` for shared mem OB? diff --git a/docs/ARCHITECTURE.md b/docs/ARCHITECTURE.md index 82c7ac3..510dadf 100644 --- a/docs/ARCHITECTURE.md +++ b/docs/ARCHITECTURE.md @@ -49,4 +49,13 @@ can be done in two ways, 1. Call `kevent` for each change to actively monitored fd list 2. Build up a list of descriptor changes and pass it to the kernel the next event loop epoch. Reduces number of - sys-calls made \ No newline at end of file + sys-calls made + +```cpp +struct kevent { + uintptr_t ident; // Most of the time refers to a FD, but its meaning can change based on the filter. Essentially a value to identify the event + filter; // Determines the kernel filter to process this event, e.g `EVFILT_TIMER` + +}; +``` + diff --git a/examples/CMakeLists.txt b/examples/CMakeLists.txt new file mode 100644 index 0000000..fb85b78 --- /dev/null +++ b/examples/CMakeLists.txt @@ -0,0 +1,2 @@ +add_executable(fiber fiber.cpp) +target_link_libraries(fiber PRIVATE libflux external) diff --git a/src/main.cpp b/examples/fiber.cpp similarity index 68% rename from src/main.cpp rename to examples/fiber.cpp index 7f7bc7a..d60df0a 100644 --- a/src/main.cpp +++ b/examples/fiber.cpp @@ -4,6 +4,9 @@ #include #include +#include "tracy/Tracy.hpp" +#include "tracy/TracyC.h" + #include "backends/darwin.hpp" #include "thread.hpp" @@ -36,6 +39,7 @@ struct Worker : flux::Thread { thing = (thing * 7 + count) / 8; printf("count: %d\n", count); this->wait(); + FrameMark; } } }; @@ -49,33 +53,10 @@ int main() { flux::KqueueReactor reactor; reactor.set_timer(1010, 1500, &worker); // reactor.subscribe(1010, &worker); + tracy::SetThreadName("hello"); while (reactor.active()) { reactor.work(); + FrameMark; } - - return 0; - - // CHECK_EX(false, "This is a test"); - // exit(1); - // kq = kqueue(); - // assert(kq != -1); - // - // struct context obj = {}; - // obj.rhandler = [](struct context *obj) { - // printf("Received socket READ event via kqueue\n"); - // int csock = accept(obj->sk, NULL, 0); - // assert(csock != -1); - // close(csock); - // }; - // - // // creet and prepare a socket - // obj.sk = socket(AF_INET, SOCK_STREAM | SOCK_NONBLOCK, 0); - // assert(obj.sk != -1); - // int val = 1; - // setsockopt(obj.sk, SOL_SOCKET, SO_REUSEADDR, &val, 4); - // - // struct sockaddr_in addr = {}; - // addr.sin_family = AF_INET; - // addr.sin_port = ntohs(64000); } diff --git a/external/CMakeLists.txt b/external/CMakeLists.txt index e798e8b..e69de29 100644 --- a/external/CMakeLists.txt +++ b/external/CMakeLists.txt @@ -1,8 +0,0 @@ -find_package(Boost COMPONENTS context REQUIRED) -message(STATUS "Boost include dir: ${Boost_INCLUDE_DIRS}") - -add_subdirectory(quill) - -add_library(external INTERFACE) -target_link_libraries(external INTERFACE ${Boost_LIBRARIES} quill::quill) -target_include_directories(external INTERFACE ${Boost_INCLUDE_DIRS}) \ No newline at end of file diff --git a/external/quill b/external/quill deleted file mode 160000 index ea0e0e8..0000000 --- a/external/quill +++ /dev/null @@ -1 +0,0 @@ -Subproject commit ea0e0e811cdddb8b987232ef7bc648a4cb57ad81 diff --git a/external/tracy b/external/tracy new file mode 160000 index 0000000..521e371 --- /dev/null +++ b/external/tracy @@ -0,0 +1 @@ +Subproject commit 521e371c60e37b47ffb8b0330d310af7061e0af8 diff --git a/libflux/CMakeLists.txt b/libflux/CMakeLists.txt new file mode 100644 index 0000000..fac6c00 --- /dev/null +++ b/libflux/CMakeLists.txt @@ -0,0 +1,44 @@ +cmake_minimum_required(VERSION 3.9) +project(libflux) +include(FetchContent) + +set(CMAKE_CXX_STANDARD 20) +set(CMAKE_CXX_STANDARD_REQUIRED ON) + +# Boost +find_package(Boost COMPONENTS context REQUIRED) +message(STATUS "Boost include dir: ${Boost_INCLUDE_DIRS}") + +# Tracy +set(TRACY_ENABLE ON) +set(TRACY_FIBERS ON) # pdf page 38 +FetchContent_Declare( + tracy + GIT_REPOSITORY https://github.com/wolfpld/tracy.git + GIT_TAG master + GIT_SHALLOW TRUE + GIT_PROGRESS TRUE +) +FetchContent_MakeAvailable(tracy) + +# Quill +FetchContent_Declare( + quill + GIT_REPOSITORY https://github.com/odygrd/quill.git + GIT_TAG master + GIT_SHALLOW TRUE + GIT_PROGRESS TRUE +) +FetchContent_MakeAvailable(quill) + + +# specify the source files +set(SOURCES + src/thread.cpp + src/reactor.cpp + src/backends/darwin.cpp) + +# add the library +add_library(${PROJECT_NAME} STATIC ${SOURCES}) +target_include_directories(${PROJECT_NAME} PUBLIC include ${Boost_INCLUDE_DIRS}) +target_link_libraries(${PROJECT_NAME} PUBLIC ${Boost_LIBRARIES} Tracy::TracyClient quill:quill) \ No newline at end of file diff --git a/include/backends/darwin.hpp b/libflux/include/backends/darwin.hpp similarity index 100% rename from include/backends/darwin.hpp rename to libflux/include/backends/darwin.hpp diff --git a/include/fifo.hpp b/libflux/include/fifo.hpp similarity index 100% rename from include/fifo.hpp rename to libflux/include/fifo.hpp diff --git a/include/reactor.hpp b/libflux/include/reactor.hpp similarity index 100% rename from include/reactor.hpp rename to libflux/include/reactor.hpp diff --git a/include/thread.hpp b/libflux/include/thread.hpp similarity index 86% rename from include/thread.hpp rename to libflux/include/thread.hpp index 21ab6f8..6182c22 100644 --- a/include/thread.hpp +++ b/libflux/include/thread.hpp @@ -3,6 +3,7 @@ #include #include #include +#include #include #include @@ -41,7 +42,7 @@ class Thread { ~Thread(); - //! Called from within thread's context + //! Called from within thread's context. //! Passes control back to the caller (e.g Reactor), and this thread will be resumed //! when the events are ready. auto wait() -> Event *; @@ -49,19 +50,19 @@ class Thread { //! Resumes the thread with the given event. Returns true if resumable [[nodiscard]] auto resume(Event *event) -> bool; - //! Where you place your business logic + //! Where you place your business logic. virtual void run() = 0; - //! Starts executing the `run()` method + //! Starts executing the `run()` method. void start(); - //! Subscribe to a particular file descriptor + //! Subscribe to a particular file descriptor. auto subscribe(int fd) -> bool; - //! Unsubscribe to a particular file descriptor + //! Unsubscribe to a particular file descriptor. auto unsubscribe(int fd) -> bool; - //! List of fds that this thread is interested in + //! List of fds that this thread is interested in. std::vector m_fds; private: diff --git a/include/utils.hpp b/libflux/include/utils.hpp similarity index 100% rename from include/utils.hpp rename to libflux/include/utils.hpp diff --git a/src/backends/darwin.cpp b/libflux/src/backends/darwin.cpp similarity index 99% rename from src/backends/darwin.cpp rename to libflux/src/backends/darwin.cpp index b27ca66..44c6046 100644 --- a/src/backends/darwin.cpp +++ b/libflux/src/backends/darwin.cpp @@ -10,6 +10,7 @@ KqueueReactor::KqueueReactor() : m_kqueue_fd{kqueue()}, m_timeout{nullptr} { KqueueReactor::~KqueueReactor() { close(m_kqueue_fd); } bool KqueueReactor::work() { + ZoneScoped; // TODO: 16 can be adjusted based on busy-ness of the event loop. Can even be dynamic std::array events{}; @@ -61,6 +62,7 @@ void KqueueReactor::set_timer(int id, int timer_period, Thread *thread) { } void KqueueReactor::handle_sock_op(int fd, Operation op) { + ZoneScoped; // #ifndef NDEBUG FLUX_ASSERT(m_kqueue_fd >= 0, "Kqueue file descriptor is invalid"); // #endif diff --git a/src/reactor.cpp b/libflux/src/reactor.cpp similarity index 100% rename from src/reactor.cpp rename to libflux/src/reactor.cpp diff --git a/src/thread.cpp b/libflux/src/thread.cpp similarity index 93% rename from src/thread.cpp rename to libflux/src/thread.cpp index c3251dc..68665b7 100644 --- a/src/thread.cpp +++ b/libflux/src/thread.cpp @@ -2,6 +2,8 @@ using namespace flux; +const char *flux_thread = "flux_thread"; + Thread::Thread(size_t _stack_size) { StackAllocator stack_allocator(_stack_size); m_stack = stack_allocator.allocate(); @@ -13,12 +15,13 @@ Thread::~Thread() { } auto Thread::wait() -> Event * { + TracyFiberLeave; m_return_context = jump_fcontext(m_return_context.fctx, this); + TracyFiberEnter(flux_thread); return reinterpret_cast(m_return_context.data); } auto Thread::resume(Event *event) -> bool { - printf("in resume\n"); m_return_context = jump_fcontext(m_return_context.fctx, (void *)event); return m_return_context.data != THREAD_STATUS_COMPLETE; } @@ -37,7 +40,7 @@ void Thread::enter(ReturnContext ctx) { auto *thread = reinterpret_cast(ctx.data); thread->m_return_context = ctx; - + TracyFiberEnter(flux_thread); thread->run(); while (true) {