|
39 | 39 | #include <vector> |
40 | 40 |
|
41 | 41 | #include "test_suite.hpp" |
| 42 | +#include "canada.hpp" |
| 43 | +#include "citm_catalog.hpp" |
42 | 44 |
|
43 | 45 | /* References |
44 | 46 |
|
|
48 | 50 | */ |
49 | 51 |
|
50 | 52 | std::string s_tests = "ps"; |
51 | | -std::string s_impls = "busorn"; |
| 53 | +std::string s_impls = "busodrn"; |
52 | 54 | std::size_t s_trials = 6; |
53 | 55 | std::string s_branch = ""; |
54 | 56 | std::string s_alloc = "p"; |
@@ -747,6 +749,173 @@ class boost_operator_impl : public any_impl |
747 | 749 | } |
748 | 750 | }; |
749 | 751 |
|
| 752 | +class boost_direct_impl : public any_impl |
| 753 | +{ |
| 754 | +private: |
| 755 | + struct canada_support |
| 756 | + { |
| 757 | + using type = canada; |
| 758 | + static constexpr char const* const name = "canada.json"; |
| 759 | + }; |
| 760 | + struct citm_catalog_support |
| 761 | + { |
| 762 | + using type = citm_catalog; |
| 763 | + static constexpr char const* const name = "citm_catalog.json"; |
| 764 | + }; |
| 765 | + using supported_files = mp11::mp_list< |
| 766 | + canada_support, citm_catalog_support>; |
| 767 | + |
| 768 | + static |
| 769 | + int |
| 770 | + find_supported_file(file_item const& fi) |
| 771 | + { |
| 772 | + int result = -1; |
| 773 | + using N = mp11::mp_size<supported_files>; |
| 774 | + mp11::mp_for_each<mp11::mp_iota<N>>([&](auto index) |
| 775 | + { |
| 776 | + using supported_file = mp11::mp_at_c<supported_files, index.value>; |
| 777 | + std::size_t const name_len = std::strlen(supported_file::name); |
| 778 | + |
| 779 | + std::size_t pos = fi.name.rfind( |
| 780 | + supported_file::name, string_view::npos, name_len); |
| 781 | + if(pos == string_view::npos) |
| 782 | + return; |
| 783 | + if( pos + name_len != fi.name.size() ) |
| 784 | + return; |
| 785 | + if( pos != 0 && fi.name[pos - 1] != '/' |
| 786 | + && fi.name[pos - 1] != '\\' ) |
| 787 | + { |
| 788 | + return; |
| 789 | + } |
| 790 | + |
| 791 | + result = static_cast<int>(index); |
| 792 | + }); |
| 793 | + return result; |
| 794 | + } |
| 795 | + |
| 796 | +public: |
| 797 | + boost_direct_impl(bool with_file_io, parse_options const& popts) |
| 798 | + : any_impl("boost (direct)", true, false, with_file_io, popts) |
| 799 | + {} |
| 800 | + |
| 801 | + clock_type::duration |
| 802 | + parse_string(file_item const& fi, std::size_t repeat) const override |
| 803 | + { |
| 804 | + auto const i = find_supported_file(fi); |
| 805 | + if( i < 0 ) |
| 806 | + return clock_type::duration::zero(); |
| 807 | + |
| 808 | + using N = mp11::mp_size<supported_files>; |
| 809 | + return mp11::mp_with_index<N>(i, [&](auto index) |
| 810 | + { |
| 811 | + using supported_file = mp11::mp_at_c<supported_files, index.value>; |
| 812 | + |
| 813 | + auto const start = clock_type::now(); |
| 814 | + while(repeat--) |
| 815 | + { |
| 816 | + using data_type = typename supported_file::type; |
| 817 | + data_type v; |
| 818 | + system::error_code ec; |
| 819 | + parser_for<data_type> p(get_parse_options(), &v); |
| 820 | + |
| 821 | + auto const n = p.write_some( |
| 822 | + false, fi.text.data(), fi.text.size(), ec ); |
| 823 | + if( !ec.failed() && n < fi.text.size() ) |
| 824 | + ec = error::extra_data; |
| 825 | + if( ec.failed() ) |
| 826 | + throw system::system_error( ec ); |
| 827 | + } |
| 828 | + return clock_type::now() - start; |
| 829 | + }); |
| 830 | + } |
| 831 | + |
| 832 | + clock_type::duration |
| 833 | + parse_file(file_item const& fi, std::size_t repeat) const override |
| 834 | + { |
| 835 | + auto const i = find_supported_file(fi); |
| 836 | + if( i < 0 ) |
| 837 | + return clock_type::duration::zero(); |
| 838 | + |
| 839 | + using N = mp11::mp_size<supported_files>; |
| 840 | + return mp11::mp_with_index<N>(i, [&](auto index) |
| 841 | + { |
| 842 | + using supported_file = mp11::mp_at_c<supported_files, index.value>; |
| 843 | + |
| 844 | + auto const start = clock_type::now(); |
| 845 | + char s[ BOOST_JSON_STACK_BUFFER_SIZE]; |
| 846 | + while(repeat--) |
| 847 | + { |
| 848 | + using data_type = typename supported_file::type; |
| 849 | + data_type v; |
| 850 | + system::error_code ec; |
| 851 | + parser_for<data_type> p(get_parse_options(), &v); |
| 852 | + |
| 853 | + FILE* f = fopen(fi.name.data(), "rb"); |
| 854 | + |
| 855 | + while( true ) |
| 856 | + { |
| 857 | + std::size_t const sz = fread(s, 1, sizeof(s), f); |
| 858 | + if( ferror(f) ) |
| 859 | + break; |
| 860 | + |
| 861 | + p.write_some(true, s, sz, ec); |
| 862 | + if( ec.failed() ) |
| 863 | + throw system::system_error(ec); |
| 864 | + |
| 865 | + if( feof(f) ) |
| 866 | + break; |
| 867 | + } |
| 868 | + |
| 869 | + if( !p.done() ) |
| 870 | + { |
| 871 | + p.write_some(false, nullptr, 0, ec); |
| 872 | + if( ec.failed() ) |
| 873 | + throw system::system_error(ec); |
| 874 | + } |
| 875 | + |
| 876 | + fclose(f); |
| 877 | + } |
| 878 | + return clock_type::now() - start; |
| 879 | + }); |
| 880 | + } |
| 881 | + |
| 882 | + clock_type::duration |
| 883 | + serialize_string(file_item const& fi, std::size_t repeat) const override |
| 884 | + { |
| 885 | + auto const i = find_supported_file(fi); |
| 886 | + if( i < 0 ) |
| 887 | + return clock_type::duration::zero(); |
| 888 | + |
| 889 | + using N = mp11::mp_size<supported_files>; |
| 890 | + return mp11::mp_with_index<N>(i, [&](auto index) |
| 891 | + { |
| 892 | + using supported_file = mp11::mp_at_c<supported_files, index.value>; |
| 893 | + typename supported_file::type v; |
| 894 | + json::parse_into(v, fi.text); |
| 895 | + |
| 896 | + auto const start = clock_type::now(); |
| 897 | + serializer sr; |
| 898 | + string out; |
| 899 | + out.reserve(512); |
| 900 | + while(repeat--) |
| 901 | + { |
| 902 | + sr.reset(&v); |
| 903 | + out.clear(); |
| 904 | + for(;;) |
| 905 | + { |
| 906 | + auto const sv = sr.read( |
| 907 | + out.end(), out.capacity() - out.size() ); |
| 908 | + out.grow( sv.size() ); |
| 909 | + if( sr.done() ) |
| 910 | + break; |
| 911 | + out.reserve( out.capacity() + 1 ); |
| 912 | + } |
| 913 | + } |
| 914 | + return clock_type::now() - start; |
| 915 | + }); |
| 916 | + } |
| 917 | +}; |
| 918 | + |
750 | 919 | //---------------------------------------------------------- |
751 | 920 |
|
752 | 921 | #ifdef BOOST_JSON_HAS_RAPIDJSON |
@@ -988,6 +1157,10 @@ bool add_impl(impl_list & vi, char kind, char alloc, char io, char num) |
988 | 1157 | is_pool, with_file_io, popts); |
989 | 1158 | break; |
990 | 1159 |
|
| 1160 | + case 'd': |
| 1161 | + impl = std::make_unique<boost_direct_impl>(with_file_io, popts); |
| 1162 | + break; |
| 1163 | + |
991 | 1164 | #ifdef BOOST_JSON_HAS_RAPIDJSON |
992 | 1165 | case 'r': |
993 | 1166 | if(is_pool) |
@@ -1058,35 +1231,36 @@ main( |
1058 | 1231 | std::cerr << |
1059 | 1232 | "Usage: bench [options...] <file>...\n" |
1060 | 1233 | "\n" |
1061 | | - "Options: -t:[p][s] Test parsing, serialization or both\n" |
1062 | | - " (default both)\n" |
1063 | | - " -i:[b][u][s][o][r][n] Test the specified implementations\n" |
1064 | | - " (b: Boost.JSON)\n" |
1065 | | - " (u: Boost.JSON, null parser)\n" |
1066 | | - " (s: Boost.JSON, convenient functions)\n" |
1067 | | - " (o: Boost.JSON, stream operators)\n" |
| 1234 | + "Options: -t:[p][s] Test parsing, serialization or both\n" |
| 1235 | + " (default both)\n" |
| 1236 | + " -i:[b][u][s][o][d][r][n] Test the specified implementations\n" |
| 1237 | + " (b: Boost.JSON)\n" |
| 1238 | + " (u: Boost.JSON, null parser)\n" |
| 1239 | + " (s: Boost.JSON, convenient functions)\n" |
| 1240 | + " (o: Boost.JSON, stream operators)\n" |
| 1241 | + " (d: Boost.JSON, direct conversion)\n" |
1068 | 1242 | #ifdef BOOST_JSON_HAS_RAPIDJSON |
1069 | | - " (r: RapidJSON)\n" |
| 1243 | + " (r: RapidJSON)\n" |
1070 | 1244 | #endif // BOOST_JSON_HAS_RAPIDJSON |
1071 | 1245 | #ifdef BOOST_JSON_HAS_NLOHMANN_JSON |
1072 | | - " (n: nlohmann/json)\n" |
| 1246 | + " (n: nlohmann/json)\n" |
1073 | 1247 | #endif // BOOST_JSON_HAS_NLOHMANN_JSON |
1074 | | - " (default all)\n" |
1075 | | - " -a:(p|d) Memory allocation strategy\n" |
1076 | | - " (p: memory pool)\n" |
1077 | | - " (d: default strategy)\n" |
1078 | | - " (default memory pool)\n" |
1079 | | - " -n:<number> Number of trials (default 6)\n" |
1080 | | - " -b:<branch> Branch label for boost implementations\n" |
1081 | | - " -m:(i|p|n) Number parsing mode\n" |
1082 | | - " (i: imprecise)\n" |
1083 | | - " (p: precise)\n" |
1084 | | - " (n: none)\n" |
1085 | | - " (default imprecise)\n" |
1086 | | - " -f:(y|n) Include file IO into consideration when testing parsers\n" |
1087 | | - " (y: yes)\n" |
1088 | | - " (n: no)\n" |
1089 | | - " (default no)\n" |
| 1248 | + " (default all)\n" |
| 1249 | + " -a:[p][d] Memory allocation strategy\n" |
| 1250 | + " (p: memory pool)\n" |
| 1251 | + " (d: default strategy)\n" |
| 1252 | + " (default memory pool)\n" |
| 1253 | + " -n:<number> Number of trials (default 6)\n" |
| 1254 | + " -b:<branch> Branch label for boost implementations\n" |
| 1255 | + " -m:[i][p][n] Number parsing mode\n" |
| 1256 | + " (i: imprecise)\n" |
| 1257 | + " (p: precise)\n" |
| 1258 | + " (n: none)\n" |
| 1259 | + " (default imprecise)\n" |
| 1260 | + " -f:[y][n] Include file IO into consideration when testing parsers\n" |
| 1261 | + " (y: yes)\n" |
| 1262 | + " (n: no)\n" |
| 1263 | + " (default no)\n" |
1090 | 1264 | ; |
1091 | 1265 |
|
1092 | 1266 | return 4; |
|
0 commit comments