Your high performance web application C framework
MIT License
Bot releases are hidden (Show)
Published by boazsegev over 6 years ago
This beta 7 release is a big step towards an actual 0.6.0 release, with some important bugs being squashed.
I still want to implement a few features and live-test the beta versions in an actual project before a full version release...
... However, by now the 0.6.0.beta.x releases are far superior than the 0.5.x releases in terms of API, extendibility and ease of use. Where 0.5.x was a closer to being a platform than a framework, the 0.6.0 release is definitely a framework.
Enjoy.
Fix: (websockets
) fixed an issue with client pinging would break the protocol in a way that would result in either loss of data or disconnections.
Fix: (websockets
) removed the debugging ping (3 seconds interval ping) from the Websocket client. Pings can be sent manually or by setting the connection's timeout using facil_set_timeout
.
Fix: (websockets
) made sure the client mask is never zero by setting a few non-random bits.
Fix: (redis
) fixed an issue where the command queue (for busy pipelined Redis commands and for reconnection) would send the last message repeatedly instead of sending the messages in the queue.
Fix: (facil
) Fixed a possible memory leak related to facil_connect
and failed connections to localhost. Improved process exit cleanup.
Fix: (pubsub
) improved process exit cleanup.
Fix: (fio_cli
) fixed text coloring on terminal output.
Fix: (fio_hash
) fixed looping logic to remove the need for the "data-end" marker optimizing allocations in a very small way.
Update: (websockets
) added a client example using the terminal IO for Websocket text communication.
Published by boazsegev over 6 years ago
This beta release is a performance oriented release and includes mostly performance related changes.
This release updates some default values to make them more reasonable for common use cases and to help minimize memory consumption.
These values, such as the LIB_SOCK_MAX_CAPACITY
, FIO_HASH_INITIAL_CAPACITY
and the FIOBJ_ARRAY_DEFAULT_CAPA
values, can be updated during compile time.
Some of these default values can be bypassed during runtime by using specific function calls (such as fio_hash_new2
).
Other notable performance changes include the short string hash cashing (shortening the FIOBJ short-string capacity in exchange for reducing fio_siphash
calls).
These are lessons learned from the TechEmpower benchmarks... although they will not be reflected in the Round 15 results.
Published by boazsegev over 6 years ago
Releasing fixes for issues related to the TechEmpower Framework Benchmarks 80 core startup.
Fix: fixed error handling during cluster mode startup, making sure facil.io fails to start.
Update: capped maximum core detection value to 120 cores. Any value larger than 120 will raise a warning and the cap (120) will be used.
Published by boazsegev over 6 years ago
This release should have no significant changes from the beta.3 release. This release signifies a testing milestone for the beta stage.
A facil.io server was stress tested, malicious data was sent, connections were abruptly terminated, timeouts were held on to and abuse was generally attempted... and all was well :-)
There's also some minor refactoring and minor JSON performance enhancements were attempted... these are negligible.
Published by boazsegev over 6 years ago
The long awaited Websocket Client support is here and it's working (limited testing so far, but hey... it's super fun π).
Breaking Change: (websockets
) the websocket on_close
callback signature had changed to allow it to be called on connection/upgrade failures as well (easier udata
cleanup).
Fix (facil
): fixes an issue introduced in the beta.2 version, where deferred events that where scheduled before a call to facil_run
would only be called for the parent process. Now these events would perform as intended (once in the root process and once in each worker process).
Fix (facil
): updates the logical assumption about open connections, to make sure any open connections are closed when re-spawning a child worker. This shift the connection assumption from unsafe (forked connections should be closed by extensions) to safe (reconnection should be handled by extension). This change should effect internal extensions only, since active connections aren't handled by the root process in clustered mode.
Change (websocket
): the protocol is now more forgiving in cases where clients don't mask empty messages.
Feature (websockets
): A simple and easy Websocket client using websocket_connect
as well as support for more complex clients (with authentication logic etc') using a combination of the http_connect
and http_upgrade2ws
functions.
Minor: some changes to the inner HTTP logic, fixed some error messages, and other minor updates.
Published by boazsegev over 6 years ago
This is a major release, changing much of the extension API (HTTP, pub/sub, cli) and some of the core API (i.e., moving the evio
polling to One-Shot polling).
Migration isn't difficult, but is not transparent either.
Note About Fixes:
I simply rewrote much of the code to know if the issues I fixed were present in the 0.5.x version or not.
I believe some things work better. Some of the locking concerns will have less contention and I think I fixed some issues in the fiobj
core types as well as the http
extension.
However, experience tells me a new major release (0.6.0) is always more fragile than a patch release. I did my best to test the new code, but experience tells me my tests are often as buggy as the code they test.
Anyway, I'm releasing 0.6.0 knowing it works better than the 0.5.8 version, but also knowing it wasn't battle tested just yet.
Changes!: (fiobj
/ facil.io objects):
Major API changes.
The facil.io dynamic type library moved closer to facil.io's core, integrating itself into the HTTP request/response handling, the Pub/Sub engine, the Websocket internal buffer and practically every aspect of the library.
This required some simplification of the fiobj
and making sure future changes would require less of a migration process.
The Symbol and Couplet types were removed, along with nesting protection support (which nobody seemed to use anyway).
We're back to static typing with enum
, using macros and inline functions for type identification (better performance at the expense of making extendability somewhat harder).
Hashes are now 100% collision resistant and have improved memory locality, at the expense of using more memory and performing calling memcmp
(this can be avoided when seeking / removing / deleting items, but not when overwriting items).
Changes!: (http
):
The HTTP API and engine was completely re-written (except the HTTP/1.1 parser), both to support future client mode (including chunked encoding for trailing headers) and to make routing and request parsing easier.
The updates to the HTTP API might result in decreased performance during the HTTP request reading due to the need to allocate resources and possibly copy some of the data into dynamic storage... For example, header Hash Tables replaced header Arrays, improving lookup times and increasing creation time.
The HTTP parser now breaks down long URI schemes into a short URI + host
header (which might become an array if it's included anyway).
Changes!: (websocket
):
The Websocket API includes numerous breaking changes, not least is the pub/sub API rewrite that now leverages FIOBJ
Strings / Symbols.
websocket_write_each
was deprecated (favoring a pub/sub only design).
Changes!: (pubsub
):
The pubsub
API was redesigned after re-evaluating the function of a pub/sub engine and in order to take advantage of the FIOBJ
type system.
Channel names now use a hash map with collision protection (using memcmp
to compare channel names). The means that the 4 but trie is no longer in use and will be deprecated.
Changes!: (redis
):
redis_engine
was rewritten, along with the RESP parser, to reflect the changes in the new pubsub
service and to remove obsolete code.Changes!: (facil
):
Slight API changes:
facil_last_tick
now returns struct timespec
instead of time_t
, allowing for more accurate time stamping.
facil_cluster_send
and facil_cluster_set_handler
were redesigned to reflect the new cluster engine (now using Unix Sockets instead of pipes).
Internal updates to accommodate changes to other libraries.
Cluster mode now behaves as sentinel, re-spawning any crashed worker processes (except in DEBUG mode).
Changes!: (evio
):
the evented IO library was redesigned for one-shot notifications, requiring a call to evio_add
or evio_set_timer
in order to receive future notifications.
This was a significant change in behavior and the changes to the API (causing backwards incompatibility) were intentional.
the code was refactored to separate system specific logic into different files. making it easier to support more systems in the future.
Changes!: (sock
):
the socket library now supports automatic Unix detection (set port
to NULL and provide a valid Unix socket path in the address
field).
the socket library's Read/Write hooks API was revised, separating the function pointers from the user data. At server loads over 25%, this decreases the memory footprint.
the socket library's packet buffer API was deprecated and all sock_write2(...)
operations take ownership of the memory/file (enforce move
).
The internal engine was updated, removing pre-allocated packet buffers altogether and enabling packet header allocation using malloc
, which introduces a significant changes to the internal behavior, possibly effecting embedded systems.
Changes!: (defer
):
Removed forking from the defer library, moving the fork
logic into the main facil
source code.
Defer thread pools and now include two weak functions that allow for customized thread scheduling (wakeup/wait). These are overwritten by facil.io (in facil.c
).
By default, defer will use nanosleep
.
Refactoring: (fiobj
) moved the underlying Dynamic Array and Hash Table logic into single file libraries that support void *
pointers, allowing the same logic to be used for any C object collection (as well as the facil.io objects).
Published by boazsegev almost 7 years ago
Fix: (websocket_parser
)
The websocket parser had a rare memory offset and alignment handling issue in it's unmasking (XOR) logic and the new memory alignment protection code.
The issue would impact the parser in rare occasions when multiple messages where pipelined in the internal buffer and their length produced an odd alignment (the issue would occur with very fast clients, or a very stressed server).
The issue was discovering during testing of the 0.6.0-dev version branch and the fix was backported to the 0.5.x version.
Published by boazsegev almost 7 years ago
This version is a minor patch to the 0.5.7 version, which broke Linux compilation on some GCC versions:
Fix: (defer
, fiobj
) fix Linux compatibility concerns (when using GCC). Credit goes to @kotocom for opening issue #23.
Published by boazsegev almost 7 years ago
This release marks an improvement to the defer core. Next up are changes to the evio core which will probably require a version bump (from 0.5.x to 0.6.x).
This version includes the following changes:
Fix: (defer
) fixes the non-debug version of the new (v.0.5.6) defer, which didn't define some debug macros.
Fix: Added cmake_minimum_required
and related CMake fixes to the CMake file and generator. Credit to David MorΓ‘n (@david-moran) for PR #22 fixing the CMakelist.txt.
Compatibility: (websocket_parser
) removed unaligned memory access from the XOR logic in the parser, making it more compatible with older CPU systems that don't support unaligned memory access or 64 bit word lengths.
Optimization: (defer
) rewrote the data structure to use a hybrid cyclic buffer and linked list for the task queue (instead of a simple linked list), optimizing locality and minimizing memory allocations.
Misc: minor updates and tweaks, such as adding the fiobj_ary2prt
function for operations such as quick sort, updating some documentation etc'.
Published by boazsegev almost 7 years ago
Fix: (fiobj
) fixed an issue #21, where gcc
would complain about overwriting the fio_cstr_s
struct due to const
members. Credit to @vit1251 for exposing this issue.
Fix: (fiobj
) fixed NULL pointer testing for fiobj_free(NULL)
.
Fix/Compatibility: (gcc-6
) Fix some compatibility concerns with gcc
version 6, as well as some warnings that were exposed when testing with gcc
.
Optimization: (fiobj
) optimized the JSON parsing memory allocations as well as fixed some of the function declarations to add the const
keyword where relevant.
Published by boazsegev almost 7 years ago
The 0.5.4 release focused on updating the internal code's design and includes all the fixes and changes from the (unreleased) 0.5.3 code base
Some notable updates include native JSON support and the new fiobj
dynamic type system.
These include:
Change/Update: (fiobj
) The dynamic type library (a version 0.5.3 feature) was redesigned to make it extendable. This means that code that used type testing using a switch
statement needs to be rewritten.
Change: minor changes to the versioning scheme removed some version MACROS... this isn't API related, so I don't consider it a breaking change, but it might effect code that relied too much on internal workings. The only valid version macros are the FACIL_VERSION_*
macros, in the facil.h
header.
Change: (http
) the HTTP/1.x parser was re-written and replaced. It should perform the same, while being easier to maintain. Also, the new parser could potentially be used to author an HTTP client.
Change: (websocket
) the Websocket parser was re-written and replaced, decoupling the parser and message wrapper from the IO layer. Performance might slightly improve, but should mostly remain the same. However, the new code is easier to maintain and easier to port to other implementations. Also, the new parser supports a client mode (message masking).
Fix: (websocket
) issues with the new websocket parser were fixed. Credit to Tom Lahti (@uidzip) for exposing the issues.
Fix: (websocket
) fix #16, where a client's first message could have been lost due to long on_open
processing times. This was fixed by fragmenting the upgrade
event into two events, adding the facil_attach_locked
feature and attaching the new protocol before sending the response. Credit to @madsheep and @nilclass for exposing the issue and tracking it down to the on_open
callbacks.
Fix: (sock
) sockets created using the TCP/IP sock
library now use TCP_NODELAY
as the new default. This shouldn't be considered a breaking change as much as it should be considered a fix.
Fix: (http1
) HTTP/1.x is now more fragmented, avoiding a read
loop to allow for mid-stream / mid-processing protocol upgrades. This also fixes #16 at it's root (besides the improved websocket
callback handling).
Fix: (http1
) HTTP/1.x now correctly initializes the udata
pointer to NULL fore each new request.
Fix: (facil
) the facil_run_every
function now correctly calls the on_finish
callback when a timer initialization fails. This fixes a leak that could have occurred due to inconsistent API expectations. Workarounds written due to this issue should be removed.
Fix: (facil
) connection timeout is now correctly ignored for timers.
Fix: (defer
) a shutdown issue in defer_perform_in_fork
was detected by @cdkrot and his fix was implemented.
Fix: (evio
) fixed an issue where the evented IO library failed to reset the state indicator after evio_close
was called, causing some functions to believe that events are still processed. Now the evio_isactive
will correctly indicate that the evented IO is inactive after evio_close
was called.
Fix: (evio
) fixes an issue where evio_add_timer
would fail with EEXIST
instead of reporting success (this might be related to timer consolidation concerns in the Linux kernel).
Fix: (evio
) better timer fd
creation compatibility with different Linux kernels.
Fix: (documentation) credit to @cdkrot for reporting an outdated demo in the README.
Fix: (linking) added the missing -lm
linker flag for gcc
/Linux (I was using clang
, which automatically links to the math library, so I didn't notice this).
Portability: added extern "C"
directive for untested C++ support.
Feature: π added a CLI helper service, allowing easy parsing and publishing of possible command line arguments.
Feature: ππ added a dynamic type library to facil.io
's core, making some common web related tasks easier to manage.
Feature: πππ added native JSON support. JSON strings can be converted to fiobj_s *
objects and fiobj_s *
objects can be rendered as JSON! I'm hoping to get it benchmarked publicly.
Published by boazsegev over 7 years ago
Change: non-breaking changes to the folder structure are also reflected in the updated makefile
and .clang_complete
.
Fix: (defer
) Fixed SIGTERM
handling (signal was mistakingly filtered away).
Fix: (http_response
) Fixed http_response_sendfile2
where path concatenation occurred without a folder separator (/
) and exclusively safe file paths were being ignored (the function assumed an unsafe path to be used, at least in part).
Fix: minor fixes and documentation.
Fix / Feature: (facil
) sibling processes will now detect a sibling's death (caused by a crashed process) and shutdown.
Feature: @benjcal suggested the script used to create new applications. The current version is a stand-in draft used for testing.
Feature: Temporary boiler plate code for a simple "hello world" HTTP application using the new application script (see the README). This is a temporary design to allow us to test the script's functionality and decide on the final boiler plate's design.
Published by boazsegev over 7 years ago
Fix: (sock
) Fixed an issue where sock_flush
would always invoke sock_touch
, even if no data was actually sent on the wire.
Fix: (sock
) fixed a possible issue with sock_flush_strong
which might have caused the facil.io to hang.
Fix: (Websocket
) fixed an issue with fragmented pipelined Websocket messages and the security patch that was used to prevent such cases from monopolizing resources.
Feature: (facil
) easily force an IO event, even if it did not occur, using facil_force_event
.
Published by boazsegev over 7 years ago
Braking changes: (pubsub
) The API was changed / updated, making pubsub_engine_s
objects easier to author and allowing allocations to be avoided by utilizing two void * udata
fields... Since this is a breaking change, and following semantic versioning, the minor version is updated. I do wish I could have delayed the version bump, as the roadmap ahead is long, but it is what it is.
Braking changes: (facil
) Since the API is already changing a bit, I thought I'd clean it up a bit and have all the on_X
flow events (on_close
, on_fail
, on_start
...) share the same function signature where possible.
Changes: (facil
) Minor changes to the fio_cluster_*
API now use signed message types. All negative msg_type
values are reserved for internal use.
Fix: plugging memory leaks while testing the system under very high stress.
Fix: (pubsub
, fio_dict
) Fixed glob pattern matching... I hope. It seems to work fine, but I'm not sure it the algorithm matches the Redis implementation which is the de-facto standard for channel pattern matching.
Security: (http
) the HTTP parser now breaks pipelined HTTP requests into fragmented events, preventing an attacker from monopolizing requests through endless pipelining of requests that have a long processing time.
Fix: (http
) http_listen
will now always copy the string for the public_folder
, allowing dynamic strings to be safely used.
Fix: (http
) default error files weren't located due to missing /
in name. Fixed by adjusting the requirement for the /
to be more adaptive.
Fix: (http
) dates were off by 1 day. Now fixed.
Fix: (http1
) a minor issue in the on_data
callback could have caused the parser to crash in rare cases of fragmented pipelined requests on slower connections. This is now fixed.
Fix?: (http
) When decoding the path or a request, the +
sign is now left unencoded (correct behavior), trusting in better clients in this great jungle.
Fix: (facil
) facil_defer
would leak memory if a connection was disconnected while a task was scheduled.
Fix: (facil
) facil_connect
now correctly calls the on_fail
callback even on immediate failures (i.e. when the function call was missing a target address and port).
Fix: (facil
) facil_connect
can now be called before other socket events (protected form library initialization conflicts).
Fix: (facil
) facil_listen
will now always copy the string for the port
, allowing dynamic strings to be safely used when FACIL_PRINT_STATE
is set.
Fix: (facil
) facil_last_tick
would crash if called before the library was initialized during socket operations (facil_listen
, facil_attach
, etc')... now facil_last_tick
falls back to time()
if nothing happened yet.
Fix: (facil
) .on_idle
now correctly checks for non networks events as well before the callback is called.
Fix: (defer
) A large enough (or fast enough) thread pool in a forked process would complete the existing tasks before the active flag was set, causing the facil.io reactor to be stranded in an unscheduled mode, as if expecting to exit. This is now fixed by setting a temporary flag pointer for the forked children, preventing a premature task cleanup.
Changes: Major folder structure updates make development and support for CMake submodules easier. These changes should also make it easier to push PRs for by offering the dev
folder for any localized testing prior to submitting the PR.
Feature: (websockets
) The websocket pub/sub support is here - supporting protocol tasks as well as direct client publishsing (and autu text/binary detection)! There are limits and high memory costs related to channel names, since pubsub
uses a trie for absolute channel matching (i.e. channel name length should be short, definitely less than 1024Bytes).
Feature: (redis
) The websocket pub/sub support features a shiny new Redis engine to synchronize pub/sub across machines! ... I tested it as much as I could, but I know my tests are as buggy as my code, so please test before using.
Feature: (facil_listen
, http_listen
) supports an optional on_finish_rw
callback to clean-up the rw_udata
object.
Feature: (pubsub
) channels now use the available fio_dict_s
(trie) data store. The potential price of the larger data-structure is elevated by it's absolute protection against hash collisions. Also, I hope that since channels are more often searched than created, this should improve performance when searching for channels by both pattern and perfect match. I hope this combination of hash tables (for client lookup) and tries (for channel traversal) will provide the best balance between string matching, pattern matching, iterations and subscription management.
Feature: (http
) http_listen
now supports an on_finish
callback.
Feature: (http1
) HTTP/1.1 will, in some cases, search for available error files (i.e. "400.html") in the public_folder
root, allowing for custom error messages.
Feature: CMake inclusion. Credit to @OwenDelahoy (PR#8).
To use facil.io in a CMake build you may add it as a submodule to the project's repository.
git submodule add https://github.com/boazsegev/facil.io.git
Then add the following line the project's
CMakeLists.txt
add_subdirectory(facil.io)
Optimize: (fio_hash_table
) optimize fio_ht_s
bin memory allocations.