Giter Club home page Giter Club logo

faststring's Introduction

FastString

Fast, in stack, fixed size string implementation with constexpr noexcept constructors and accessors. FastString improves memory locality and latency of strings by avoiding heap allocations.

Abstract

std::string allocates heap memory for strings not qualified for SSO (small string optimization) and reduces memory locality. FastString is a thin wrapper around a plain char array with constexpr noexcept constructors and accessors for fast, in stack string manipulation. FastString is a fast and efficient alternative for std::string or plain char arrays in low latency applications and can be easily used with std::string_view for further operations.

Requirements

  • C++20 compatible compiler (constexpr std::copy is required for constexpr constructors)
  • Works with
    • Microsoft (R) C/C++ Optimizing Compiler Version 19.27.29111 or above
    • x86-64 gcc-trunk

Build

mkdir build && cd build && cmake .. && make

Performance

  • Compiler version:MSVC 19.28.29334.0
  • Using Google Benchmark (Tests are included in repo)
Run on (8 X 1498 MHz CPU s)
CPU Caches:
  L1 Data 48 KiB (x4)
  L1 Instruction 32 KiB (x4)
  L2 Unified 512 KiB (x4)
  L3 Unified 8192 KiB (x1)
--------------------------------------------------------------------------------------
Benchmark                                            Time             CPU   Iterations
--------------------------------------------------------------------------------------
BM_std_string_from_const_char                      498 ns          148 ns      5600000
BM_fixed_size_str_from_const_char                 46.9 ns         16.3 ns     34461538
BM_std_string_from_constexpr_const_char            500 ns          153 ns      4480000
BM_fixed_size_str_from_constexpr_const_char       47.8 ns         16.7 ns     37333333
BM_std_string_from_buffer                          505 ns          158 ns      5146257
BM_fixed_size_str_from_buffer                     49.6 ns         14.2 ns     37333333
BM_std_string_from_constexpr_buffer                503 ns          188 ns      4072727
BM_fixed_size_str_from_constexpr_buffer           50.1 ns         12.6 ns     44800000
BM_std_string_from_const_char_large_str           1048 ns          384 ns      2240000
BM_fixed_size_str_from_const_char_large_str        153 ns         50.0 ns     10000000
BM_std_string_append                               190 ns         62.5 ns     10000000
BM_fixed_size_str_append                           164 ns         56.2 ns     14451613
BM_std_string_append_large                        50.0 ns         16.4 ns     64000000
BM_fixed_size_str_append_large                    61.5 ns         23.4 ns     37333333
  • Compiler version: x86-64 gcc-trunk
  • Test scenario - Function creates a string from a given char pointer and return length of the created string. Length is returned and assigned to a volatile variable to avoid compiler optimizing out the construction of the variable.
  • Test code
    • Using std::string
      auto f(const char* str)
      {
          std::string a{str};
          return a.length();
      }
      
      void g(const char* str)
      {
          volatile auto x = f(str);
      }
    • Using FastString. Note use of constexpr and noexcept
      constexpr auto f(const char* str) noexcept
      {
          using string64 = fss::fixed_size_str<63>;
          string64 a{str};
          return a.length(); 
      }
      
      void g(const char* str)
      {
          volatile auto x = f(str);
      }
  • Comparison of compiler output between std::string and FastString using https://godbolt.org/ image

Usage

