parsing strings uses SSE2

This commit is contained in:
Vinnie Falco 2019-11-01 12:48:05 -07:00
parent c1ef2ab337
commit fbff4f97a3
5 changed files with 91 additions and 41 deletions

View File

@ -444,7 +444,7 @@ main(
//vi.emplace_back(new nlohmann_impl);
benchParse(vs, vi);
benchSerialize(vs, vi);
//benchSerialize(vs, vi);
}
catch(system_error const& se)
{

View File

@ -35,43 +35,6 @@ struct parser_base
return 10 + c - 'a';
return -1;
}
static
int
utf8_encode(
char* dest,
unsigned long cp)
{
if(cp < 0x80)
{
dest[0] = static_cast<char>(cp);
return 1;
}
if(cp < 0x800)
{
dest[0] = static_cast<char>( (cp >> 6) | 0xc0);
dest[1] = static_cast<char>( (cp & 0x3f) | 0x80);
return 2;
}
if(cp < 0x10000)
{
dest[0] = static_cast<char>( (cp >> 12) | 0xe0);
dest[1] = static_cast<char>(((cp >> 6) & 0x3f) | 0x80);
dest[2] = static_cast<char>( (cp & 0x3f) | 0x80);
return 3;
}
{
dest[0] = static_cast<char>( (cp >> 18) | 0xf0);
dest[1] = static_cast<char>(((cp >> 12) & 0x3f) | 0x80);
dest[2] = static_cast<char>(((cp >> 6) & 0x3f) | 0x80);
dest[3] = static_cast<char>( (cp & 0x3f) | 0x80);
return 4;
}
}
};
} // detail

View File

@ -52,8 +52,6 @@
# endif
#endif
#define BOOST_JSON_VALUE_IS_TRIVIAL
#ifndef BOOST_NO_EXCEPTIONS
# define BOOST_JSON_THROW(x) throw(x)
#else
@ -62,4 +60,16 @@
#define BOOST_JSON_STATIC_ASSERT( ... ) static_assert(__VA_ARGS__, #__VA_ARGS__)
// optimizations
#define BOOST_JSON_VALUE_IS_TRIVIAL
#ifndef BOOST_JSON_NO_SSE2
# if (defined(_M_IX86) && _M_IX86_FP == 2) || \
defined(_M_X64) || defined(__SSE2__)
# define BOOST_JSON_USE_SSE2
# endif
#endif
#endif

View File

@ -0,0 +1,75 @@
//
// Copyright (c) 2018-2019 Vinnie Falco (vinnie dot falco at gmail dot com)
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//
// Official repository: https://github.com/vinniefalco/json
//
#ifndef BOOST_JSON_DETAIL_SSE2_HPP
#define BOOST_JSON_DETAIL_SSE2_HPP
#include <boost/json/detail/config.hpp>
#ifdef BOOST_JSON_USE_SSE2
#include <emmintrin.h>
#include <xmmintrin.h>
#endif
namespace boost {
namespace json {
namespace detail {
#ifdef BOOST_JSON_USE_SSE2
inline
unsigned long long
count_unescaped(
char const* s,
unsigned long long n) noexcept
{
__m128i const q1 = _mm_set1_epi8( '"' );
__m128i const q2 = _mm_set1_epi8( '\\' );
__m128i const q3 = _mm_set1_epi8( 0x20 );
char const * s0 = s;
while( n >= 16 )
{
__m128i v1 = _mm_loadu_si128( (__m128i const*)s );
__m128i v2 = _mm_cmpeq_epi8( v1, q1 );
__m128i v3 = _mm_cmpeq_epi8( v1, q2 );
__m128i v4 = _mm_cmplt_epi8( v1, q3 );
__m128i v5 = _mm_or_si128( v2, v3 );
__m128i v6 = _mm_or_si128( v5, v4 );
int w = _mm_movemask_epi8( v6 );
if( w != 0 ) break;
s += 16;
n -= 16;
}
return s - s0;
};
#else
inline
unsigned long long
count_unescaped(
char const*,
unsigned long long) noexcept
{
return 0;
}
#endif
} // detail
} // json
} // boost
#endif

View File

@ -12,8 +12,9 @@
#include <boost/json/basic_parser.hpp>
#include <boost/json/error.hpp>
#include <boost/json/detail/buffer.hpp>
#include <boost/json/detail/assert.hpp>
#include <boost/json/detail/buffer.hpp>
#include <boost/json/detail/sse2.hpp>
namespace boost {
namespace json {
@ -516,6 +517,7 @@ loop_string:
auto const start = p;
while(p < p1)
{
p += detail::count_unescaped(p, p1 - p);
if(*p == '\"')
{
if(is_key_)