Refer to below example code

    /* define types */
    using string8 = fss::fixed_size_str<7>;
    using string64 = fss::fixed_size_str<63>;

    /* default construction */
    constexpr string8 a{};
    constexpr auto a_length = a.length();               // a_length is 0
    constexpr auto a_empty = a.empty();                 // a_empty is true
    constexpr auto a_max_size = a.max_size();           // a_max_size is 7

    /* copy construction */
    constexpr auto a_copy_c = a;
    auto a_copy = a;

    /* move construction */
    auto a_move = std::move(a_copy);

    /* copy assignment */
    constexpr string8 b{ "1234", 4 };                   // b is "1234"
    string8 c{ "lmnopqrstuvxyz" };                      // c is "lmnopqr"
    string8 d{ "56789" };                               // d is "789". rest is truncated.
    c = b;                                              // now c is "1234"

    /* move assingment */
    c = std::move(d);                                   // c is "56789"

    /* using with string view */
    constexpr string8 e{ "abcdefghij", 10 };            // truncated. e is "abcdefg";
    constexpr auto e_sub_str = e.str().substr(0, 2);    // e_sub_str is "ab"
    constexpr auto e_length = e.length();               // e_length is 7

    /* comparison */
    constexpr string8 f{ "abcd" };
    constexpr string8 g{ "abcd" };
    constexpr string8 h{ "abcf" };
    constexpr auto i = (f == g);                        // i is true 
    constexpr auto j = (g == h);                        // j is false

    /* append */
    string8 k{ "abc" };                                 // k is "abc"
    k.append("d");                                      // k is "abcd"
    k.append("efghi", 5);                               // k is "abcdefg". rest is truncated

    /* clear */
    k.clear();                                          // k is empty() ""
    auto k_empty = k.empty();                           // k_empty is true

    /* reset */
    k.reset("1234");                                    // k is "1234";
    auto k_length = k.length();                         // k_length is 4
    k.reset("xyz", 3);                                  // k is "xyz"

    /* remove_suffix */
    /* there is no boundary check. similar to string_view */
    string8 l{ "1234567" };
    l.remove_suffix(3);                                 // l is "1234"

    /* remove_prefix */
    /* there is no boundary check. similar to string_view */
    l.remove_prefix(2);                                 // l is "34"

    /* stream operator */
    std::cout << l << std::endl;

    /* using for member variables */
    struct test_struct
    {
        std::uint32_t a_{};
        std::uint64_t b_{};
        string8 c_{ "abcd" };                           // uses only 8 + 4 bytes in stack

        constexpr auto get_c() const { return c_.str(); }
        constexpr void set_c(const char* str) { c_.reset(str); }
    };

    auto test_struct_size = sizeof(test_struct);
    constexpr test_struct t;
    constexpr auto t_a = t.get_c();

    /* swap */
    l.swap(k);                                          // l is "xyz" and k is "34"
    swap(l, k);                                         // l is "34" and k is "xyz"

faststring's People

Contributors

abeimler avatar m3janitha avatar

Stargazers

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

Watchers

 avatar  avatar

faststring's Issues

What's the license?

I'd like to use this in a GPL project.
I don't see any license specified. What license is used here?

Thanks a lot!

Example fails to compile (gcc 12.2.1)

Nice library. Here are the issues:

  1. example.cpp needs a #include <cstdint> for std::uint32_t support

  2. Here is the other compile errors:

[ 25%] Building CXX object example/CMakeFiles/examples.dir/main.cpp.o
cd /home/twigger/faststring/FastString/example && /usr/bin/c++  -I/home/twigger/faststring/FastString/include -O3 -O3 -DNDEBUG -std=c++20 -Wall -Wextra -pedantic -Werror -MD -MT example/CMakeFiles/examples.dir/main.cpp.o -MF CMakeFiles/examples.dir/main.cpp.o.d -o CMakeFiles/examples.dir/main.cpp.o -c /home/twigger/faststring/FastString/example/main.cpp
/home/twigger/faststring/FastString/example/main.cpp: In function ‘int main()’:
/home/twigger/faststring/FastString/example/main.cpp:39:51: error: ‘std::basic_string_view<char>{2, ((const char*)(& e.fss::basic_str<char, 7, std::char_traits<char> >::buffer_))}’ is not a constant expression
   39 |     constexpr auto e_sub_str = e.str().substr(0, 2);    // e_sub_str is "ab"
      |                                                   ^
/home/twigger/faststring/FastString/example/main.cpp:96:40: error: ‘std::basic_string_view<char>{4, ((const char*)(& t.main()::test_struct::c_.fss::basic_str<char, 7, std::char_traits<char> >::buffer_))}’ is not a constant expression
   96 |     constexpr const auto t_a = t.get_c();
      |                                        ^
make[2]: *** [example/CMakeFiles/examples.dir/build.make:79: example/CMakeFiles/examples.dir/main.cpp.o] Error 1
  1. Finally you use std::size_t for your size type. This needlessly makes, eg, string64 take up 8 more bytes than necessary. Why not use something like uint8_t and have a static_assert that the size is suitable for the capacity. Or even better, have a template argument for the size type, eg using string64 = fss::fixed_size_str<62, std::uint8_t>;

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.