47 Commits

Author SHA1 Message Date
  Arcueid fafc2217fe remove obsolete files 8 months ago
  wesley 824f0600a0 finish benchmark report 8 months ago
  wesley 427367f144 Merge branch 'main' into wesley 8 months ago
  wesley ce7a5410ed Merge remote-tracking branch 'refs/remotes/origin/main' 8 months ago
  wesley d0c73b4899 small fix 8 months ago
  Arcueid b6aceb37db update report 8 months ago
  Arcueid 8dd61a1e16 update design and report doc 8 months ago
  wesley af7c4c5041 testing 8 months ago
  wesley 9a36e35ed6 bench_test modify arg 8 months ago
  wesley 296d539d35 Merge branch 'main' into wesley 8 months ago
  wesley 32e61b5e29 Merge remote-tracking branch 'refs/remotes/origin/main' 8 months ago
  wesley 65cfa75cf2 fix 8 months ago
  ArcueidType 30e2712000 add write bytes info 8 months ago
  wesley 23899cf93b test again to better 8 months ago
  wesley ba547f458d Merge branch 'main' into wesley 8 months ago
  wesley a0f1e5ad83 Merge remote-tracking branch 'refs/remotes/origin/main' 8 months ago
  wesley ccb5e35e2b test_bench ver2 8 months ago
  ArcueidType 6c04c50aae parse file name bug fix 8 months ago
  wesley 9307ace9bc Merge branch 'main' into wesley 8 months ago
  wesley 328a8b3cc6 Merge remote-tracking branch 'refs/remotes/origin/main' 8 months ago
  ArcueidType 17bac7d6d6 manager permanent bug fix 8 months ago
  ArcueidType e93419c268 gc bug fix 8 months ago
  wesley 3d9eddf44f Merge branch 'main' into wesley 8 months ago
  wesley 45e1148a9c Merge remote-tracking branch 'refs/remotes/origin/main' 8 months ago
  ArcueidType 6a7aa874b1 gc bug fix 8 months ago
  wesley fbc2471200 Merge branch 'main' into wesley 8 months ago
  wesley 18ea460b40 Merge remote-tracking branch 'refs/remotes/origin/main' 8 months ago
  wesley b9ae0741c5 maybe fix 8 months ago
  ArcueidType 0d069e81e7 fix ~dbimpl 8 months ago
  wesley 57f68f119d Merge branch 'main' into wesley 8 months ago
  wesley 0ae41c46ef Merge remote-tracking branch 'refs/remotes/origin/main' 8 months ago
  ArcueidType 339d0a57c0 add size method for fields 8 months ago
  wesley 7578f5d728 test_bench ver1 8 months ago
  wesley ebecd08378 Merge branch 'main' into wesley 8 months ago
  wesley 97cbccbc4f Merge remote-tracking branch 'refs/remotes/origin/main' 8 months ago
  李畅 b31487747b benchmark test with diff args 8 months ago
  ArcueidType 096f6fddfb gc function 8 months ago
  李畅 52e7b38f62 ver1 bug fix again 8 months ago
  李畅 071dffd533 unnecessary modeldb ignored 8 months ago
  李畅 5901b845ed ver1 bug fix 8 months ago
  李畅 2e031d6c63 Merge branch 'main' into wesley 8 months ago
  李畅 e4eb3154ae benchmark test_1 8 months ago
  ArcueidType 568fe7ac2e vtable manager 8 months ago
  李畅 f5d9f6bb32 benchmark test_0 9 months ago
  ArcueidType 39187ba9d5 modify experiment config 9 months ago
  ArcueidType f1d10e175c benmark bug fixed 9 months ago
  Arcueid 1118a1c75c some fix 9 months ago
51 changed files with 3287 additions and 845 deletions
Unified View
  1. +1
    -0
      .gitignore
  2. +0
    -8
      .idea/.gitignore
  3. +0
    -1
      .idea/.name
  4. +0
    -2
      .idea/LevelDB-KV-Separation.iml
  5. +0
    -106
      .idea/codeStyles/Project.xml
  6. +0
    -5
      .idea/codeStyles/codeStyleConfig.xml
  7. +0
    -580
      .idea/editor.xml
  8. +0
    -13
      .idea/misc.xml
  9. +0
    -8
      .idea/modules.xml
  10. +0
    -8
      .idea/vcs.xml
  11. +20
    -4
      CMakeLists.txt
  12. +222
    -66
      PLAN.md
  13. +687
    -1
      README.md
  14. BIN
      assets/Insert_static_vsize.png
  15. BIN
      assets/db_bench_1.jpg
  16. BIN
      assets/db_bench_2.jpg
  17. BIN
      assets/db_bench_new.png
  18. BIN
      assets/fields.png
  19. BIN
      assets/gc.png
  20. BIN
      assets/kvsep_overview.png
  21. BIN
      assets/meta.png
  22. BIN
      assets/randvalue.png
  23. BIN
      assets/sst_value.png
  24. BIN
      assets/vtable.png
  25. BIN
      assets/vtable_index.png
  26. BIN
      assets/writeampli.png
  27. +19
    -3
      benchmarks/db_bench.cc
  28. +1248
    -0
      benchmarks/db_bench_new.cc
  29. +16
    -3
      db/builder.cc
  30. +4
    -1
      db/builder.h
  31. +142
    -19
      db/db_impl.cc
  32. +3
    -0
      db/db_impl.h
  33. +2
    -0
      db/dbformat.h
  34. +2
    -1
      db/fields.cc
  35. +3
    -0
      db/fields.h
  36. +10
    -1
      db/filename.cc
  37. +5
    -1
      db/filename.h
  38. +3
    -1
      db/repair.cc
  39. +3
    -1
      include/leveldb/options.h
  40. +7
    -1
      include/leveldb/status.h
  41. +1
    -0
      table/vtable_builder.cc
  42. +5
    -0
      table/vtable_builder.h
  43. +15
    -4
      table/vtable_format.h
  44. +195
    -0
      table/vtable_manager.cc
  45. +75
    -0
      table/vtable_manager.h
  46. +18
    -3
      table/vtable_reader.cc
  47. +11
    -0
      table/vtable_reader.h
  48. +2
    -2
      test/test_basicio.cc
  49. +290
    -0
      test/test_bench.cc
  50. +276
    -0
      test/test_bench_gc.cc
  51. +2
    -2
      test/test_fields.cc

+ 1
- 0
.gitignore View File

@ -3,6 +3,7 @@ build/
xcuserdata xcuserdata
cmake-build-debug/ cmake-build-debug/
.idea/ .idea/
.vscode/
bazel-bin bazel-bin
bazel-genfiles bazel-genfiles
bazel-googletest bazel-googletest

+ 0
- 8
.idea/.gitignore View File

@ -1,8 +0,0 @@
# Default ignored files
/shelf/
/workspace.xml
# Editor-based HTTP Client requests
/httpRequests/
# Datasource local storage ignored files
/dataSources/
/dataSources.local.xml

+ 0
- 1
.idea/.name View File

@ -1 +0,0 @@
leveldb

+ 0
- 2
.idea/LevelDB-KV-Separation.iml View File

@ -1,2 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<module classpath="CMake" type="CPP_MODULE" version="4" />

+ 0
- 106
.idea/codeStyles/Project.xml View File

@ -1,106 +0,0 @@
<component name="ProjectCodeStyleConfiguration">
<code_scheme name="Project" version="173">
<RiderCodeStyleSettings>
<option name="/Default/CodeStyle/CodeFormatting/CppClangFormat/EnableClangFormatSupport/@EntryValue" value="true" type="bool" />
<option name="/Default/CodeStyle/EditorConfig/EnableClangFormatSupport/@EntryValue" value="false" type="bool" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/ALIGN_MULTILINE_BINARY_EXPRESSIONS_CHAIN/@EntryValue" value="true" type="bool" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/ALIGN_MULTILINE_CALLS_CHAIN/@EntryValue" value="false" type="bool" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/ALIGN_MULTILINE_EXPRESSION/@EntryValue" value="false" type="bool" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/ALIGN_MULTILINE_FOR_STMT/@EntryValue" value="true" type="bool" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/ALIGN_MULTIPLE_DECLARATION/@EntryValue" value="false" type="bool" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/ALIGN_TERNARY/@EntryValue" value="ALIGN_ALL" type="string" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/BLANK_LINES_AROUND_CLASS_DEFINITION/@EntryValue" value="1" type="int" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/KEEP_BLANK_LINES_IN_DECLARATIONS/@EntryValue" value="2" type="int" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/KEEP_BLANK_LINES_IN_CODE/@EntryValue" value="2" type="int" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/KEEP_USER_LINEBREAKS/@EntryValue" value="true" type="bool" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/INDENT_CASE_FROM_SWITCH/@EntryValue" value="true" type="bool" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/INDENT_COMMENT/@EntryValue" value="true" type="bool" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/INT_ALIGN_EQ/@EntryValue" value="false" type="bool" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/SIMPLE_BLOCK_STYLE/@EntryValue" value="DO_NOT_CHANGE" type="string" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/SPACE_AFTER_COMMA_IN_TEMPLATE_ARGS/@EntryValue" value="true" type="bool" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/SPACE_AFTER_COMMA_IN_TEMPLATE_PARAMS/@EntryValue" value="true" type="bool" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/SPACE_AFTER_FOR_SEMICOLON/@EntryValue" value="true" type="bool" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/SPACE_BEFORE_FOR_SEMICOLON/@EntryValue" value="false" type="bool" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/SPACE_AFTER_UNARY_OPERATOR/@EntryValue" value="false" type="bool" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/SPACE_WITHIN_ARRAY_ACCESS_BRACKETS/@EntryValue" value="false" type="bool" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/SPACE_WITHIN_CAST_EXPRESSION_PARENTHESES/@EntryValue" value="false" type="bool" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/SPACE_WITHIN_EMPTY_INITIALIZER_BRACES/@EntryValue" value="false" type="bool" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/SPACE_WITHIN_EMPTY_METHOD_PARENTHESES/@EntryValue" value="false" type="bool" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/SPACE_WITHIN_INITIALIZER_BRACES/@EntryValue" value="false" type="bool" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/SPECIAL_ELSE_IF_TREATMENT/@EntryValue" value="true" type="bool" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/SPACE_AFTER_CAST_EXPRESSION_PARENTHESES/@EntryValue" value="true" type="bool" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/WRAP_AFTER_BINARY_OPSIGN/@EntryValue" value="true" type="bool" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/WRAP_BEFORE_TERNARY_OPSIGNS/@EntryValue" value="true" type="bool" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/TYPE_DECLARATION_BRACES/@EntryValue" value="END_OF_LINE" type="string" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/OTHER_BRACES/@EntryValue" value="END_OF_LINE" type="string" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/CASE_BLOCK_BRACES/@EntryValue" value="END_OF_LINE" type="string" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/BLANK_LINES_AROUND_FUNCTION_DECLARATION/@EntryValue" value="1" type="int" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/BLANK_LINES_AROUND_FUNCTION_DEFINITION/@EntryValue" value="1" type="int" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/PLACE_WHILE_ON_NEW_LINE/@EntryValue" value="false" type="bool" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/PLACE_ELSE_ON_NEW_LINE/@EntryValue" value="false" type="bool" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/PLACE_CATCH_ON_NEW_LINE/@EntryValue" value="false" type="bool" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/NAMESPACE_INDENTATION/@EntryValue" value="All" type="string" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/ALIGN_MULTILINE_ARGUMENT/@EntryValue" value="true" type="bool" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/ALIGN_MULTILINE_EXTENDS_LIST/@EntryValue" value="true" type="bool" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/ALIGN_MULTILINE_PARAMETER/@EntryValue" value="true" type="bool" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/ALIGN_MULTILINE_TYPE_ARGUMENT/@EntryValue" value="false" type="bool" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/ALIGN_MULTILINE_TYPE_PARAMETER/@EntryValue" value="false" type="bool" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/BLANK_LINES_AROUND_DECLARATIONS/@EntryValue" value="0" type="int" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/INDENT_ACCESS_SPECIFIERS_FROM_CLASS/@EntryValue" value="false" type="bool" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/INDENT_CLASS_MEMBERS_FROM_ACCESS_SPECIFIERS/@EntryValue" value="true" type="bool" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/LINE_BREAK_AFTER_COLON_IN_MEMBER_INITIALIZER_LISTS/@EntryValue" value="ON_SINGLE_LINE" type="string" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/MEMBER_INITIALIZER_LIST_STYLE/@EntryValue" value="DO_NOT_CHANGE" type="string" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/PLACE_NAMESPACE_DEFINITIONS_ON_SAME_LINE/@EntryValue" value="false" type="bool" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/SPACE_AFTER_COLON_IN_BITFIELD_DECLARATOR/@EntryValue" value="true" type="bool" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/SPACE_BEFORE_COLON_IN_BITFIELD_DECLARATOR/@EntryValue" value="false" type="bool" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/SPACE_AFTER_EXTENDS_COLON/@EntryValue" value="true" type="bool" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/SPACE_BEFORE_EXTENDS_COLON/@EntryValue" value="true" type="bool" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/SPACE_AFTER_FOR_COLON/@EntryValue" value="true" type="bool" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/SPACE_BEFORE_FOR_COLON/@EntryValue" value="false" type="bool" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/SPACE_AFTER_PTR_IN_DATA_MEMBER/@EntryValue" value="false" type="bool" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/SPACE_AFTER_PTR_IN_DATA_MEMBERS/@EntryValue" value="false" type="bool" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/SPACE_AFTER_PTR_IN_METHOD/@EntryValue" value="false" type="bool" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/SPACE_AFTER_PTR_IN_NESTED_DECLARATOR/@EntryValue" value="false" type="bool" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/SPACE_AFTER_REF_IN_DATA_MEMBER/@EntryValue" value="false" type="bool" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/SPACE_AFTER_REF_IN_DATA_MEMBERS/@EntryValue" value="false" type="bool" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/SPACE_AFTER_REF_IN_METHOD/@EntryValue" value="false" type="bool" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/SPACE_BEFORE_PTR_IN_ABSTRACT_DECL/@EntryValue" value="true" type="bool" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/SPACE_BEFORE_PTR_IN_DATA_MEMBER/@EntryValue" value="true" type="bool" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/SPACE_BEFORE_PTR_IN_DATA_MEMBERS/@EntryValue" value="true" type="bool" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/SPACE_BEFORE_PTR_IN_METHOD/@EntryValue" value="true" type="bool" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/SPACE_BEFORE_REF_IN_ABSTRACT_DECL/@EntryValue" value="true" type="bool" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/SPACE_BEFORE_REF_IN_DATA_MEMBER/@EntryValue" value="true" type="bool" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/SPACE_BEFORE_REF_IN_DATA_MEMBERS/@EntryValue" value="true" type="bool" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/SPACE_BEFORE_REF_IN_METHOD/@EntryValue" value="true" type="bool" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/SPACE_BEFORE_TEMPLATE_ARGS/@EntryValue" value="false" type="bool" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/SPACE_BEFORE_TEMPLATE_PARAMS/@EntryValue" value="false" type="bool" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/SPACE_BETWEEN_CLOSING_ANGLE_BRACKETS_IN_TEMPLATE_ARGS/@EntryValue" value="true" type="bool" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/SPACE_WITHIN_EMPTY_TEMPLATE_PARAMS/@EntryValue" value="false" type="bool" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/SPACE_WITHIN_TEMPLATE_ARGS/@EntryValue" value="false" type="bool" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/SPACE_WITHIN_TEMPLATE_PARAMS/@EntryValue" value="false" type="bool" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/SPACE_WITHIN_DECLARATION_PARENTHESES/@EntryValue" value="false" type="bool" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/SPACE_WITHIN_EMPTY_BLOCKS/@EntryValue" value="false" type="bool" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/WRAP_BEFORE_INVOCATION_LPAR/@EntryValue" value="false" type="bool" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/WRAP_AFTER_INVOCATION_LPAR/@EntryValue" value="false" type="bool" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/WRAP_BEFORE_INVOCATION_RPAR/@EntryValue" value="false" type="bool" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/WRAP_BEFORE_DECLARATION_LPAR/@EntryValue" value="false" type="bool" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/WRAP_AFTER_DECLARATION_LPAR/@EntryValue" value="false" type="bool" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/WRAP_BEFORE_DECLARATION_RPAR/@EntryValue" value="false" type="bool" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/WRAP_ARGUMENTS_STYLE/@EntryValue" value="WRAP_IF_LONG" type="string" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/WRAP_PARAMETERS_STYLE/@EntryValue" value="WRAP_IF_LONG" type="string" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/BREAK_TEMPLATE_DECLARATION/@EntryValue" value="LINE_BREAK" type="string" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/NAMESPACE_DECLARATION_BRACES/@EntryValue" value="END_OF_LINE" type="string" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/FREE_BLOCK_BRACES/@EntryValue" value="END_OF_LINE" type="string" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/INVOCABLE_DECLARATION_BRACES/@EntryValue" value="END_OF_LINE" type="string" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/ANONYMOUS_METHOD_DECLARATION_BRACES/@EntryValue" value="END_OF_LINE" type="string" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/INITIALIZER_BRACES/@EntryValue" value="END_OF_LINE_NO_SPACE" type="string" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/INDENT_STYLE/@EntryValue" value="Space" type="string" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/INDENT_SIZE/@EntryValue" value="4" type="int" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/CONTINUOUS_LINE_INDENT/@EntryValue" value="Double" type="string" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/TAB_WIDTH/@EntryValue" value="4" type="int" />
</RiderCodeStyleSettings>
<clangFormatSettings>
<option name="ENABLED" value="true" />
</clangFormatSettings>
</code_scheme>
</component>

+ 0
- 5
.idea/codeStyles/codeStyleConfig.xml View File

@ -1,5 +0,0 @@
<component name="ProjectCodeStyleConfiguration">
<state>
<option name="USE_PER_PROJECT_SETTINGS" value="true" />
</state>
</component>

+ 0
- 580
.idea/editor.xml View File

@ -1,580 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="BackendCodeEditorSettings">
<option name="/Default/CodeStyle/CodeFormatting/CppClangFormat/EnableClangFormatSupport/@EntryValue" value="true" type="bool" />
<option name="/Default/CodeStyle/EditorConfig/EnableClangFormatSupport/@EntryValue" value="false" type="bool" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/ALIGN_MULTILINE_BINARY_EXPRESSIONS_CHAIN/@EntryValue" value="true" type="bool" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/ALIGN_MULTILINE_CALLS_CHAIN/@EntryValue" value="false" type="bool" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/ALIGN_MULTILINE_EXPRESSION/@EntryValue" value="false" type="bool" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/ALIGN_MULTILINE_FOR_STMT/@EntryValue" value="true" type="bool" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/ALIGN_MULTIPLE_DECLARATION/@EntryValue" value="false" type="bool" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/ALIGN_TERNARY/@EntryValue" value="ALIGN_ALL" type="string" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/BLANK_LINES_AROUND_CLASS_DEFINITION/@EntryValue" value="1" type="int" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/KEEP_BLANK_LINES_IN_DECLARATIONS/@EntryValue" value="2" type="int" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/KEEP_BLANK_LINES_IN_CODE/@EntryValue" value="2" type="int" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/KEEP_USER_LINEBREAKS/@EntryValue" value="true" type="bool" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/INDENT_CASE_FROM_SWITCH/@EntryValue" value="true" type="bool" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/INDENT_COMMENT/@EntryValue" value="true" type="bool" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/INT_ALIGN_EQ/@EntryValue" value="false" type="bool" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/SIMPLE_BLOCK_STYLE/@EntryValue" value="DO_NOT_CHANGE" type="string" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/SPACE_AFTER_COMMA_IN_TEMPLATE_ARGS/@EntryValue" value="true" type="bool" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/SPACE_AFTER_COMMA_IN_TEMPLATE_PARAMS/@EntryValue" value="true" type="bool" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/SPACE_AFTER_FOR_SEMICOLON/@EntryValue" value="true" type="bool" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/SPACE_BEFORE_FOR_SEMICOLON/@EntryValue" value="false" type="bool" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/SPACE_AFTER_UNARY_OPERATOR/@EntryValue" value="false" type="bool" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/SPACE_WITHIN_ARRAY_ACCESS_BRACKETS/@EntryValue" value="false" type="bool" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/SPACE_WITHIN_CAST_EXPRESSION_PARENTHESES/@EntryValue" value="false" type="bool" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/SPACE_WITHIN_EMPTY_INITIALIZER_BRACES/@EntryValue" value="false" type="bool" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/SPACE_WITHIN_EMPTY_METHOD_PARENTHESES/@EntryValue" value="false" type="bool" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/SPACE_WITHIN_INITIALIZER_BRACES/@EntryValue" value="false" type="bool" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/SPECIAL_ELSE_IF_TREATMENT/@EntryValue" value="true" type="bool" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/SPACE_AFTER_CAST_EXPRESSION_PARENTHESES/@EntryValue" value="true" type="bool" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/WRAP_AFTER_BINARY_OPSIGN/@EntryValue" value="true" type="bool" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/WRAP_BEFORE_TERNARY_OPSIGNS/@EntryValue" value="true" type="bool" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/TYPE_DECLARATION_BRACES/@EntryValue" value="END_OF_LINE" type="string" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/OTHER_BRACES/@EntryValue" value="END_OF_LINE" type="string" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/CASE_BLOCK_BRACES/@EntryValue" value="END_OF_LINE" type="string" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/BLANK_LINES_AROUND_FUNCTION_DECLARATION/@EntryValue" value="1" type="int" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/BLANK_LINES_AROUND_FUNCTION_DEFINITION/@EntryValue" value="1" type="int" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/PLACE_WHILE_ON_NEW_LINE/@EntryValue" value="false" type="bool" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/PLACE_ELSE_ON_NEW_LINE/@EntryValue" value="false" type="bool" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/PLACE_CATCH_ON_NEW_LINE/@EntryValue" value="false" type="bool" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/NAMESPACE_INDENTATION/@EntryValue" value="All" type="string" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/ALIGN_MULTILINE_ARGUMENT/@EntryValue" value="true" type="bool" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/ALIGN_MULTILINE_EXTENDS_LIST/@EntryValue" value="true" type="bool" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/ALIGN_MULTILINE_PARAMETER/@EntryValue" value="true" type="bool" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/ALIGN_MULTILINE_TYPE_ARGUMENT/@EntryValue" value="false" type="bool" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/ALIGN_MULTILINE_TYPE_PARAMETER/@EntryValue" value="false" type="bool" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/BLANK_LINES_AROUND_DECLARATIONS/@EntryValue" value="0" type="int" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/INDENT_ACCESS_SPECIFIERS_FROM_CLASS/@EntryValue" value="false" type="bool" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/INDENT_CLASS_MEMBERS_FROM_ACCESS_SPECIFIERS/@EntryValue" value="true" type="bool" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/LINE_BREAK_AFTER_COLON_IN_MEMBER_INITIALIZER_LISTS/@EntryValue" value="ON_SINGLE_LINE" type="string" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/MEMBER_INITIALIZER_LIST_STYLE/@EntryValue" value="DO_NOT_CHANGE" type="string" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/PLACE_NAMESPACE_DEFINITIONS_ON_SAME_LINE/@EntryValue" value="false" type="bool" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/SPACE_AFTER_COLON_IN_BITFIELD_DECLARATOR/@EntryValue" value="true" type="bool" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/SPACE_BEFORE_COLON_IN_BITFIELD_DECLARATOR/@EntryValue" value="false" type="bool" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/SPACE_AFTER_EXTENDS_COLON/@EntryValue" value="true" type="bool" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/SPACE_BEFORE_EXTENDS_COLON/@EntryValue" value="true" type="bool" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/SPACE_AFTER_FOR_COLON/@EntryValue" value="true" type="bool" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/SPACE_BEFORE_FOR_COLON/@EntryValue" value="false" type="bool" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/SPACE_AFTER_PTR_IN_DATA_MEMBER/@EntryValue" value="false" type="bool" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/SPACE_AFTER_PTR_IN_DATA_MEMBERS/@EntryValue" value="false" type="bool" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/SPACE_AFTER_PTR_IN_METHOD/@EntryValue" value="false" type="bool" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/SPACE_AFTER_PTR_IN_NESTED_DECLARATOR/@EntryValue" value="false" type="bool" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/SPACE_AFTER_REF_IN_DATA_MEMBER/@EntryValue" value="false" type="bool" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/SPACE_AFTER_REF_IN_DATA_MEMBERS/@EntryValue" value="false" type="bool" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/SPACE_AFTER_REF_IN_METHOD/@EntryValue" value="false" type="bool" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/SPACE_BEFORE_PTR_IN_ABSTRACT_DECL/@EntryValue" value="true" type="bool" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/SPACE_BEFORE_PTR_IN_DATA_MEMBER/@EntryValue" value="true" type="bool" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/SPACE_BEFORE_PTR_IN_DATA_MEMBERS/@EntryValue" value="true" type="bool" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/SPACE_BEFORE_PTR_IN_METHOD/@EntryValue" value="true" type="bool" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/SPACE_BEFORE_REF_IN_ABSTRACT_DECL/@EntryValue" value="true" type="bool" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/SPACE_BEFORE_REF_IN_DATA_MEMBER/@EntryValue" value="true" type="bool" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/SPACE_BEFORE_REF_IN_DATA_MEMBERS/@EntryValue" value="true" type="bool" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/SPACE_BEFORE_REF_IN_METHOD/@EntryValue" value="true" type="bool" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/SPACE_BEFORE_TEMPLATE_ARGS/@EntryValue" value="false" type="bool" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/SPACE_BEFORE_TEMPLATE_PARAMS/@EntryValue" value="false" type="bool" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/SPACE_BETWEEN_CLOSING_ANGLE_BRACKETS_IN_TEMPLATE_ARGS/@EntryValue" value="true" type="bool" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/SPACE_WITHIN_EMPTY_TEMPLATE_PARAMS/@EntryValue" value="false" type="bool" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/SPACE_WITHIN_TEMPLATE_ARGS/@EntryValue" value="false" type="bool" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/SPACE_WITHIN_TEMPLATE_PARAMS/@EntryValue" value="false" type="bool" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/SPACE_WITHIN_DECLARATION_PARENTHESES/@EntryValue" value="false" type="bool" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/SPACE_WITHIN_EMPTY_BLOCKS/@EntryValue" value="false" type="bool" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/WRAP_BEFORE_INVOCATION_LPAR/@EntryValue" value="false" type="bool" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/WRAP_AFTER_INVOCATION_LPAR/@EntryValue" value="false" type="bool" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/WRAP_BEFORE_INVOCATION_RPAR/@EntryValue" value="false" type="bool" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/WRAP_BEFORE_DECLARATION_LPAR/@EntryValue" value="false" type="bool" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/WRAP_AFTER_DECLARATION_LPAR/@EntryValue" value="false" type="bool" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/WRAP_BEFORE_DECLARATION_RPAR/@EntryValue" value="false" type="bool" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/WRAP_ARGUMENTS_STYLE/@EntryValue" value="WRAP_IF_LONG" type="string" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/WRAP_PARAMETERS_STYLE/@EntryValue" value="WRAP_IF_LONG" type="string" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/BREAK_TEMPLATE_DECLARATION/@EntryValue" value="LINE_BREAK" type="string" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/NAMESPACE_DECLARATION_BRACES/@EntryValue" value="END_OF_LINE" type="string" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/FREE_BLOCK_BRACES/@EntryValue" value="END_OF_LINE" type="string" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/INVOCABLE_DECLARATION_BRACES/@EntryValue" value="END_OF_LINE" type="string" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/ANONYMOUS_METHOD_DECLARATION_BRACES/@EntryValue" value="END_OF_LINE" type="string" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/INITIALIZER_BRACES/@EntryValue" value="END_OF_LINE_NO_SPACE" type="string" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/INDENT_STYLE/@EntryValue" value="Space" type="string" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/INDENT_SIZE/@EntryValue" value="4" type="int" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/CONTINUOUS_LINE_INDENT/@EntryValue" value="Double" type="string" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/TAB_WIDTH/@EntryValue" value="4" type="int" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppSmartPointerVsMakeFunction/@EntryIndexedValue" value="SUGGESTION" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppCStyleCast/@EntryIndexedValue" value="SUGGESTION" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppFunctionalStyleCast/@EntryIndexedValue" value="SUGGESTION" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppReinterpretCastFromVoidPtr/@EntryIndexedValue" value="SUGGESTION" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppNonExplicitConvertingConstructor/@EntryIndexedValue" value="HINT" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppNonExplicitConversionOperator/@EntryIndexedValue" value="HINT" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppDiscardedPostfixOperatorResult/@EntryIndexedValue" value="SUGGESTION" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppConstValueFunctionReturnType/@EntryIndexedValue" value="SUGGESTION" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppMemberFunctionMayBeConst/@EntryIndexedValue" value="SUGGESTION" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppMemberFunctionMayBeStatic/@EntryIndexedValue" value="SUGGESTION" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppLocalVariableMayBeConst/@EntryIndexedValue" value="HINT" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppParameterMayBeConst/@EntryIndexedValue" value="HINT" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppVariableCanBeMadeConstexpr/@EntryIndexedValue" value="SUGGESTION" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppParameterMayBeConstPtrOrRef/@EntryIndexedValue" value="SUGGESTION" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppPassValueParameterByConstReference/@EntryIndexedValue" value="SUGGESTION" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppThrowExpressionCanBeReplacedWithRethrow/@EntryIndexedValue" value="WARNING" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppZeroConstantCanBeReplacedWithNullptr/@EntryIndexedValue" value="SUGGESTION" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppCompileTimeConstantCanBeReplacedWithBooleanConstant/@EntryIndexedValue" value="SUGGESTION" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppIfCanBeReplacedByConstexprIf/@EntryIndexedValue" value="SUGGESTION" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=IfStdIsConstantEvaluatedCanBeReplaced/@EntryIndexedValue" value="SUGGESTION" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=StdIsConstantEvaluatedWillAlwaysEvaluateToConstant/@EntryIndexedValue" value="WARNING" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=ConstevalIfIsAlwaysConstant/@EntryIndexedValue" value="WARNING" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppClassCanBeFinal/@EntryIndexedValue" value="HINT" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppUseStructuredBinding/@EntryIndexedValue" value="HINT" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppUseTypeTraitAlias/@EntryIndexedValue" value="SUGGESTION" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppUseAlgorithmWithCount/@EntryIndexedValue" value="SUGGESTION" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppUseRangeAlgorithm/@EntryIndexedValue" value="SUGGESTION" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppUseElementsView/@EntryIndexedValue" value="SUGGESTION" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppUseStdSize/@EntryIndexedValue" value="SUGGESTION" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppForLoopCanBeReplacedWithWhile/@EntryIndexedValue" value="SUGGESTION" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppJoinDeclarationAndAssignment/@EntryIndexedValue" value="SUGGESTION" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppReplaceTieWithStructuredBinding/@EntryIndexedValue" value="SUGGESTION" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppReplaceMemsetWithZeroInitialization/@EntryIndexedValue" value="SUGGESTION" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppUseAssociativeContains/@EntryIndexedValue" value="SUGGESTION" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppUseEraseAlgorithm/@EntryIndexedValue" value="SUGGESTION" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppUseFamiliarTemplateSyntaxForGenericLambdas/@EntryIndexedValue" value="SUGGESTION" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppTooWideScope/@EntryIndexedValue" value="SUGGESTION" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppTooWideScopeInitStatement/@EntryIndexedValue" value="HINT" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppRedundantNamespaceDefinition/@EntryIndexedValue" value="SUGGESTION" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppNonInlineFunctionDefinitionInHeaderFile/@EntryIndexedValue" value="WARNING" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppNonInlineVariableDefinitionInHeaderFile/@EntryIndexedValue" value="WARNING" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppFunctionIsNotImplemented/@EntryIndexedValue" value="WARNING" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppPrivateSpecialMemberFunctionIsNotImplemented/@EntryIndexedValue" value="WARNING" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppHiddenFunction/@EntryIndexedValue" value="WARNING" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppHidingFunction/@EntryIndexedValue" value="WARNING" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppPolymorphicClassWithNonVirtualPublicDestructor/@EntryIndexedValue" value="WARNING" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppAbstractClassWithoutSpecifier/@EntryIndexedValue" value="WARNING" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppIncompleteSwitchStatement/@EntryIndexedValue" value="WARNING" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppDefaultCaseNotHandledInSwitchStatement/@EntryIndexedValue" value="WARNING" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppPossiblyErroneousEmptyStatements/@EntryIndexedValue" value="WARNING" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppExpressionWithoutSideEffects/@EntryIndexedValue" value="WARNING" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppNoDiscardExpression/@EntryIndexedValue" value="WARNING" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppFunctionResultShouldBeUsed/@EntryIndexedValue" value="HINT" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppMissingKeywordThrow/@EntryIndexedValue" value="WARNING" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppDependentTypeWithoutTypenameKeyword/@EntryIndexedValue" value="WARNING" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppDependentTemplateWithoutTemplateKeyword/@EntryIndexedValue" value="WARNING" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppImplicitDefaultConstructorNotAvailable/@EntryIndexedValue" value="WARNING" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppClassNeedsConstructorBecauseOfUninitializedMember/@EntryIndexedValue" value="WARNING" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppUninitializedNonStaticDataMember/@EntryIndexedValue" value="WARNING" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppRangeBasedForIncompatibleReference/@EntryIndexedValue" value="WARNING" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppZeroValuedExpressionUsedAsNullPointer/@EntryIndexedValue" value="WARNING" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppPossiblyUnintendedObjectSlicing/@EntryIndexedValue" value="WARNING" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppPossiblyUninitializedMember/@EntryIndexedValue" value="WARNING" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppDeclaratorDisambiguatedAsFunction/@EntryIndexedValue" value="WARNING" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppVirtualFunctionInFinalClass/@EntryIndexedValue" value="WARNING" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppMustBePublicVirtualToImplementInterface/@EntryIndexedValue" value="WARNING" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppDeclarationSpecifierWithoutDeclarators/@EntryIndexedValue" value="WARNING" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppEmptyDeclaration/@EntryIndexedValue" value="WARNING" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppDeclarationHidesLocal/@EntryIndexedValue" value="WARNING" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppDeclarationHidesUncapturedLocal/@EntryIndexedValue" value="HINT" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppMismatchedClassTags/@EntryIndexedValue" value="WARNING" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppUsingResultOfAssignmentAsCondition/@EntryIndexedValue" value="WARNING" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppIntegralToPointerConversion/@EntryIndexedValue" value="WARNING" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppPointerToIntegralConversion/@EntryIndexedValue" value="WARNING" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppIncompatiblePointerConversion/@EntryIndexedValue" value="WARNING" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppPointerConversionDropsQualifiers/@EntryIndexedValue" value="WARNING" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppStringLiteralToCharPointerConversion/@EntryIndexedValue" value="WARNING" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppNonExceptionSafeResourceAcquisition/@EntryIndexedValue" value="HINT" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppVirtualFunctionCallInsideCtor/@EntryIndexedValue" value="WARNING" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppAbstractVirtualFunctionCallInCtor/@EntryIndexedValue" value="ERROR" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppInvalidLineContinuation/@EntryIndexedValue" value="WARNING" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppPrintfBadFormat/@EntryIndexedValue" value="WARNING" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppPrintfRiskyFormat/@EntryIndexedValue" value="WARNING" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppPrintfMissedArg/@EntryIndexedValue" value="ERROR" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppPrintfExtraArg/@EntryIndexedValue" value="WARNING" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppBoostFormatBadCode/@EntryIndexedValue" value="WARNING" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppBoostFormatLegacyCode/@EntryIndexedValue" value="SUGGESTION" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppBoostFormatMixedArgs/@EntryIndexedValue" value="ERROR" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppBoostFormatTooFewArgs/@EntryIndexedValue" value="ERROR" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppBoostFormatTooManyArgs/@EntryIndexedValue" value="WARNING" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppDeprecatedEntity/@EntryIndexedValue" value="WARNING" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppMissingIncludeGuard/@EntryIndexedValue" value="WARNING" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppDoxygenSyntaxError/@EntryIndexedValue" value="WARNING" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppDoxygenUnresolvedReference/@EntryIndexedValue" value="WARNING" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppDoxygenUndocumentedParameter/@EntryIndexedValue" value="SUGGESTION" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppDeletingVoidPointer/@EntryIndexedValue" value="WARNING" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppBooleanIncrementExpression/@EntryIndexedValue" value="WARNING" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppDeprecatedRegisterStorageClassSpecifier/@EntryIndexedValue" value="WARNING" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppIdenticalOperandsInBinaryExpression/@EntryIndexedValue" value="WARNING" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppEqualOperandsInBinaryExpression/@EntryIndexedValue" value="WARNING" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppRedefinitionOfDefaultArgumentInOverrideFunction/@EntryIndexedValue" value="WARNING" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppUnnamedNamespaceInHeaderFile/@EntryIndexedValue" value="WARNING" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppParameterNamesMismatch/@EntryIndexedValue" value="HINT" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppDefaultedSpecialMemberFunctionIsImplicitlyDeleted/@EntryIndexedValue" value="WARNING" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppNodiscardFunctionWithoutReturnValue/@EntryIndexedValue" value="WARNING" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppRedundantComplexityInComparison/@EntryIndexedValue" value="SUGGESTION" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppAbstractFinalClass/@EntryIndexedValue" value="WARNING" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppSpecialFunctionWithoutNoexceptSpecification/@EntryIndexedValue" value="WARNING" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppUnsignedZeroComparison/@EntryIndexedValue" value="WARNING" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppMultiCharacterLiteral/@EntryIndexedValue" value="WARNING" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppMultiCharacterWideLiteral/@EntryIndexedValue" value="WARNING" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppRedundantQualifier/@EntryIndexedValue" value="HINT" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppRedundantAccessSpecifier/@EntryIndexedValue" value="HINT" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppAccessSpecifierWithNoDeclarations/@EntryIndexedValue" value="SUGGESTION" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppRedundantTypenameKeyword/@EntryIndexedValue" value="WARNING" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppRedundantTemplateKeyword/@EntryIndexedValue" value="WARNING" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppRedundantElseKeyword/@EntryIndexedValue" value="HINT" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppRedundantElseKeywordInsideCompoundStatement/@EntryIndexedValue" value="HINT" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppRedundantControlFlowJump/@EntryIndexedValue" value="HINT" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppRedundantEmptyStatement/@EntryIndexedValue" value="HINT" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppRedundantEmptyDeclaration/@EntryIndexedValue" value="HINT" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppRedundantParentheses/@EntryIndexedValue" value="HINT" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppRedundantLambdaParameterList/@EntryIndexedValue" value="HINT" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppRedundantCastExpression/@EntryIndexedValue" value="HINT" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppHeaderHasBeenAlreadyIncluded/@EntryIndexedValue" value="HINT" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppTemplateArgumentsCanBeDeduced/@EntryIndexedValue" value="HINT" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppRedundantTemplateArguments/@EntryIndexedValue" value="HINT" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppStaticSpecifierOnAnonymousNamespaceMember/@EntryIndexedValue" value="SUGGESTION" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppRedundantStaticSpecifierOnMemberAllocationFunction/@EntryIndexedValue" value="HINT" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppRedundantStaticSpecifierOnThreadLocalLocalVariable/@EntryIndexedValue" value="HINT" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppRedundantBaseClassAccessSpecifier/@EntryIndexedValue" value="HINT" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppRedundantInlineSpecifier/@EntryIndexedValue" value="HINT" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppRedundantConstSpecifier/@EntryIndexedValue" value="HINT" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppRedundantBooleanExpressionArgument/@EntryIndexedValue" value="WARNING" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppRedundantVoidArgumentList/@EntryIndexedValue" value="SUGGESTION" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppRedundantMemberInitializer/@EntryIndexedValue" value="SUGGESTION" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppRedundantBaseClassInitializer/@EntryIndexedValue" value="SUGGESTION" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppConstParameterInDeclaration/@EntryIndexedValue" value="SUGGESTION" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppVolatileParameterInDeclaration/@EntryIndexedValue" value="SUGGESTION" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppFinalFunctionInFinalClass/@EntryIndexedValue" value="SUGGESTION" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppFinalNonOverridingVirtualFunction/@EntryIndexedValue" value="SUGGESTION" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppRedundantElaboratedTypeSpecifier/@EntryIndexedValue" value="HINT" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppRedundantDereferencingAndTakingAddress/@EntryIndexedValue" value="SUGGESTION" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppRedundantConditionalExpression/@EntryIndexedValue" value="SUGGESTION" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppConditionalExpressionCanBeSimplified/@EntryIndexedValue" value="SUGGESTION" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppRedundantExportKeyword/@EntryIndexedValue" value="WARNING" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppRedundantZeroInitializerInAggregateInitialization/@EntryIndexedValue" value="SUGGESTION" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppUserDefinedLiteralSuffixDoesNotStartWithUnderscore/@EntryIndexedValue" value="WARNING" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppClassIsIncomplete/@EntryIndexedValue" value="WARNING" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppTemplateParameterShadowing/@EntryIndexedValue" value="WARNING" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppMutableSpecifierOnReferenceMember/@EntryIndexedValue" value="WARNING" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppDefaultInitializationWithNoUserConstructor/@EntryIndexedValue" value="WARNING" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppExplicitSpecializationInNonNamespaceScope/@EntryIndexedValue" value="WARNING" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppUnionMemberOfReferenceType/@EntryIndexedValue" value="WARNING" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppUninitializedDependentBaseClass/@EntryIndexedValue" value="WARNING" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppPrecompiledHeaderIsNotIncluded/@EntryIndexedValue" value="ERROR" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppPrecompiledHeaderNotFound/@EntryIndexedValue" value="ERROR" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppCoroutineCallResolveError/@EntryIndexedValue" value="WARNING" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppAwaiterTypeIsNotClass/@EntryIndexedValue" value="WARNING" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppOutParameterMustBeWritten/@EntryIndexedValue" value="WARNING" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppWarningDirective/@EntryIndexedValue" value="WARNING" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppStaticAssertFailure/@EntryIndexedValue" value="ERROR" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppEvaluationFailure/@EntryIndexedValue" value="ERROR" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppDeclaratorNeverUsed/@EntryIndexedValue" value="WARNING" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppTypeAliasNeverUsed/@EntryIndexedValue" value="WARNING" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppConceptNeverUsed/@EntryIndexedValue" value="WARNING" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppClassNeverUsed/@EntryIndexedValue" value="WARNING" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppEnumeratorNeverUsed/@EntryIndexedValue" value="WARNING" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppLambdaCaptureNeverUsed/@EntryIndexedValue" value="WARNING" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppLocalVariableWithNonTrivialDtorIsNeverUsed/@EntryIndexedValue" value="DO_NOT_SHOW" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppParameterNeverUsed/@EntryIndexedValue" value="HINT" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppTemplateParameterNeverUsed/@EntryIndexedValue" value="HINT" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppEntityAssignedButNoRead/@EntryIndexedValue" value="WARNING" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppEntityUsedOnlyInUnevaluatedContext/@EntryIndexedValue" value="WARNING" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppLocalVariableMightNotBeInitialized/@EntryIndexedValue" value="WARNING" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppObjectMemberMightNotBeInitialized/@EntryIndexedValue" value="WARNING" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppSomeObjectMembersMightNotBeInitialized/@EntryIndexedValue" value="WARNING" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppDeclaratorUsedBeforeInitialization/@EntryIndexedValue" value="ERROR" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppUnusedIncludeDirective/@EntryIndexedValue" value="WARNING" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppNotAllPathsReturnValue/@EntryIndexedValue" value="WARNING" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CDeclarationWithImplicitIntType/@EntryIndexedValue" value="WARNING" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppFunctionDoesntReturnValue/@EntryIndexedValue" value="WARNING" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppReturnNoValueInNonVoidFunction/@EntryIndexedValue" value="WARNING" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppCVQualifierCanNotBeAppliedToReference/@EntryIndexedValue" value="WARNING" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppDereferenceOperatorLimitExceeded/@EntryIndexedValue" value="WARNING" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppForwardEnumDeclarationWithoutUnderlyingType/@EntryIndexedValue" value="WARNING" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppUnmatchedPragmaRegionDirective/@EntryIndexedValue" value="WARNING" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppUnmatchedPragmaEndRegionDirective/@EntryIndexedValue" value="WARNING" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppStaticDataMemberInUnnamedStruct/@EntryIndexedValue" value="WARNING" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppDefaultIsUsedAsIdentifier/@EntryIndexedValue" value="WARNING" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppLongFloat/@EntryIndexedValue" value="WARNING" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppMsExtReinterpretCastFromNullptr/@EntryIndexedValue" value="WARNING" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppMsExtBindingRValueToLvalueReference/@EntryIndexedValue" value="WARNING" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppMsExtAddressOfClassRValue/@EntryIndexedValue" value="WARNING" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppMsExtDoubleUserConversionInCopyInit/@EntryIndexedValue" value="WARNING" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppMsExtCopyElisionInCopyInitDeclarator/@EntryIndexedValue" value="WARNING" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppMsExtNotInitializedStaticConstLocalVar/@EntryIndexedValue" value="WARNING" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppRemoveRedundantBraces/@EntryIndexedValue" value="DO_NOT_SHOW" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppEnforceIfStatementBraces/@EntryIndexedValue" value="DO_NOT_SHOW" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppEnforceForStatementBraces/@EntryIndexedValue" value="DO_NOT_SHOW" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppEnforceWhileStatementBraces/@EntryIndexedValue" value="DO_NOT_SHOW" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppEnforceDoStatementBraces/@EntryIndexedValue" value="DO_NOT_SHOW" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppWrongIncludesOrder/@EntryIndexedValue" value="HINT" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppWrongSlashesInIncludeDirective/@EntryIndexedValue" value="HINT" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppEnforceNestedNamespacesStyle/@EntryIndexedValue" value="HINT" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppEnforceTypeAliasCodeStyle/@EntryIndexedValue" value="DO_NOT_SHOW" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppEnforceFunctionDeclarationStyle/@EntryIndexedValue" value="DO_NOT_SHOW" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppMemberInitializersOrder/@EntryIndexedValue" value="SUGGESTION" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppEnforceOverridingFunctionStyle/@EntryIndexedValue" value="SUGGESTION" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppEnforceOverridingDestructorStyle/@EntryIndexedValue" value="SUGGESTION" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppUseAuto/@EntryIndexedValue" value="HINT" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppUseAutoForNumeric/@EntryIndexedValue" value="HINT" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppEnforceCVQualifiersPlacement/@EntryIndexedValue" value="DO_NOT_SHOW" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppEnforceCVQualifiersOrder/@EntryIndexedValue" value="DO_NOT_SHOW" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppUnnecessaryWhitespace/@EntryIndexedValue" value="DO_NOT_SHOW" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppTabsAreDisallowed/@EntryIndexedValue" value="DO_NOT_SHOW" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppDFAConstantConditions/@EntryIndexedValue" value="WARNING" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppDFANullDereference/@EntryIndexedValue" value="WARNING" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppDFANotInitializedField/@EntryIndexedValue" value="WARNING" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppDFALoopConditionNotUpdated/@EntryIndexedValue" value="WARNING" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppDFADeletedPointer/@EntryIndexedValue" value="WARNING" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppDFAMemoryLeak/@EntryIndexedValue" value="WARNING" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppDFAInvalidatedMemory/@EntryIndexedValue" value="WARNING" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppDFALocalValueEscapesScope/@EntryIndexedValue" value="WARNING" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppDFALocalValueEscapesFunction/@EntryIndexedValue" value="WARNING" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppDFAConstantParameter/@EntryIndexedValue" value="WARNING" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppDFAConstantFunctionResult/@EntryIndexedValue" value="WARNING" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppDFAArrayIndexOutOfBounds/@EntryIndexedValue" value="WARNING" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppDFAUnreachableCode/@EntryIndexedValue" value="WARNING" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppDFAUnreachableFunctionCall/@EntryIndexedValue" value="WARNING" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppDFAEndlessLoop/@EntryIndexedValue" value="WARNING" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppDFAInfiniteRecursion/@EntryIndexedValue" value="WARNING" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppDFAUnusedValue/@EntryIndexedValue" value="WARNING" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppDFAUnreadVariable/@EntryIndexedValue" value="WARNING" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppDFATimeOver/@EntryIndexedValue" value="HINT" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppInconsistentNaming/@EntryIndexedValue" value="DO_NOT_SHOW" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=StringLiteralTypo/@EntryIndexedValue" value="DO_NOT_SHOW" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CommentTypo/@EntryIndexedValue" value="DO_NOT_SHOW" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=IdentifierTypo/@EntryIndexedValue" value="DO_NOT_SHOW" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppSmartPointerVsMakeFunction/@EntryIndexRemoved" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppCStyleCast/@EntryIndexRemoved" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppFunctionalStyleCast/@EntryIndexRemoved" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppReinterpretCastFromVoidPtr/@EntryIndexRemoved" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppNonExplicitConvertingConstructor/@EntryIndexRemoved" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppNonExplicitConversionOperator/@EntryIndexRemoved" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppDiscardedPostfixOperatorResult/@EntryIndexRemoved" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppConstValueFunctionReturnType/@EntryIndexRemoved" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppMemberFunctionMayBeConst/@EntryIndexRemoved" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppMemberFunctionMayBeStatic/@EntryIndexRemoved" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppLocalVariableMayBeConst/@EntryIndexRemoved" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppParameterMayBeConst/@EntryIndexRemoved" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppVariableCanBeMadeConstexpr/@EntryIndexRemoved" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppParameterMayBeConstPtrOrRef/@EntryIndexRemoved" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppPassValueParameterByConstReference/@EntryIndexRemoved" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppThrowExpressionCanBeReplacedWithRethrow/@EntryIndexRemoved" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppZeroConstantCanBeReplacedWithNullptr/@EntryIndexRemoved" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppCompileTimeConstantCanBeReplacedWithBooleanConstant/@EntryIndexRemoved" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppIfCanBeReplacedByConstexprIf/@EntryIndexRemoved" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=IfStdIsConstantEvaluatedCanBeReplaced/@EntryIndexRemoved" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=StdIsConstantEvaluatedWillAlwaysEvaluateToConstant/@EntryIndexRemoved" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=ConstevalIfIsAlwaysConstant/@EntryIndexRemoved" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppClassCanBeFinal/@EntryIndexRemoved" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppUseStructuredBinding/@EntryIndexRemoved" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppUseTypeTraitAlias/@EntryIndexRemoved" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppUseAlgorithmWithCount/@EntryIndexRemoved" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppUseRangeAlgorithm/@EntryIndexRemoved" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppUseElementsView/@EntryIndexRemoved" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppUseStdSize/@EntryIndexRemoved" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppForLoopCanBeReplacedWithWhile/@EntryIndexRemoved" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppJoinDeclarationAndAssignment/@EntryIndexRemoved" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppReplaceTieWithStructuredBinding/@EntryIndexRemoved" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppReplaceMemsetWithZeroInitialization/@EntryIndexRemoved" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppUseAssociativeContains/@EntryIndexRemoved" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppUseEraseAlgorithm/@EntryIndexRemoved" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppUseFamiliarTemplateSyntaxForGenericLambdas/@EntryIndexRemoved" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppTooWideScope/@EntryIndexRemoved" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppTooWideScopeInitStatement/@EntryIndexRemoved" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppRedundantNamespaceDefinition/@EntryIndexRemoved" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppNonInlineFunctionDefinitionInHeaderFile/@EntryIndexRemoved" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppNonInlineVariableDefinitionInHeaderFile/@EntryIndexRemoved" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppFunctionIsNotImplemented/@EntryIndexRemoved" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppPrivateSpecialMemberFunctionIsNotImplemented/@EntryIndexRemoved" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppHiddenFunction/@EntryIndexRemoved" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppHidingFunction/@EntryIndexRemoved" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppPolymorphicClassWithNonVirtualPublicDestructor/@EntryIndexRemoved" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppAbstractClassWithoutSpecifier/@EntryIndexRemoved" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppIncompleteSwitchStatement/@EntryIndexRemoved" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppDefaultCaseNotHandledInSwitchStatement/@EntryIndexRemoved" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppPossiblyErroneousEmptyStatements/@EntryIndexRemoved" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppExpressionWithoutSideEffects/@EntryIndexRemoved" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppNoDiscardExpression/@EntryIndexRemoved" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppFunctionResultShouldBeUsed/@EntryIndexRemoved" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppMissingKeywordThrow/@EntryIndexRemoved" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppDependentTypeWithoutTypenameKeyword/@EntryIndexRemoved" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppDependentTemplateWithoutTemplateKeyword/@EntryIndexRemoved" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppImplicitDefaultConstructorNotAvailable/@EntryIndexRemoved" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppClassNeedsConstructorBecauseOfUninitializedMember/@EntryIndexRemoved" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppUninitializedNonStaticDataMember/@EntryIndexRemoved" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppRangeBasedForIncompatibleReference/@EntryIndexRemoved" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppZeroValuedExpressionUsedAsNullPointer/@EntryIndexRemoved" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppPossiblyUnintendedObjectSlicing/@EntryIndexRemoved" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppPossiblyUninitializedMember/@EntryIndexRemoved" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppDeclaratorDisambiguatedAsFunction/@EntryIndexRemoved" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppVirtualFunctionInFinalClass/@EntryIndexRemoved" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppMustBePublicVirtualToImplementInterface/@EntryIndexRemoved" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppDeclarationSpecifierWithoutDeclarators/@EntryIndexRemoved" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppEmptyDeclaration/@EntryIndexRemoved" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppDeclarationHidesLocal/@EntryIndexRemoved" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppDeclarationHidesUncapturedLocal/@EntryIndexRemoved" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppMismatchedClassTags/@EntryIndexRemoved" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppUsingResultOfAssignmentAsCondition/@EntryIndexRemoved" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppIntegralToPointerConversion/@EntryIndexRemoved" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppPointerToIntegralConversion/@EntryIndexRemoved" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppIncompatiblePointerConversion/@EntryIndexRemoved" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppPointerConversionDropsQualifiers/@EntryIndexRemoved" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppStringLiteralToCharPointerConversion/@EntryIndexRemoved" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppNonExceptionSafeResourceAcquisition/@EntryIndexRemoved" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppVirtualFunctionCallInsideCtor/@EntryIndexRemoved" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppAbstractVirtualFunctionCallInCtor/@EntryIndexRemoved" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppInvalidLineContinuation/@EntryIndexRemoved" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppPrintfBadFormat/@EntryIndexRemoved" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppPrintfRiskyFormat/@EntryIndexRemoved" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppPrintfMissedArg/@EntryIndexRemoved" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppPrintfExtraArg/@EntryIndexRemoved" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppBoostFormatBadCode/@EntryIndexRemoved" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppBoostFormatLegacyCode/@EntryIndexRemoved" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppBoostFormatMixedArgs/@EntryIndexRemoved" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppBoostFormatTooFewArgs/@EntryIndexRemoved" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppBoostFormatTooManyArgs/@EntryIndexRemoved" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppDeprecatedEntity/@EntryIndexRemoved" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppMissingIncludeGuard/@EntryIndexRemoved" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppDoxygenSyntaxError/@EntryIndexRemoved" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppDoxygenUnresolvedReference/@EntryIndexRemoved" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppDoxygenUndocumentedParameter/@EntryIndexRemoved" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppDeletingVoidPointer/@EntryIndexRemoved" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppBooleanIncrementExpression/@EntryIndexRemoved" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppDeprecatedRegisterStorageClassSpecifier/@EntryIndexRemoved" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppIdenticalOperandsInBinaryExpression/@EntryIndexRemoved" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppEqualOperandsInBinaryExpression/@EntryIndexRemoved" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppRedefinitionOfDefaultArgumentInOverrideFunction/@EntryIndexRemoved" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppUnnamedNamespaceInHeaderFile/@EntryIndexRemoved" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppParameterNamesMismatch/@EntryIndexRemoved" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppDefaultedSpecialMemberFunctionIsImplicitlyDeleted/@EntryIndexRemoved" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppNodiscardFunctionWithoutReturnValue/@EntryIndexRemoved" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppRedundantComplexityInComparison/@EntryIndexRemoved" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppAbstractFinalClass/@EntryIndexRemoved" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppSpecialFunctionWithoutNoexceptSpecification/@EntryIndexRemoved" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppUnsignedZeroComparison/@EntryIndexRemoved" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppMultiCharacterLiteral/@EntryIndexRemoved" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppMultiCharacterWideLiteral/@EntryIndexRemoved" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppRedundantQualifier/@EntryIndexRemoved" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppRedundantAccessSpecifier/@EntryIndexRemoved" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppAccessSpecifierWithNoDeclarations/@EntryIndexRemoved" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppRedundantTypenameKeyword/@EntryIndexRemoved" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppRedundantTemplateKeyword/@EntryIndexRemoved" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppRedundantElseKeyword/@EntryIndexRemoved" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppRedundantElseKeywordInsideCompoundStatement/@EntryIndexRemoved" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppRedundantControlFlowJump/@EntryIndexRemoved" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppRedundantEmptyStatement/@EntryIndexRemoved" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppRedundantEmptyDeclaration/@EntryIndexRemoved" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppRedundantParentheses/@EntryIndexRemoved" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppRedundantLambdaParameterList/@EntryIndexRemoved" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppRedundantCastExpression/@EntryIndexRemoved" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppHeaderHasBeenAlreadyIncluded/@EntryIndexRemoved" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppTemplateArgumentsCanBeDeduced/@EntryIndexRemoved" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppRedundantTemplateArguments/@EntryIndexRemoved" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppStaticSpecifierOnAnonymousNamespaceMember/@EntryIndexRemoved" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppRedundantStaticSpecifierOnMemberAllocationFunction/@EntryIndexRemoved" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppRedundantStaticSpecifierOnThreadLocalLocalVariable/@EntryIndexRemoved" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppRedundantBaseClassAccessSpecifier/@EntryIndexRemoved" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppRedundantInlineSpecifier/@EntryIndexRemoved" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppRedundantConstSpecifier/@EntryIndexRemoved" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppRedundantBooleanExpressionArgument/@EntryIndexRemoved" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppRedundantVoidArgumentList/@EntryIndexRemoved" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppRedundantMemberInitializer/@EntryIndexRemoved" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppRedundantBaseClassInitializer/@EntryIndexRemoved" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppConstParameterInDeclaration/@EntryIndexRemoved" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppVolatileParameterInDeclaration/@EntryIndexRemoved" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppFinalFunctionInFinalClass/@EntryIndexRemoved" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppFinalNonOverridingVirtualFunction/@EntryIndexRemoved" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppRedundantElaboratedTypeSpecifier/@EntryIndexRemoved" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppRedundantDereferencingAndTakingAddress/@EntryIndexRemoved" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppRedundantConditionalExpression/@EntryIndexRemoved" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppConditionalExpressionCanBeSimplified/@EntryIndexRemoved" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppRedundantExportKeyword/@EntryIndexRemoved" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppRedundantZeroInitializerInAggregateInitialization/@EntryIndexRemoved" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppUserDefinedLiteralSuffixDoesNotStartWithUnderscore/@EntryIndexRemoved" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppClassIsIncomplete/@EntryIndexRemoved" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppTemplateParameterShadowing/@EntryIndexRemoved" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppMutableSpecifierOnReferenceMember/@EntryIndexRemoved" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppDefaultInitializationWithNoUserConstructor/@EntryIndexRemoved" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppExplicitSpecializationInNonNamespaceScope/@EntryIndexRemoved" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppUnionMemberOfReferenceType/@EntryIndexRemoved" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppUninitializedDependentBaseClass/@EntryIndexRemoved" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppPrecompiledHeaderIsNotIncluded/@EntryIndexRemoved" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppPrecompiledHeaderNotFound/@EntryIndexRemoved" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppCoroutineCallResolveError/@EntryIndexRemoved" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppAwaiterTypeIsNotClass/@EntryIndexRemoved" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppOutParameterMustBeWritten/@EntryIndexRemoved" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppWarningDirective/@EntryIndexRemoved" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppStaticAssertFailure/@EntryIndexRemoved" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppEvaluationFailure/@EntryIndexRemoved" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppDeclaratorNeverUsed/@EntryIndexRemoved" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppTypeAliasNeverUsed/@EntryIndexRemoved" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppConceptNeverUsed/@EntryIndexRemoved" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppClassNeverUsed/@EntryIndexRemoved" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppEnumeratorNeverUsed/@EntryIndexRemoved" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppLambdaCaptureNeverUsed/@EntryIndexRemoved" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppLocalVariableWithNonTrivialDtorIsNeverUsed/@EntryIndexRemoved" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppParameterNeverUsed/@EntryIndexRemoved" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppTemplateParameterNeverUsed/@EntryIndexRemoved" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppEntityAssignedButNoRead/@EntryIndexRemoved" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppEntityUsedOnlyInUnevaluatedContext/@EntryIndexRemoved" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppLocalVariableMightNotBeInitialized/@EntryIndexRemoved" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppObjectMemberMightNotBeInitialized/@EntryIndexRemoved" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppSomeObjectMembersMightNotBeInitialized/@EntryIndexRemoved" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppDeclaratorUsedBeforeInitialization/@EntryIndexRemoved" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppUnusedIncludeDirective/@EntryIndexRemoved" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppNotAllPathsReturnValue/@EntryIndexRemoved" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CDeclarationWithImplicitIntType/@EntryIndexRemoved" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppFunctionDoesntReturnValue/@EntryIndexRemoved" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppReturnNoValueInNonVoidFunction/@EntryIndexRemoved" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppCVQualifierCanNotBeAppliedToReference/@EntryIndexRemoved" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppDereferenceOperatorLimitExceeded/@EntryIndexRemoved" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppForwardEnumDeclarationWithoutUnderlyingType/@EntryIndexRemoved" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppUnmatchedPragmaRegionDirective/@EntryIndexRemoved" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppUnmatchedPragmaEndRegionDirective/@EntryIndexRemoved" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppStaticDataMemberInUnnamedStruct/@EntryIndexRemoved" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppDefaultIsUsedAsIdentifier/@EntryIndexRemoved" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppLongFloat/@EntryIndexRemoved" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppMsExtReinterpretCastFromNullptr/@EntryIndexRemoved" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppMsExtBindingRValueToLvalueReference/@EntryIndexRemoved" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppMsExtAddressOfClassRValue/@EntryIndexRemoved" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppMsExtDoubleUserConversionInCopyInit/@EntryIndexRemoved" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppMsExtCopyElisionInCopyInitDeclarator/@EntryIndexRemoved" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppMsExtNotInitializedStaticConstLocalVar/@EntryIndexRemoved" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppRemoveRedundantBraces/@EntryIndexRemoved" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppEnforceIfStatementBraces/@EntryIndexRemoved" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppEnforceForStatementBraces/@EntryIndexRemoved" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppEnforceWhileStatementBraces/@EntryIndexRemoved" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppEnforceDoStatementBraces/@EntryIndexRemoved" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppWrongIncludesOrder/@EntryIndexRemoved" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppWrongSlashesInIncludeDirective/@EntryIndexRemoved" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppEnforceNestedNamespacesStyle/@EntryIndexRemoved" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppEnforceTypeAliasCodeStyle/@EntryIndexRemoved" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppEnforceFunctionDeclarationStyle/@EntryIndexRemoved" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppMemberInitializersOrder/@EntryIndexRemoved" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppEnforceOverridingFunctionStyle/@EntryIndexRemoved" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppEnforceOverridingDestructorStyle/@EntryIndexRemoved" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppUseAuto/@EntryIndexRemoved" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppUseAutoForNumeric/@EntryIndexRemoved" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppEnforceCVQualifiersPlacement/@EntryIndexRemoved" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppEnforceCVQualifiersOrder/@EntryIndexRemoved" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppUnnecessaryWhitespace/@EntryIndexRemoved" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppTabsAreDisallowed/@EntryIndexRemoved" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppDFAConstantConditions/@EntryIndexRemoved" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppDFANullDereference/@EntryIndexRemoved" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppDFANotInitializedField/@EntryIndexRemoved" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppDFALoopConditionNotUpdated/@EntryIndexRemoved" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppDFADeletedPointer/@EntryIndexRemoved" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppDFAMemoryLeak/@EntryIndexRemoved" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppDFAInvalidatedMemory/@EntryIndexRemoved" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppDFALocalValueEscapesScope/@EntryIndexRemoved" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppDFALocalValueEscapesFunction/@EntryIndexRemoved" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppDFAConstantParameter/@EntryIndexRemoved" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppDFAConstantFunctionResult/@EntryIndexRemoved" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppDFAArrayIndexOutOfBounds/@EntryIndexRemoved" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppDFAUnreachableCode/@EntryIndexRemoved" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppDFAUnreachableFunctionCall/@EntryIndexRemoved" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppDFAEndlessLoop/@EntryIndexRemoved" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppDFAInfiniteRecursion/@EntryIndexRemoved" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppDFAUnusedValue/@EntryIndexRemoved" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppDFAUnreadVariable/@EntryIndexRemoved" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppDFATimeOver/@EntryIndexRemoved" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppInconsistentNaming/@EntryIndexRemoved" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=StringLiteralTypo/@EntryIndexRemoved" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CommentTypo/@EntryIndexRemoved" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=IdentifierTypo/@EntryIndexRemoved" />
</component>
</project>

+ 0
- 13
.idea/misc.xml View File

@ -1,13 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="BackendCodeEditorMiscSettings">
<option name="/Default/RiderDebugger/RiderRestoreDecompile/RestoreDecompileSetting/@EntryValue" value="false" type="bool" />
<option name="/Default/Housekeeping/GlobalSettingsUpgraded/IsUpgraded/@EntryValue" value="true" type="bool" />
<option name="/Default/Housekeeping/FeatureSuggestion/FeatureSuggestionManager/DisabledSuggesters/=SwitchToGoToActionSuggester/@EntryIndexedValue" value="true" type="bool" />
<option name="/Default/Environment/Hierarchy/GeneratedFilesCacheKey/Timestamp/@EntryValue" value="5" type="long" />
</component>
<component name="CMakePythonSetting">
<option name="pythonIntegrationState" value="YES" />
</component>
<component name="CMakeWorkspace" PROJECT_DIR="$PROJECT_DIR$" />
</project>

+ 0
- 8
.idea/modules.xml View File

@ -1,8 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="ProjectModuleManager">
<modules>
<module fileurl="file://$PROJECT_DIR$/.idea/LevelDB-KV-Separation.iml" filepath="$PROJECT_DIR$/.idea/LevelDB-KV-Separation.iml" />
</modules>
</component>
</project>

+ 0
- 8
.idea/vcs.xml View File

@ -1,8 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="VcsDirectoryMappings">
<mapping directory="" vcs="Git" />
<mapping directory="$PROJECT_DIR$/third_party/benchmark" vcs="Git" />
<mapping directory="$PROJECT_DIR$/third_party/googletest" vcs="Git" />
</component>
</project>

+ 20
- 4
CMakeLists.txt View File

@ -176,6 +176,8 @@ target_sources(leveldb
"table/vtable_builder.h" "table/vtable_builder.h"
"table/vtable_format.cc" "table/vtable_format.cc"
"table/vtable_format.h" "table/vtable_format.h"
"table/vtable_manager.cc"
"table/vtable_manager.h"
"table/vtable_reader.cc" "table/vtable_reader.cc"
"table/vtable_reader.h" "table/vtable_reader.h"
"util/arena.cc" "util/arena.cc"
@ -337,7 +339,7 @@ if(LEVELDB_BUILD_TESTS)
PRIVATE PRIVATE
"db/autocompact_test.cc" "db/autocompact_test.cc"
"db/corruption_test.cc" "db/corruption_test.cc"
"db/db_test.cc"
# "db/db_test.cc"
"db/dbformat_test.cc" "db/dbformat_test.cc"
"db/filename_test.cc" "db/filename_test.cc"
"db/log_test.cc" "db/log_test.cc"
@ -348,7 +350,7 @@ if(LEVELDB_BUILD_TESTS)
"db/write_batch_test.cc" "db/write_batch_test.cc"
"helpers/memenv/memenv_test.cc" "helpers/memenv/memenv_test.cc"
"table/filter_block_test.cc" "table/filter_block_test.cc"
"table/table_test.cc"
# "table/table_test.cc"
"util/arena_test.cc" "util/arena_test.cc"
"util/bloom_test.cc" "util/bloom_test.cc"
"util/cache_test.cc" "util/cache_test.cc"
@ -445,8 +447,12 @@ if(LEVELDB_BUILD_BENCHMARKS)
endif(NOT HAVE_CXX17_HAS_INCLUDE) endif(NOT HAVE_CXX17_HAS_INCLUDE)
endfunction(leveldb_benchmark) endfunction(leveldb_benchmark)
# if(NOT BUILD_SHARED_LIBS)
# leveldb_benchmark("benchmarks/db_bench.cc")
# endif(NOT BUILD_SHARED_LIBS)
if(NOT BUILD_SHARED_LIBS) if(NOT BUILD_SHARED_LIBS)
leveldb_benchmark("benchmarks/db_bench.cc")
leveldb_benchmark("benchmarks/db_bench_new.cc")
endif(NOT BUILD_SHARED_LIBS) endif(NOT BUILD_SHARED_LIBS)
check_library_exists(sqlite3 sqlite3_open "" HAVE_SQLITE3) check_library_exists(sqlite3 sqlite3_open "" HAVE_SQLITE3)
@ -539,4 +545,14 @@ target_link_libraries(test_vtable PRIVATE leveldb gtest)
add_executable(test_basicio add_executable(test_basicio
"${PROJECT_SOURCE_DIR}/test/test_basicio.cc" "${PROJECT_SOURCE_DIR}/test/test_basicio.cc"
) )
target_link_libraries(test_basicio PRIVATE leveldb gtest)
target_link_libraries(test_basicio PRIVATE leveldb gtest)
add_executable(test_bench
"${PROJECT_SOURCE_DIR}/test/test_bench.cc"
)
target_link_libraries(test_bench PRIVATE leveldb gtest)
add_executable(test_bench_gc
"${PROJECT_SOURCE_DIR}/test/test_bench_gc.cc"
)
target_link_libraries(test_bench_gc PRIVATE leveldb gtest)

+ 222
- 66
PLAN.md View File

@ -77,11 +77,7 @@
- Key-Value分离结构图示: - Key-Value分离结构图示:
![kv-sep](./assets/kv-sep.png)
- Value Log中实际存储的内容 :
![vLog](./assets/vLog.png)
![kv-sep](./assets/kvsep_overview.png)
## 4. 接口/函数设计 ## 4. 接口/函数设计
@ -122,67 +118,224 @@
#### 4.2. KV分离 #### 4.2. KV分离
kv分离文件VTable的格式定义(vtable format)
- ```c++ - ```c++
// 将value写入vLog,并把将要写入LSM-tree的地址返回为value_addr
// 该函数在Put中被调用
void WriteValue(const Slice& key, const Slice& value, Slice& value_addr,
bool sync);
// VTable最基本的存储单位,表示存储的一个key和一个value
struct VTableRecord {
Slice key;
Slice value;
// 将record编码为str
void Encode(std::string* target) const;
// 将Slice解码为record
Status Decode(Slice* input);
// 该record的size
size_t size() const { return key.size() + value.size(); }
friend bool operator==(const VTableRecord& a, const VTableRecord& b) {
return a.key == b.key && a.value == b.value;
}
};
class RecordEncoder {
public:
RecordEncoder() = default;
// 编码一条vTable record
void Encode(const VTableRecord& record);
// 获得编码后的records的size
size_t GetEncodedSize() const { return sizeof(header_) + record_.size(); }
// 获取编码后的header
Slice GetHeader() const { return {header_, sizeof(header_)}; }
// 获得编码后的record
Slice GetRecord() const { return record_; }
private:
char header_[kRecordHeaderSize];
Slice record_;
std::string record_buff_;
};
class RecordDecoder {
public:
// 解码出record的header
Status DecodeHeader(Slice* input);
// 解码出record
Status DecodeRecord(Slice* input, VTableRecord* record) const;
// 获得解码后的record size
size_t GetDecodedSize() const { return record_size_; }
private:
uint32_t record_size_{0};
};
struct VTableHandle {
// 表示某个record在VTable中的位置
uint64_t offset{0};
uint64_t size{0};
void Encode(std::string* target) const;
Status Decode(Slice* input);
friend bool operator==(const VTableHandle& a, const VTableHandle& b) {
return a.offset == b.offset && a.size == b.size;
}
};
struct VTableIndex {
// 存入sstable中的index
enum Type : unsigned char {
kVTableIndex = 1,
};
uint64_t file_number{0};
VTableHandle vtable_handle;
void Encode(std::string* target) const;
Status Decode(Slice* input);
friend bool operator==(const VTableIndex& a, const VTableIndex& b) {
return a.file_number == b.file_number && a.vtable_handle == b.vtable_handle;
}
};
``` ```
VTable构建类 (vtable builder)
- ```c++ - ```c++
// 通过value_addr从vLog中获得value并返回
void GetValue(const Slice& value_addr, Slice& value);
class VTableBuilder {
public:
VTableBuilder(const Options& options, WritableFile* file);
// Add a record to the vTable
void Add(const VTableRecord& record, VTableHandle* handle);
// Builder status, return non-ok iff some error occurs
Status status() const { return status_; }
// Finish building the vTable
Status Finish();
// Abandon building the vTable
void Abandon();
uint64_t FileSize() const { return file_size_; }
uint64_t RecordNumber() const { return record_number_; }
private:
bool ok() const { return status().ok(); }
WritableFile* file_;
uint64_t file_size_{0};
uint64_t record_number_{0};
Status status_;
RecordEncoder encoder_;
};
``` ```
VTable读取类(vtable reader)
- ```c++ - ```c++
// ValueLog在LevelDB启动时即作为LevelDB的一个成员初始化一个实例
// 后续db都使用该实例进行ValueLog相关操作
class ValueLog {
private:
WriteBuff _buff;
uint64_t _head;
uint64_t _tail;
// 将缓存内容真正写入磁盘的vLog中
bool WirteDisk();
public:
ValueLog();
~ValueLog();
// 返回vLog中head处的offset
uint64_t Head();
// 返回vLog中tail处的offset
uint64_t Tail();
// 将key-value对插入Value Log,返回对应的value_addr
// 若用户要求同步写入,即sync为true,则立即将数据写入磁盘
Slice Append(const Slice& key, const Slice& value, bool sync);
// 通过value_addr获得value,首先在buff中寻找,然后才真正访问vLog
Slice Get(const Slice& value_addr);
// 对ValueLog文件进行GC操作,释放空间
void GarbageCollection(uint64_t chunk_size);
}
class VTableReader {
public:
VTableReader() = default;
VTableReader(uint64_t fnum, VTableManager *manager) :
fnum_(fnum),
manager_(manager) {};
Status Open(const Options& options, std::string fname);
Status Get(const VTableHandle& handle,
VTableRecord* record) const ;
void Close();
private:
Options options_;
uint64_t fnum_;
RandomAccessFile* file_{nullptr};
VTableManager* manager_{nullptr};
};
``` ```
VTable管理类(vtable manager)
- ```c++ - ```c++
// WriteBuff的功能与Memtable极其相似,实现可以大量仿照Memtable,甚至直接使用Memtable
// 因此,此处仅列出WriteBuff需要提供的两个接口,其他成员不再列出
class WriteBuff {
// 向buff中插入一条value_addr-vLogValue(<ksize, vsize, key, value>)对
void Add(const Slice& value_addr, const Slice& key, const Slice& value);
// 在buff中查询对应value_addr对应的value
// 找到返回true,否则返回false
bool Get(const Slice& value_addr);
// 将缓存内容写入磁盘
bool WirteDisk();
}
struct VTableMeta {
uint64_t number;
uint64_t records_num;
uint64_t invalid_num;
uint64_t table_size;
uint64_t ref = 0;
void Encode(std::string* target) const;
Status Decode(Slice* input);
VTableMeta() : number(0), records_num(0), invalid_num(0), table_size(0) {}
};
class VTableManager {
public:
explicit VTableManager(const std::string& dbname, Env* env, size_t gc_threshold) :
dbname_(dbname),
env_(env),
gc_threshold_(gc_threshold) {}
~VTableManager() = default;
// sign a vtable to meta
void AddVTable(const VTableMeta& vtable_meta);
// remove a vtable from meta
void RemoveVTable(uint64_t file_num);
// add an invalid num to a vtable
Status AddInvalid(uint64_t file_num);
// save meta info to disk
Status SaveVTableMeta() const;
// recover meta info from disk
Status LoadVTableMeta();
// reference a vtable
void RefVTable(uint64_t file_num);
// unref a vtable
void UnrefVTable(uint64_t file_num);
// maybe schedule backgroud gc
void MaybeScheduleGarbageCollect();
// do backgroud gc work
static void BackgroudGC(void* gc_info);
private:
std::string dbname_;
Env* env_;
std::map<uint64_t, VTableMeta> vtables_;
std::vector<uint64_t> invalid_;
size_t gc_threshold_;
};
``` ```
`DoCompactionWork`,`BuildTable`方法修改,完成kv分离
对`get`和`put`方法修改,`iterator`类修改,保证 `leveldb` 基本功能
## 5. 功能测试 ## 5. 功能测试
### 单元测试 ### 单元测试
@ -370,17 +523,20 @@ void TestLatency(leveldb::DB* db, int num_operations,
+ 分离存储的Value文件的大小优先,如何合适地存储超大Value + 分离存储的Value文件的大小优先,如何合适地存储超大Value
+ 分离存储导致读写时需要经过索引,读写放大产生性能影响 + 分离存储导致读写时需要经过索引,读写放大产生性能影响
#### 解决方案待定
## 7. 分工和进度安排 ## 7. 分工和进度安排
| 功能 | 完成日期 | 分工|
| :------: | :-----: | :-----:|
| Fields类和相关接口实现 | 12月1日 | 韩晨旭 |
| 修改LevelDB接口实现字段功能 | 12月1日 | 李畅 |
| ValueLog类相关接口实现 | 12月19日 | 李畅 |
| WriteBuff类相关接口实现 | 12月19日 | 韩晨旭 |
| 吞吐量测试 | 12月26日 | 韩晨旭 |
| 延迟测试 | 12月26日 | 李畅 |
| 写放大测试对比 | 12月26日 | 韩晨旭、李畅 |
| 尝试对系统性能进行优化 | 1月4日 | 韩晨旭、李畅 |
| 功能 | 完成日期 | 分工 |
|:-----------------:|:------:|:------:|
| Fields类和相关接口实现 | 12月1日 | 韩晨旭 |
| 修改LevelDB接口实现字段功能 | 12月1日 | 韩晨旭 |
| vTable format实现 | 12月19日 | 韩晨旭 |
| vTable builder实现 | 12月26日 | 韩晨旭 |
| vTable reader实现 | 12月26日 | 韩晨旭 |
| vTable manager实现 | 12月31日 | 韩晨旭 |
| 接口方法修改 | 12月31日 | 韩晨旭 |
| 功能正确性测试 | 12月31日 | 韩晨旭 |
| 吞吐量测试 | 1月4日 | 李畅 |
| 延迟测试 | 1月4日 | 李畅 |
| 写放大测试对比 | 1月4日 | 李畅 |
| 尝试对系统性能进行优化 | 1月4日 | 韩晨旭、李畅 |

+ 687
- 1
README.md View File

@ -1 +1,687 @@
> 设计文档为PLAN.md(设计文档暂时未更新)
## 1. 项目概述
### 项目背景
本项目基于LevelDB源代码进行修改和优化。`LevelDB`使用`LSM Tree`的数据结构,是`key-value`数据库的典型。LSM树后台为了加速查询,将键值对从磁盘里读取、排序再写入,会带来50倍以上的写放大。这种对HDD有利的优化方式不适用于当下使用较多的SSD,因此我们需要对其功能进行修改和优化。
### 实现功能
本项目要实现的内容及目的是:
+ **字段设计**:模仿关系型数据库,扩展`value`的结构,在`value`中多个字段,并可以通过这些字段进行查询对应的`key`,实现类似关系数据库中按列查询的功能
+ **KV分离**:分离存储LevelDB的`key`和`value`,LSM树中的value为一个指向`Value Log`文件的指针,用户的真实`value`存储在`Value Log`中,减轻LSM树的存储负载,大幅度减小了读写放大的性能影响
## 2. 功能设计
#### 2.1. 字段设计
- 设计目标
- 将 LevelDB 中的 `value` 组织成字段数组,每个数组元素对应一个字段(字段名:字段值)。
- 不改变LevelDB原有的存储方式,通过对字段数组的序列化和对字符串解析得到字段数组来实现字段功能
- 在作为key-value对存储进LevelDB之前可以任意调整字段
- 可以通过字段查询对应的key
#### 2.2. KV分离
- 设计目标
- 拓展key-value存储结构,分离key和value的存储,从而对写放大进行优化
- 不影响LevelDB原本接口的正常功能
- 分离存储Value的Value-Log需要有对应的GC(Garbage Collection)功能,在达到一定条件(如Value -Log超过大小阈值)时触发,回收Value-Log中已经失效的Value
- 确保操作的原子性
## 3. Methodology
#### 3.1. 字段功能
对应文件:`db/fields.*`
- Field, FieldArray
- ```c++
using Field = std::pair<std::string, std::string>;
using FieldArray = std::vector<std::pair<std::string, std::string>>;
```
- Fields
- 封装有 `std::map<std::string, std::string>` 的class,代替原本的 `value` 成为`leveldb` 新的存储单位,用map实现在字段较多时可以获得较高的查询效率,提供以下接口:
- ``````c++
class Fields {
public:
// 从FieldArray构建Fields
explicit Fields(const FieldArray& field_array);
// 从LevelDB存储的Value中解码出Fields
explicit Fields(const Slice& fields_str);
Fields() = default;
~Fields();
// 重载[]运算符简便对字段的修改和访问操作
std::string& operator[](const std::string& field_name);
// 获取当前Fields对应的FieldArray
FieldArray GetFieldArray() const;
// 将Fields编码为存入LevelDB的Value
std::string Serialize() const;
uint64_t size() const { return size_; }
private:
std::map<std::string, std::string> _fields;
uint64_t size_ = 0;
};
``````
- FieldString
- `Field String` 是类 `Fields` 等价的编码字符串,`Fields` 可以编码为 `Field String` ,`Field String` 可以解码为 `Fields`
- 编码后的结构为:
![fields](./assets/fields.png)
编码和解码的代码基本调用原本的函数 `PutVarint64``GetVarint64` 等,非常简单,不在此贴出,可以前往 `db/fields.*` 文件中查看具体实现
#### 3.2 KV分离
- **KV分离的基本框架:**
![kv_overview](./assets/kvsep_overview.png)
KV分离发生在 `leveldb` 的小合并的过程中,用户可以自定义一个 `kv_sep_threshold` ,默认为 `1000` ,单位是Byte。当数据从内存中落盘时,根据 `value` 的大小是否超过阈值判断是否要进行KV分离,由于小的Value并不会造成明显的写放大,如果进行分离会严重影响其读性能,弊大于利,因此仅对大的Value进行KV分离是一种能提高小Value读取速度的优化。
此时,存入SSTable的 `value` 存在两种情况:
- 真实的value值(value较小)
- value在VTables中的位置(value较大)
我们通过在Value前增加type标识来区分这两种情况:
```c++
enum Type : unsigned char {
kVTableIndex = 1,
kNonIndexValue = 2,
};
```
`kVTableIndex` 表示该value是一个指向value的地址,`kNonIndexValue` 表示该value为value的真实值。两种情况的value如图所示:
![sst](./assets/sst_value.png)
- **VTable Format**
接下来对VTable文件结构以及编码和解码进行介绍,代码实现位于文件 `table/vtable_format.*`
VTable的整体结构图:
![vtable](./assets/vtable.png)
`VTable` 最基本的存储单位为 `VTableRecord` ,其内容包含存储的 `key` `value` 对,提供 `Encode``Decode` 方法进行编码解码,基本使用 `utils/coding.*`的方法,本报告中忽略基本的编码解码代码:
```c++
// VTable最基本的存储单位,表示存储的一个key和一个value
struct VTableRecord {
Slice key;
Slice value;
// 将record编码为str
void Encode(std::string* target) const;
// 将Slice解码为record
Status Decode(Slice* input);
// 该record的size
size_t size() const { return key.size() + value.size(); }
};
```
要将 `VTableRecord` 写入 `VTable` ,需要将 `VTableRecord` 结构体编码为一个 `Header` 和相应的 `Record` (<key_size, key, value_size, value>)
为了方便的编码 `VTableRecord` 以构建VTable,实现了 `RecordEncoder` 类对编码过程进行了封装,简化了编码过程:
```c++
class RecordEncoder {
public:
// TODO: Support compression while encoding a record
RecordEncoder() = default;
// 编码一条vTable record
void Encode(const VTableRecord& record);
// 获得编码后的records的size
size_t GetEncodedSize() const { return sizeof(header_) + record_.size(); }
// 获取编码后的header
Slice GetHeader() const { return {header_, sizeof(header_)}; }
// 获得编码后的record
Slice GetRecord() const { return record_; }
private:
char header_[kRecordHeaderSize];
Slice record_;
std::string record_buff_;
};
```
`RecordEncoder::Encode` 方法将对 `record` 进行编码并生成对应的 `header`,Encode完成后就可以调用该类的另外几个方法获得编码后的数据 :
```c++
void RecordEncoder::Encode(const VTableRecord& record) {
record_buff_.clear();
record.Encode(&record_buff_);
record_ = Slice(record_buff_.data(), record_buff_.size());
EncodeFixed32(header_, static_cast<uint32_t>(record_.size()));
}
```
`VTable` 中获得 `Slice` 后要将其解码为 `VTableRecord`,为此实现了 `RecordDecoder` 类,对解码过程同样进行了封装:
```c++
class RecordDecoder {
public:
// 解码出record的header
Status DecodeHeader(Slice* input);
// 解码出record
Status DecodeRecord(Slice* input, VTableRecord* record) const;
// 获得解码后的record size
size_t GetDecodedSize() const { return record_size_; }
private:
uint32_t record_size_{0};
};
```
使用时先使用 `DecodeHeader` 解码`header` 获得 `record` 的相关信息,再调用 `DecodeRecord` 解码 `record` 的内容
至此,我们已经可以方便的将KV对编码为可以写入VTable的内容,也可以方便的从编码好的 `Slice` 中解码出相应的KV对,我们接下来需要定义 `SSTable` 中存储的 `VTableIndex`,以建立 `SSTable``index``VTable``VTableRecord` 的映射关系
`VTable Index` 的结构如图所示:
![VTableIndex](./assets/vtable_index.png)
其在代码结构中的定义:
```c++
struct VTableHandle {
// 表示某个record在VTable中的位置
uint64_t offset{0};
uint64_t size{0};
void Encode(std::string* target) const;
Status Decode(Slice* input);
};
struct VTableIndex {
// 存入sstable中的index
enum Type : unsigned char {
kVTableIndex = 1,
};
uint64_t file_number{0};
VTableHandle vtable_handle;
void Encode(std::string* target) const;
Status Decode(Slice* input);
};
```
通过结构体自带的 `Encode``Decode` 方法可以将 `VTableIndex` 轻松的编码为写入 `SSTable``Index` ,也可以轻松的将 `SSTable` 中的 `Index` 解码为 `VTableIndex` 结构体
- **VTable Manager**
为了进行 `GC(Garbage Collection)`,我们会在内存中保存每个 `VTable` 的元数据(meta),`GC` 的具体方法将在后文介绍,本处引出 `VTable Manager` 的部分功能以帮助说明接下来的功能,代码位于 `table/vtable_manager.*`
`VTableManager` 会作为 `DBImpl` 的成员和数据库共享生命周期
`VTableManager``VTableMeta` 结构如下:
![meta](./assets/meta.png)
`VTable Manager` 中用 `VTable Number` 映射到该 `VTable` 对应的元数据,每个 `VTable` 的元数据包括:
- File Num: VTable的序号 `VTable Number`
- Records Num: 该VTable中的Record的总数量
- Invalid Num:该VTable中无效的Record的总数量
- Table Size:该VTable的文件大小
- Ref:该VTable目前被几个 `Reader` 读取
`VTable Meta``Vtable Manager` 的代码结构如下:
```c++
struct VTableMeta {
uint64_t number;
uint64_t records_num;
uint64_t invalid_num;
uint64_t table_size;
uint64_t ref = 0;
void Encode(std::string* target) const;
Status Decode(Slice* input);
VTableMeta() : number(0), records_num(0), invalid_num(0), table_size(0) {}
};
class VTableManager {
public:
explicit VTableManager(const std::string& dbname, Env* env,
size_t gc_threshold) :
dbname_(dbname),
env_(env),
gc_threshold_(gc_threshold) {}
~VTableManager() = default;
// sign a vtable to meta
void AddVTable(const VTableMeta& vtable_meta);
// remove a vtable from meta
void RemoveVTable(uint64_t file_num);
// add an invalid num to a vtable
Status AddInvalid(uint64_t file_num);
// save meta info to disk
Status SaveVTableMeta() const;
// recover meta info from disk
Status LoadVTableMeta();
// reference a vtable
void RefVTable(uint64_t file_num);
// unref a vtable
void UnrefVTable(uint64_t file_num);
// maybe schedule backgroud gc
void MaybeScheduleGarbageCollect();
// do backgroud gc work
static void BackgroudGC(void* gc_info);
private:
std::string dbname_;
Env* env_;
std::map<uint64_t, VTableMeta> vtables_;
std::vector<uint64_t> invalid_;
size_t gc_threshold_;
};
```
非GC相关的方法多为增加减少计数和 `VTable Meta` ,因此报告中不展示其具体实现,可在对应文件中找到相关代码
由于 `VTable Manager` 是在 `leveldb` 运行过程中在内存中维护的数据结构,因此一旦程序停止运行,即数据库关闭, `VTable Manager` 存储的元数据就会丢失,而作为一个数据库,其可以在关闭后重启,重启时可以通过遍历所有 `VTable` 并且用其中的key恢复上次关闭时的元数据信息,但是这样恢复的效率在数据量较大时会产生大量的读磁盘,导致启动速度极慢。为了解决这个问题,这里采用了类似 `Log` 的机制,`VTable Manager` 提供了 `SaveVTableMeta` 方法用于将当前元数据状态写入磁盘, `LoadVTableMeta` 方法用于从磁盘中读取并恢复元数据状态
在时机上,遵从 `leveldb` 的机制,即在 `version set` `LogAndApply` 时调用 `SaveVTableMeta` 保存当前数据库 `VTable Meta` 状态,在数据库启动时的恢复过程中调用 `LoadVTableMeta` 读取关机时数据库中的 `VTable Meta` 状态
- **VTable Builder**
在上文中我们完成了对 `VTable` 结构的定义,现在需要考虑的问题是如何构建一个 `VTable`
`SSTable` 提供了 `TableBuilder` 类的封装来方便的构建 `SSTable`,我们同样提供了 `VTableBuilder` 类对 `VTable` 构建进行了封装,从而可以在KV分离功能注入时方便的构建 `VTable` ,代码位于文件 `table/vtable_builder.*`
`VTableBuilder` 的代码结构如下:
```c++
class VTableBuilder {
public:
VTableBuilder(const Options& options, WritableFile* file);
// Add a record to the vTable
void Add(const VTableRecord& record, VTableHandle* handle);
// Builder status, return non-ok iff some error occurs
Status status() const { return status_; }
// Finish building the vTable
Status Finish();
// Abandon building the vTable
void Abandon();
uint64_t FileSize() const { return file_size_; }
uint64_t RecordNumber() const { return record_number_; }
private:
bool ok() const { return status().ok(); }
WritableFile* file_;
uint64_t file_size_{0};
uint64_t record_number_{0};
Status status_;
RecordEncoder encoder_;
};
```
`VTableBuilder` 拥有上文提到的 `RecordEncoder` 用于编码 `Record`,以及要写入的目标 `VTable` 文件
`VTableBuilder` 在建立后必须调用 `Finish``Abondon` 方法中的一个来结束构建,前者完成文件写入,后者放弃文件的构建
`Add` 方法用于向目标 `Vtable` 中加入一个 `Record` ,并返回该 `Record` 在目标 `VTable` 中的 `VTableHandle` ,即其 `offset``size`
`Add` 方法通过上文的 `RecordEncoder` ,可以很轻松的实现:
```c++
void VTableBuilder::Add(const VTableRecord& record, VTableHandle* handle) {
if (!ok()) return;
encoder_.Encode(record);
handle->offset = file_size_;
handle->size = encoder_.GetEncodedSize();
file_size_ += encoder_.GetEncodedSize();
status_ = file_->Append(encoder_.GetHeader().ToString() +
encoder_.GetRecord().ToString());
record_number_ += 1;
}
```
通过返回的 `VTableHandle``VTable Number` ,就可以构造 `VTableIndex` 结构体并调用 `Encode` 编码为写入 `SSTable``Index`
- **VTable Reader**
现在我们可以方便的构建 `VTable` 了,我们还需要一个轻松读取 `VTable` 的方法,为此,我们提供了 `VTableReader` 类,其封装了对 `VTable` 内容读取的相关功能,代码位于文件 `table/vtable_reader.*`
`VTableReader` 的代码结构如下:
```c++
class VTableReader {
public:
VTableReader() = default;
VTableReader(uint64_t fnum, VTableManager *manager) :
fnum_(fnum),
manager_(manager) {};
Status Open(const Options& options, std::string fname);
Status Get(const VTableHandle& handle,
VTableRecord* record) const ;
void Close();
private:
Options options_;
uint64_t fnum_;
RandomAccessFile* file_{nullptr};
VTableManager* manager_{nullptr};
};
```
`VTableReader` 使用时首先调用 `Open` 方法打开 `VTable` 文件,这会增加 `manager`中该 `VTable` 的引用计数 **(Ref)** 然后调用 `Get` 方法,使用 `VTableHandle` 查询对应 `Record` ,并返回 `VTableRecord` 结构体,结束读取后要调用 `Close` 方法减少 `manager` 中该 `VTable``Ref` 计数
`Get` 方法实现也很简单,通过 `handle` 的信息读取对应的编码 `Slice` ,然后使用上文的 `RecordDecoder` 类的 `DecodeHeader``DecodeRecord` 方法得到解码后的 `Record`
- **KV分离功能实现**
首先是KV分离的节点,我们让KV分离发生在 `Immutable Memtable` 小合并写入磁盘的过程中,`leveldb` 在小合并中通过 `BuildTable` 函数构建 `SSTable` ,我们对该函数进行修改以实现KV分离
逻辑很简单,在 `iteratir` 遍历过程中判断 `value size` 是否达到阈值,未达到则直接写入 `SSTable` ,否则将 `value` 通过 `VTableBuilder` 写入 `VTable` 中,并向 `SSTable` 中写入对应的 `VTableIndex` ,核心代码如下:
```c++
if (value.size() < options.kv_sep_size) {
// No need to separate key and value
builder->Add(key, value);
} else {
// Separate key value
ParsedInternalKey parsed;
if (!ParseInternalKey(key, &parsed)) {
s = Status::Corruption("Fatal. Memtable Key Error");
builder->Abandon();
vtb_builder->Abandon();
return s;
}
value.remove_prefix(1);
VTableRecord record {parsed.user_key, value};
VTableHandle handle;
VTableIndex index;
std::string value_index;
vtb_builder->Add(record, &handle);
index.file_number = meta->number;
index.vtable_handle = handle;
index.Encode(&value_index);
builder->Add(key, Slice(value_index));
}
```
完成了写入时的KV分离,接下来要解决的是如何对KV分离的数据库进行数据的读取
我们采取的方法是修改 `leveldb``Get` 方法,对于找到的KV对,我们分析其Value,如果是真实Value就直接返回,否则使用 `VTableReader` 通过 `VTableIndex` 获取其真实Value并返回,最后会将其转化为 `Fields`
该过程是一个通用的做法,因此我们将其抽取出来封装为 `DBImpl` 类下的一个方法 `DecodeValue` ,对通过Key查询到的Value进行上述一系列分析:
```c++
Status DBImpl::DecodeValue(std::string* value) const {
std::string tmp = *value;
auto input = new Slice(tmp);
unsigned char type;
if (!GetValueType(*input, &type)) {
return Status::Corruption("Fatal Value Error");
}
if (type == kNonIndexValue) {
input->remove_prefix(1);
*value = input->ToString();
return Status::OK();
}
if (type == kVTableIndex) {
VTableIndex index;
VTableRecord record;
Status s = index.Decode(input);
if (!s.ok()) {
return s;
}
VTableReader reader(index.file_number, this->vtable_manager_);
std::string vtb_name = VTableFileName(this->dbname_, index.file_number);
s = reader.Open(this->options_, vtb_name);
if (!s.ok()) {
reader.Close();
return s;
}
s = reader.Get(index.vtable_handle, &record);
if (!s.ok()) {
reader.Close();
return s;
}
*value = record.value.ToString();
reader.Close();
return s;
}
return Status::Corruption("Unsupported value type");
}
```
完成了 `Get``Put` 方法,我们还需要确保 `iterator` 能够正常使用,以提供范围查询功能
由于当前 `leveldb` 已经实现了 `Fileds` 功能,原本的 `Iterator::value` 方法已经被弃用,取而代之的是 `Iterator::fields` 方法,该方法同样经过上述 `DeocodeValue` 流程,最后返回 `Fields` 类,`DBIter` 中的具体实现:
```c++
Fields fields() const override {
assert(valid_);
if (direction_ == kForward) {
std::string field_str = iter_->value().ToString();
db_->DecodeValue(&field_str);
return Fields(Slice(field_str));
} else {
std::string field_str = saved_value_;
db_->DecodeValue(&field_str);
return Fields(Slice(field_str));
}
}
```
根据原本 `leveldb``Delete` 逻辑,其插入了一条特殊的Key表示删除,因此无需修改仍可正常使用
为了完成上述对主要方法的支持,还向 `leveldb` 中原本的文件名相关代码中注入了 `VTable` 相关的内容
`filename.h` 中增加了 `FileType` ,包括 `kVTableFile``kVTableManagerFile` ,增加了两个方法 `VTableFileName``VTableManagerFileName` ,返回对应的文件名
`filename.cc``ParseFileName` 方法中增加了对上述两种文件名的分析
- **Garbage Collection (GC)**
GC是KV分离中的一个非常重要的问题,虽然KV分离的功能显著缓解了原本的写放大问题,但是一旦相同的key有新数据写入,那么原本在 `VTable` 中的旧value已经失效,但是其仍留存在磁盘中,久而久之会造成严重的空间浪费,因此要有GC机制去回收这些额外占用的空间
**传统GC**: 传统GC的方法都相差不大,主要思想都是在合并时统计每个参与合并的 `VTable` 失效的大小,当大小达到一定阈值时对这些文件进行GC,做法是遍历整个 `VTable` ,用其中的key在LSM-Tree中进行查询,如果当前value已过期则跳过,若未过期则写入新的 `VTable` 中,最后回收之前的整个`VTable` ,将新写入 `VTable` 的KV对重新插入LSM-Tree,这种做法会导致额外的写放大,并且要进行多次的查询,GC过程中会严重影响前台的表现
最近,一种新的GC方法被提出,在 `TitanDB` 中作为一项实验功能,名为 `Level Merge` ,其在Compaction过程中,对于要保留的KV对直接写入新的 `VTable` 中,在 `Builder` 构造 `SSTable` 时将其value直接换位新的Index,该过程相当于完成了GC的工作,对于没有有效数据的VTable则可以直接删除,省去了多次查询和插入带来的开销。但由于这种方法本身也会带来写放大,会影响性能,因此只在最后两个 `level` 进行上述 `level merge` ,因为大量的数据都落在最后这两层,无效数据的含量也较高,因此可以在对性能影响较小的情况下优雅的完成GC
关于 `Level Merge` 执行的层数,DiffKV中也选择仅对最后两层执行
综上,我们选择使用新的GC方法,并提供config中配置执行Level Merge的层数
- **GC Overview:**
![gc](./assets/gc.png)
在合并中,如果level低于配置层数,对于需要drop的数据,我们在manager中为其对应的 `VTable` 增加一个 `Invalid` 计数,其他的数据按原样合并。如果level高于配置层数,不仅对需要drop的KV对增加 `Invalid` 计数,需要保留的KV对通过 `VTableBuilder` 重新构造新的VTable将其写入,并在新的 `SSTable` 中写入新的Index,为原 `VTable` 增加一个 `Invalid` 计数
每次增加 `Invalid` 计数时,都会判断该 `VTable``Invalid` 计数是否达到 `Record Num` ,若达到则将其加入 `invalid_` list中,作为GC的候选文件,然后调用 `MaybeScheduleGC` ,判断是否调度GC线程
由于GC过于频繁会影响前台性能,因此我们提供了一个设置,可以调整GC的threshold,即失效文件总大小达到该阈值时,才调度一次GC
如果要调度GC,此时会为GC构建一个 `delete_list` ,判断 `invalid_` 中是否还有文件正在被别的线程读取,仅将 `Ref` 为0的 `VTable` 加入 `delete_list` 中,其它的将继续保留等待下一次调度
最终,manager会将这个删掉的 `VTable元数据` 从内存中抹除,后台GC线程会将这些文件从磁盘中删除
## 4. 实验
### 4.1 正确性实验:
对KV分离改造后的数据库的正确性进行实验,主要测试 `Fields` 功能和 `leveldb` 的基本功能,即写入,点查询和范围查询等
正确性实验代码位于 `test/*` 目录下,`test_fileds.cc` 验证了 `Fields` 功能的正确性,`test_basicio.cc` 验证了 `leveldb` 的基本功能的正确性,连续多次执行该测试,也能够完成数据库的重启,并且在无效数据大小超过预设 GC 大小后完成了 GC ,通过监控数据库文件夹大小即可发现GC能让数据库大小稳定在一定范围以下 (该测试key范围固定,因此多次插入无效数据必然增多)
### 4.2 **BenchMark:** v
#### 4.2.1 测试文件及使用
+ 本次实验中用于性能测试的文件有两个:
+ `benchmarks/db_bench_new.cc`:此文件基于`Leveldb`原有的`db_bench.cc`,对其进行了修改和扩写,使其能够胜任实现了字段设计和KV分离后的本实验数据库。对部分重要的、可调整的参数说明:
```c++
// 该字符串规定正式运行本文件时使用的性能测试方法
// 可在Benchmark类定义的方法中选择需要的,填写在这个字符串中
static const char* FLAGS_benchmarks;
// 运行性能测试所使用的K/V对数量,按需修改
static int FLAGS_num = 1000000;
// 规定了每个存储对象的value的大小
// 由于本实验实现的KV分离功能通过value大小判断是否需要分离
// 可以通过修改这个参数开启或关闭KV分离功能的性能测试
static int FLAGS_value_size = 1000;
```
+ `test/test_bench.cc`:由于`db_bench_new.cc`文件是进行整体测试的,对于单个操作和功能的测试并不方便,因此我们同时编写了这个文件,以便于单独测试`Put(), Get(), Iterator(), FindKeysByField()`等操作的性能,包括了吞吐量和延迟,其中对于延迟的测试同时可以输出平均延迟、P75延迟和P99延迟。在不进行修改直接运行`test_bench.cc`的情况下,能够输出以上所有信息。
+ **注意:** 两个文件的`benchmark`测出的性能都是实机性能,会受到机型配置影响,且在同一台主机运行时也会受到实时性能影响。下图是一张成功运行`db_bench_new.cc`的截图,以此为演示样例,本小组进行性能测试的虚拟机配置也如图中信息所示:
![db_bench_new](/assets/db_bench_new.png)
+ 为了尽可能保证测试的准确性,下文所展示的性能测试的结果均是在相同条件下重复运行几十次`benchmark`后取平均值所得。
#### 4.2.2 性能预期
本次实验中要通过`benchmark`检测的功能主要有:
+ `Put(), Get(), Iterator(), FindKeysByField()`等基本功能的吞吐量(Throughput)和延迟(Latency);
+ KV分离功能对读写性能的影响;
+ 后台GC是否成功,对性能产生的影响;
在正式开始性能测试前,应当先分析预测,有的放矢,与实机效果对比,判断功能是否符合预期。
1. `Put(), Get(), Iter()`分别是写入数据和点查询、范围查询读取数据的基本功能函数,这些操作的吞吐量直接反映了数据库的读写速度。
2. `FindKeysByField()`是在实现字段设计功能后添加的函数。为了保证查准率和查全率,该函数用`iterator`依序遍历了整个数据库,其运行速度必然很慢。若想提升其性能,应该考虑二级索引相关的设计。故在本小组的性能测试中,此功能的性能仅作为了解参考,而非检验KV分离性能的标准。
3. KV分离功能会显著地提高写入数据的性能,代价是牺牲一部分读取数据的性能。同时,KV分离后的数据库在合并(Compact)时的性能应该大幅提升,且写放大的开销会有所减少。
4. 后台GC会清除过期的或遭遗弃的VTable,减轻数据库的负载。同时GC过程中,读写等操作会受到阻塞,性能略微下降。而且由于本小组实现的GC只有在`level`达到最高两层时才会生成新的VTable,而这种情况很少发生,因此产生的额外写放大开销几乎可以忽略不计。
#### 4.2.3 性能测试
##### Part. A 通过db_bench观察整体性能
`LevelDB`自带的`db_bench`可以统括地展示数据库的整体性能。这张图是仅仅实现了字段设计的数据库性能:
![bench_1](/assets/db_bench_1.jpg)
下面这张图是实现了完整的KV分离功能的数据库的性能:
![bench_2](/assets/db_bench_2.jpg)
可以明显地看出来,写入数据的性能(`fillseq, fillrandom`)提升了将近两倍,而合并(compact)的耗时缩短了十倍以上。这与上一部分中我们的预期基本吻合,说明从这个角度看KV分离是成功地提升了数据库的性能。
使用`test_bench.cc`则可以直接测出读、写、扫描等操作的性能。不过,只有通过不同情境下的性能比较才能体现出我们实现的KV分离功能的作用。以下是我预设的几个可以体现性能差异的场景。
##### Part. B 面对不同的value_size时数据库的性能,以及GC对性能的影响
在这一部分,我们将数据库根据功能的完善程度不同分为三个版本:实现了KV分离的数据库,触发了GC;KV分离但不触发GC的数据库;仅有字段设计的原LevelDB。
在实际操作时,我们的版本控制实际上只需要分为功能完善的KV分离数据库和没有KV分离功能的LevelDB。对于是否使用新GC,可以在`include/leveldb/options.h`中修改`gc_size_threshold`这一变量的大小。该值越小,后台自动GC越容易被触发;反之,将其调到极大时,就相当于禁用了新GC。通过控制GC是否触发,可以大致测得GC对数据库性能的影响。
使用`test_bench.cc`文件,将全局变量的`value_size_`修改为不同的值,重复测试。这里选择的是50,500,1000,2000。这里设定的KV分离阈值是1000,即对于`value_size`超过1000的文件对象才使用KV分离。
为了直观展现KV分离的性能,这里选择用测得的在不同的`value_size`情况下,`Put()`操作的吞吐量的差异,绘图表现。这里要说明的是,测试脚本`test_bench.cc`里通过`Put()`实现的是随机写功能,因此可以直观反映数据库写性能的提高:
![insert](/assets/Insert_static_vsize.png)
类似地,使用`test_bench.cc`可以测得`Put()`的延迟,以及其他操作的吞吐量和延迟。这里不一一作图展示。
##### Part. C 面对不固定的value_size时数据库的性能
在数据库的实际应用场景中,通常来说不可能遇到`value_size`不变的数据。本小组实现的KV分离数据库在面对`value_size`比较小的数据时不会使用KV分离功能,这是考虑到小数据的写入、合并开销并不大,贸然分离存储反而可能由于读取性能降低导致数据库整体性能受影响。能够灵活面对实际应用场景中不同大小的数据,正是这种设计思路的初衷。
我在`test_bench.cc`插入数据的函数`InsertData()`中加入了随机数,用来随机生成不同大小的`value_size`。
需要注意的是:
+ 由于`InsertData()`本身是随机插入,其`key`值也是个随机数,在生成这两个随机数的时候需要用到不同的随机数生成函数。
+ 测试不同版本数据库时需要控制变量,因此需要控制不同测试时,随机数的种子保持不变。
在这次性能测试中,我们设定的`value_size`的随机范围是`500~2048`,预设的KV分离阈值是1000,正好可以模拟实际应用情况。同时,我们还是设定了对于全部数据都使用KV分离和完全不使用KV分离的两种数据库作为对照组。
![randvsizet](/assets/randvalue.png)
Latency等数据不便于在图中展示,这里省略。
##### Part. D 不同数据量的写放大开销
写放大 = 输入磁盘的数据总量 / 实际数据量。
在`test_bench`中,我加入了一个全局变量`bytes_`用于监控文件大小,可以通过调用它来输出;然后在每次运行`test_bench`后,生成的LOG文件中有每次合并产生的新文件的大小信息。将LOG文件中所有写入文件的大小相加,再与`bytes_`相比,可以算出写放大这个比值。
通过调整`value_size`,我发现写放大与`value_size`有一定相关性,且实现KV分离的数据库写放大明显减少。
![writeampli](/assets/writeampli.png)
##### Part. E 其他指标
关于其他操作的延迟、吞吐量可以运行`test_bench`直接输出。
对于GC的持续时间,我在实施GC的函数里做了标记,可以输出GC函数的持续时间。通过大量的测试,算出GC持续时间的平均值在600微妙-1000微秒之间,而且似乎和`value_size`等关系不大,没有直接影响因素,因此这里给出一个范围而非准确值。
## 5. 可能的优化空间
- 经过KV分离的数据库,虽然写性能有明显的上升,但在读性能上有明显的下降,为了优化读性能,可以为 `VTable` 设置Cache机制,从而提高顺序读和随机读的性能,但本身 `VTable` 的value较大,Cache可能会需要较多的内存,会增加内存的开销,属于一种空间换时间的优化
- 将 `VTable` 也以类似树的结构按层组织,并在compaction过程中也对 `VTable` 进行Merge,过程中利用 `VTable` 中的key使新得到的 `VTable` 中的key变得和 `SSTable` 一样有序,这样可以提高顺序读的性能
## 6. 实验中遇到的问题
- 如何获得GC相关的信息,最终决定在内存中维护一个 `VTableManager` 用于存储 `VTable` 的相关信息以调度GC
- 设计 `VTableManager` 后,如何保证数据库的重启恢复功能,并且在恢复后仍能正常保留GC相关信息,一开始考虑将其融入 `VersionSet` 中,但由于时间有限,对 `leveldb` 做出侵入性更改可能会带来一系列问题,最终决定跟随 `VersionSet``LogAndApply` 使用自己实现的方法将其存入磁盘中
- 在小合并进行KV分离过程中,一开始忘记了 `BuildTable` 时使用的是 `Immutable Memtable``Iterator` ,其中的 key 是 `Internal Key`,而不是传入的 `User Key` ,导致了一系列错误,最终在 `BuildTable` 中对 `Internal Key` 进行 Parse,并取出其中的 `User Key` 写入 `VTable`
## 7. 结论
本次实验中,尝试了在leveldb的基础上实现Fields功能和KV分离功能,并对其性能进行了大量测试,与未KV分离的Baseline进行对比,发现KV分离后,对于大Value数据的写入吞吐量有明显的提升,显著降低了写放大,虽然读性能也有了不小的下降,但仍然是可以接受的速度。还提出了可能的优化方案,理论上可以提高KV分离后的读性能。

BIN
assets/Insert_static_vsize.png View File

Before After
Width: 568  |  Height: 453  |  Size: 40 KiB

BIN
assets/db_bench_1.jpg View File

Before After
Width: 1112  |  Height: 862  |  Size: 194 KiB

BIN
assets/db_bench_2.jpg View File

Before After
Width: 996  |  Height: 850  |  Size: 206 KiB

BIN
assets/db_bench_new.png View File

Before After
Width: 564  |  Height: 527  |  Size: 23 KiB

BIN
assets/fields.png View File

Before After
Width: 701  |  Height: 145  |  Size: 13 KiB

BIN
assets/gc.png View File

Before After
Width: 854  |  Height: 592  |  Size: 77 KiB

BIN
assets/kvsep_overview.png View File

Before After
Width: 1033  |  Height: 494  |  Size: 88 KiB

BIN
assets/meta.png View File

Before After
Width: 704  |  Height: 322  |  Size: 29 KiB

BIN
assets/randvalue.png View File

Before After
Width: 1348  |  Height: 818  |  Size: 63 KiB

BIN
assets/sst_value.png View File

Before After
Width: 501  |  Height: 151  |  Size: 14 KiB

BIN
assets/vtable.png View File

Before After
Width: 913  |  Height: 475  |  Size: 57 KiB

BIN
assets/vtable_index.png View File

Before After
Width: 504  |  Height: 242  |  Size: 16 KiB

BIN
assets/writeampli.png View File

Before After
Width: 1345  |  Height: 868  |  Size: 60 KiB

+ 19
- 3
benchmarks/db_bench.cc View File

@ -74,7 +74,7 @@ static int FLAGS_reads = -1;
static int FLAGS_threads = 1; static int FLAGS_threads = 1;
// Size of each value // Size of each value
static int FLAGS_value_size = 100;
static int FLAGS_value_size = 1000;
// Arrange to generate values that shrink to this fraction of // Arrange to generate values that shrink to this fraction of
// their original size after compression // their original size after compression
@ -134,6 +134,15 @@ namespace leveldb {
namespace { namespace {
leveldb::Env* g_env = nullptr; leveldb::Env* g_env = nullptr;
void EncodeNonIndexValue(const Slice& value, std::string* res) {
enum Type : unsigned char {
kNonIndexValue = 2,
};
res->push_back(kNonIndexValue);
res->append(value.ToString());
}
class CountComparator : public Comparator { class CountComparator : public Comparator {
public: public:
CountComparator(const Comparator* wrapped) : wrapped_(wrapped) {} CountComparator(const Comparator* wrapped) : wrapped_(wrapped) {}
@ -852,8 +861,15 @@ class Benchmark {
for (int j = 0; j < entries_per_batch_; j++) { for (int j = 0; j < entries_per_batch_; j++) {
const int k = seq ? i + j : thread->rand.Uniform(FLAGS_num); const int k = seq ? i + j : thread->rand.Uniform(FLAGS_num);
key.Set(k); key.Set(k);
batch.Put(key.slice(), gen.Generate(value_size_));
bytes += value_size_ + key.slice().size();
auto value = gen.Generate(value_size_);
FieldArray field_array = {
{"1", value.ToString()},
};
auto field_str = Fields(field_array).Serialize();
std::string encoded_value;
EncodeNonIndexValue(field_str, &encoded_value);
batch.Put(key.slice(), Slice(encoded_value));
bytes += encoded_value.size() + key.slice().size();
thread->stats.FinishedSingleOp(); thread->stats.FinishedSingleOp();
} }
s = db_->Write(write_options_, &batch); s = db_->Write(write_options_, &batch);

+ 1248
- 0
benchmarks/db_bench_new.cc
File diff suppressed because it is too large
View File


+ 16
- 3
db/builder.cc View File

@ -8,15 +8,19 @@
#include "db/filename.h" #include "db/filename.h"
#include "db/table_cache.h" #include "db/table_cache.h"
#include "db/version_edit.h" #include "db/version_edit.h"
#include "leveldb/db.h" #include "leveldb/db.h"
#include "leveldb/env.h" #include "leveldb/env.h"
#include "leveldb/iterator.h" #include "leveldb/iterator.h"
#include "table/vtable_builder.h" #include "table/vtable_builder.h"
#include "table/vtable_manager.h"
namespace leveldb { namespace leveldb {
Status BuildTable(const std::string& dbname, Env* env, const Options& options, Status BuildTable(const std::string& dbname, Env* env, const Options& options,
TableCache* table_cache, Iterator* iter, FileMetaData* meta) {
TableCache* table_cache, Iterator* iter, FileMetaData* meta,
VTableMeta* vtable_meta) {
Status s; Status s;
meta->file_size = 0; meta->file_size = 0;
iter->SeekToFirst(); iter->SeekToFirst();
@ -46,8 +50,7 @@ Status BuildTable(const std::string& dbname, Env* env, const Options& options,
if (value.size() < options.kv_sep_size) { if (value.size() < options.kv_sep_size) {
// No need to separate key and value // No need to separate key and value
builder->Add(key, value); builder->Add(key, value);
}
else {
} else {
// Separate key value // Separate key value
ParsedInternalKey parsed; ParsedInternalKey parsed;
if (!ParseInternalKey(key, &parsed)) { if (!ParseInternalKey(key, &parsed)) {
@ -94,6 +97,11 @@ Status BuildTable(const std::string& dbname, Env* env, const Options& options,
if (s.ok()) { if (s.ok()) {
s = vtb_builder->Finish(); s = vtb_builder->Finish();
} }
if (s.ok()) {
vtable_meta->number = meta->number;
vtable_meta->table_size = vtb_builder->FileSize();
vtable_meta->records_num = vtb_builder->RecordNumber();
}
delete vtb_builder; delete vtb_builder;
if (s.ok()) { if (s.ok()) {
@ -124,6 +132,11 @@ Status BuildTable(const std::string& dbname, Env* env, const Options& options,
} else { } else {
env->RemoveFile(fname); env->RemoveFile(fname);
} }
if (s.ok() && vtable_meta->table_size > 0) {
// Keep it
} else {
env->RemoveFile(vtb_name);
}
return s; return s;
} }

+ 4
- 1
db/builder.h View File

@ -7,6 +7,8 @@
#include "leveldb/status.h" #include "leveldb/status.h"
#include "table/vtable_manager.h"
namespace leveldb { namespace leveldb {
struct Options; struct Options;
@ -23,7 +25,8 @@ class VersionEdit;
// If no data is present in *iter, meta->file_size will be set to // If no data is present in *iter, meta->file_size will be set to
// zero, and no Table file will be produced. // zero, and no Table file will be produced.
Status BuildTable(const std::string& dbname, Env* env, const Options& options, Status BuildTable(const std::string& dbname, Env* env, const Options& options,
TableCache* table_cache, Iterator* iter, FileMetaData* meta);
TableCache* table_cache, Iterator* iter, FileMetaData* meta,
VTableMeta* vtable_meta);
} // namespace leveldb } // namespace leveldb

+ 142
- 19
db/db_impl.cc View File

@ -33,7 +33,9 @@
#include "table/block.h" #include "table/block.h"
#include "table/merger.h" #include "table/merger.h"
#include "table/two_level_iterator.h" #include "table/two_level_iterator.h"
#include "table/vtable_builder.h"
#include "table/vtable_format.h" #include "table/vtable_format.h"
#include "table/vtable_manager.h"
#include "table/vtable_reader.h" #include "table/vtable_reader.h"
#include "util/coding.h" #include "util/coding.h"
#include "util/logging.h" #include "util/logging.h"
@ -69,7 +71,10 @@ struct DBImpl::CompactionState {
: compaction(c), : compaction(c),
smallest_snapshot(0), smallest_snapshot(0),
outfile(nullptr), outfile(nullptr),
vtb_file(nullptr),
builder(nullptr), builder(nullptr),
vtable_builder(nullptr),
vtb_num(0),
total_bytes(0) {} total_bytes(0) {}
Compaction* const compaction; Compaction* const compaction;
@ -84,8 +89,11 @@ struct DBImpl::CompactionState {
// State kept for output being generated // State kept for output being generated
WritableFile* outfile; WritableFile* outfile;
WritableFile* vtb_file;
TableBuilder* builder; TableBuilder* builder;
VTableBuilder* vtable_builder;
uint64_t vtb_num;
uint64_t total_bytes; uint64_t total_bytes;
}; };
@ -151,7 +159,8 @@ DBImpl::DBImpl(const Options& raw_options, const std::string& dbname)
background_compaction_scheduled_(false), background_compaction_scheduled_(false),
manual_compaction_(nullptr), manual_compaction_(nullptr),
versions_(new VersionSet(dbname_, &options_, table_cache_, versions_(new VersionSet(dbname_, &options_, table_cache_,
&internal_comparator_)) {}
&internal_comparator_)),
vtable_manager_(new VTableManager(dbname, raw_options.env, raw_options.gc_size_threshold)){}
DBImpl::~DBImpl() { DBImpl::~DBImpl() {
// Wait for background work to finish. // Wait for background work to finish.
@ -180,6 +189,7 @@ DBImpl::~DBImpl() {
if (owns_cache_) { if (owns_cache_) {
delete options_.block_cache; delete options_.block_cache;
} }
delete vtable_manager_;
} }
Status DBImpl::NewDB() { Status DBImpl::NewDB() {
@ -268,6 +278,8 @@ void DBImpl::RemoveObsoleteFiles() {
case kCurrentFile: case kCurrentFile:
case kDBLockFile: case kDBLockFile:
case kInfoLogFile: case kInfoLogFile:
case kVTableFile:
case kVTableManagerFile:
keep = true; keep = true;
break; break;
} }
@ -383,6 +395,11 @@ Status DBImpl::Recover(VersionEdit* edit, bool* save_manifest) {
versions_->SetLastSequence(max_sequence); versions_->SetLastSequence(max_sequence);
} }
s = vtable_manager_->LoadVTableMeta();
if (!s.ok()) {
return Status::Corruption("LoadVTableMeta failed");
}
return Status::OK(); return Status::OK();
} }
@ -511,6 +528,7 @@ Status DBImpl::WriteLevel0Table(MemTable* mem, VersionEdit* edit,
mutex_.AssertHeld(); mutex_.AssertHeld();
const uint64_t start_micros = env_->NowMicros(); const uint64_t start_micros = env_->NowMicros();
FileMetaData meta; FileMetaData meta;
VTableMeta vtable_meta;
meta.number = versions_->NewFileNumber(); meta.number = versions_->NewFileNumber();
pending_outputs_.insert(meta.number); pending_outputs_.insert(meta.number);
Iterator* iter = mem->NewIterator(); Iterator* iter = mem->NewIterator();
@ -520,7 +538,7 @@ Status DBImpl::WriteLevel0Table(MemTable* mem, VersionEdit* edit,
Status s; Status s;
{ {
mutex_.Unlock(); mutex_.Unlock();
s = BuildTable(dbname_, env_, options_, table_cache_, iter, &meta);
s = BuildTable(dbname_, env_, options_, table_cache_, iter, &meta, &vtable_meta);
mutex_.Lock(); mutex_.Lock();
} }
@ -541,6 +559,9 @@ Status DBImpl::WriteLevel0Table(MemTable* mem, VersionEdit* edit,
} }
edit->AddFile(level, meta.number, meta.file_size, meta.smallest, edit->AddFile(level, meta.number, meta.file_size, meta.smallest,
meta.largest); meta.largest);
if (vtable_meta.number > 0) {
vtable_manager_->AddVTable(vtable_meta);
}
} }
CompactionStats stats; CompactionStats stats;
@ -570,6 +591,9 @@ void DBImpl::CompactMemTable() {
edit.SetPrevLogNumber(0); edit.SetPrevLogNumber(0);
edit.SetLogNumber(logfile_number_); // Earlier logs no longer needed edit.SetLogNumber(logfile_number_); // Earlier logs no longer needed
s = versions_->LogAndApply(&edit, &mutex_); s = versions_->LogAndApply(&edit, &mutex_);
if (s.ok()) {
s = vtable_manager_->SaveVTableMeta();
}
} }
if (s.ok()) { if (s.ok()) {
@ -749,6 +773,12 @@ void DBImpl::BackgroundCompaction() {
if (!status.ok()) { if (!status.ok()) {
RecordBackgroundError(status); RecordBackgroundError(status);
} }
status = vtable_manager_->SaveVTableMeta();
if (!status.ok()) {
RecordBackgroundError(status);
}
VersionSet::LevelSummaryStorage tmp; VersionSet::LevelSummaryStorage tmp;
Log(options_.info_log, "Moved #%lld to level-%d %lld bytes %s: %s\n", Log(options_.info_log, "Moved #%lld to level-%d %lld bytes %s: %s\n",
static_cast<unsigned long long>(f->number), c->level() + 1, static_cast<unsigned long long>(f->number), c->level() + 1,
@ -822,6 +852,10 @@ Status DBImpl::OpenCompactionOutputFile(CompactionState* compact) {
mutex_.Unlock(); mutex_.Unlock();
} }
if (compact->vtb_num == 0) {
compact->vtb_num = file_number;
}
// Make the output file // Make the output file
std::string fname = TableFileName(dbname_, file_number); std::string fname = TableFileName(dbname_, file_number);
Status s = env_->NewWritableFile(fname, &compact->outfile); Status s = env_->NewWritableFile(fname, &compact->outfile);
@ -864,6 +898,28 @@ Status DBImpl::FinishCompactionOutputFile(CompactionState* compact,
delete compact->outfile; delete compact->outfile;
compact->outfile = nullptr; compact->outfile = nullptr;
if (compact->vtable_builder != nullptr && s.ok()) {
VTableMeta meta;
meta.invalid_num = 0;
meta.number = compact->vtb_num;
meta.records_num = compact->vtable_builder->RecordNumber();
meta.table_size = compact->vtable_builder->FileSize();
compact->total_bytes += meta.table_size;
s = compact->vtable_builder->Finish();
delete compact->vtable_builder;
compact->vtable_builder = nullptr;
if (s.ok()) {
s = compact->vtb_file->Sync();
}
if (s.ok()) {
s = compact->vtb_file->Close();
}
delete compact->vtb_file;
compact->vtb_file = nullptr;
vtable_manager_->AddVTable(meta);
}
if (s.ok() && current_entries > 0) { if (s.ok() && current_entries > 0) {
// Verify that the table is usable // Verify that the table is usable
Iterator* iter = Iterator* iter =
@ -898,6 +954,14 @@ Status DBImpl::InstallCompactionResults(CompactionState* compact) {
return versions_->LogAndApply(compact->compaction->edit(), &mutex_); return versions_->LogAndApply(compact->compaction->edit(), &mutex_);
} }
bool GetValueType(const Slice& input, unsigned char* value) {
if (input.empty()) {
return false;
}
*value = *input.data();
return true;
}
Status DBImpl::DoCompactionWork(CompactionState* compact) { Status DBImpl::DoCompactionWork(CompactionState* compact) {
const uint64_t start_micros = env_->NowMicros(); const uint64_t start_micros = env_->NowMicros();
int64_t imm_micros = 0; // Micros spent doing imm_ compactions int64_t imm_micros = 0; // Micros spent doing imm_ compactions
@ -921,6 +985,10 @@ Status DBImpl::DoCompactionWork(CompactionState* compact) {
// Release mutex while we're actually doing the compaction work // Release mutex while we're actually doing the compaction work
mutex_.Unlock(); mutex_.Unlock();
enum Type : unsigned char {
kVTableIndex = 1,
kNonIndexValue = 2,
};
input->SeekToFirst(); input->SeekToFirst();
Status status; Status status;
ParsedInternalKey ikey; ParsedInternalKey ikey;
@ -1007,7 +1075,44 @@ Status DBImpl::DoCompactionWork(CompactionState* compact) {
compact->current_output()->smallest.DecodeFrom(key); compact->current_output()->smallest.DecodeFrom(key);
} }
compact->current_output()->largest.DecodeFrom(key); compact->current_output()->largest.DecodeFrom(key);
compact->builder->Add(key, input->value());
auto value = input->value();
std::string new_value = value.ToString();
unsigned char type;
if(!GetValueType(value, &type)) {
break;
}
if (type == kVTableIndex) {
if (compact->compaction->level() >= config::kNumLevels - config::kLevelMergeLevel) {
if (compact->vtable_builder == nullptr) {
auto fname = VTableFileName(dbname_, compact->vtb_num);
status = env_->NewWritableFile(fname, &compact->vtb_file);
auto vtable_builder = new VTableBuilder(options_, compact->vtb_file);
compact->vtable_builder = vtable_builder;
}
VTableIndex index;
VTableRecord record;
VTableHandle handle;
status = index.Decode(&value);
VTableReader reader(index.file_number, this->vtable_manager_);
std::string vtb_name = VTableFileName(this->dbname_, index.file_number);
status = reader.Open(this->options_, vtb_name);
status = reader.Get(index.vtable_handle, &record);
reader.Close();
vtable_manager_->AddInvalid(index.file_number);
compact->vtable_builder->Add(record, &handle);
VTableIndex new_index;
new_index.file_number = compact->vtb_num;
new_index.vtable_handle = handle;
new_index.Encode(&new_value);
}
}
compact->builder->Add(key, Slice(new_value));
// Close output file if it is big enough // Close output file if it is big enough
if (compact->builder->FileSize() >= if (compact->builder->FileSize() >=
@ -1017,6 +1122,17 @@ Status DBImpl::DoCompactionWork(CompactionState* compact) {
break; break;
} }
} }
} else {
unsigned char type;
auto value = input->value();
if(!GetValueType(value, &type)) {
break;
}
if (type == kVTableIndex) {
VTableIndex vtable_index;
vtable_index.Decode(&value);
vtable_manager_->AddInvalid(vtable_index.file_number);
}
} }
input->Next(); input->Next();
@ -1054,6 +1170,11 @@ Status DBImpl::DoCompactionWork(CompactionState* compact) {
if (!status.ok()) { if (!status.ok()) {
RecordBackgroundError(status); RecordBackgroundError(status);
} }
status = vtable_manager_->SaveVTableMeta();
if (!status.ok()) {
RecordBackgroundError(status);
}
VersionSet::LevelSummaryStorage tmp; VersionSet::LevelSummaryStorage tmp;
Log(options_.info_log, "compacted to: %s", versions_->LevelSummary(&tmp)); Log(options_.info_log, "compacted to: %s", versions_->LevelSummary(&tmp));
return status; return status;
@ -1121,18 +1242,6 @@ int64_t DBImpl::TEST_MaxNextLevelOverlappingBytes() {
return versions_->MaxNextLevelOverlappingBytes(); return versions_->MaxNextLevelOverlappingBytes();
} }
namespace {
bool GetValueType(const Slice& input, unsigned char* value) {
if (input.empty()) {
return false;
}
*value = *input.data();
return true;
}
} // namespace
Status DBImpl::DecodeValue(std::string* value) const { Status DBImpl::DecodeValue(std::string* value) const {
enum Type : unsigned char { enum Type : unsigned char {
kVTableIndex = 1, kVTableIndex = 1,
@ -1151,7 +1260,6 @@ Status DBImpl::DecodeValue(std::string* value) const {
} }
if (type == kVTableIndex) { if (type == kVTableIndex) {
VTableIndex index; VTableIndex index;
VTableReader reader;
VTableRecord record; VTableRecord record;
Status s = index.Decode(input); Status s = index.Decode(input);
@ -1159,17 +1267,21 @@ Status DBImpl::DecodeValue(std::string* value) const {
return s; return s;
} }
VTableReader reader(index.file_number, this->vtable_manager_);
std::string vtb_name = VTableFileName(this->dbname_, index.file_number); std::string vtb_name = VTableFileName(this->dbname_, index.file_number);
s = reader.Open(this->options_, vtb_name); s = reader.Open(this->options_, vtb_name);
if (!s.ok()) { if (!s.ok()) {
reader.Close();
return s; return s;
} }
s = reader.Get(index.vtable_handle, &record); s = reader.Get(index.vtable_handle, &record);
if (!s.ok()) { if (!s.ok()) {
reader.Close();
return s; return s;
} }
*value = record.value.ToString(); *value = record.value.ToString();
reader.Close();
return s; return s;
} }
return Status::Corruption("Unsupported value type"); return Status::Corruption("Unsupported value type");
@ -1215,8 +1327,12 @@ Status DBImpl::Get(const ReadOptions& options, const Slice& key,
if (s.ok()) { if (s.ok()) {
s = DecodeValue(value); s = DecodeValue(value);
} }
auto fields = Fields(Slice(*value));
*value = fields["1"];
if (s.ok()) {
auto fields = Fields(Slice(*value));
*value = fields["1"];
} else {
*value = "";
}
mutex_.Lock(); mutex_.Lock();
} }
@ -1268,7 +1384,11 @@ Status DBImpl::Get(const ReadOptions& options, const Slice& key,
if (s.ok()) { if (s.ok()) {
s = DecodeValue(value); s = DecodeValue(value);
} }
*fields = Fields(Slice(*value));
if (s.ok()) {
*fields = Fields(Slice(*value));
} else {
*fields = Fields();
}
mutex_.Lock(); mutex_.Lock();
} }
@ -1684,6 +1804,9 @@ Status DB::Open(const Options& options, const std::string& dbname, DB** dbptr) {
edit.SetPrevLogNumber(0); // No older logs needed after recovery. edit.SetPrevLogNumber(0); // No older logs needed after recovery.
edit.SetLogNumber(impl->logfile_number_); edit.SetLogNumber(impl->logfile_number_);
s = impl->versions_->LogAndApply(&edit, &impl->mutex_); s = impl->versions_->LogAndApply(&edit, &impl->mutex_);
if (s.ok()) {
s = impl->vtable_manager_->SaveVTableMeta();
}
} }
if (s.ok()) { if (s.ok()) {
impl->RemoveObsoleteFiles(); impl->RemoveObsoleteFiles();

+ 3
- 0
db/db_impl.h View File

@ -17,6 +17,7 @@
#include "leveldb/env.h" #include "leveldb/env.h"
#include "port/port.h" #include "port/port.h"
#include "port/thread_annotations.h" #include "port/thread_annotations.h"
#include "table/vtable_manager.h"
namespace leveldb { namespace leveldb {
@ -210,6 +211,8 @@ class DBImpl : public DB {
Status bg_error_ GUARDED_BY(mutex_); Status bg_error_ GUARDED_BY(mutex_);
CompactionStats stats_[config::kNumLevels] GUARDED_BY(mutex_); CompactionStats stats_[config::kNumLevels] GUARDED_BY(mutex_);
VTableManager* vtable_manager_ {};
}; };
// Sanitize db options. The caller should delete result.info_log if // Sanitize db options. The caller should delete result.info_log if

+ 2
- 0
db/dbformat.h View File

@ -24,6 +24,8 @@ namespace leveldb {
namespace config { namespace config {
static const int kNumLevels = 7; static const int kNumLevels = 7;
static const int kLevelMergeLevel = 2;
// Level-0 compaction is started when we hit this many files. // Level-0 compaction is started when we hit this many files.
static const int kL0_CompactionTrigger = 4; static const int kL0_CompactionTrigger = 4;

+ 2
- 1
db/fields.cc View File

@ -7,6 +7,7 @@ namespace leveldb {
assert(!field_array.empty()); assert(!field_array.empty());
for (const auto& field : field_array) { for (const auto& field : field_array) {
this->_fields[field.first] = field.second; this->_fields[field.first] = field.second;
this->size_ += field.first.size() + field.second.size();
} }
} }
@ -25,7 +26,7 @@ namespace leveldb {
Slice value = Slice(field.data() + name_size, field.size() - name_size); Slice value = Slice(field.data() + name_size, field.size() - name_size);
this->_fields[name.ToString()] = value.ToString(); this->_fields[name.ToString()] = value.ToString();
this->size_ += name.ToString().size() + value.ToString().size();
fields = Slice(fields.data() + field_size, fields.size() - field_size); fields = Slice(fields.data() + field_size, fields.size() - field_size);
} }
} }

+ 3
- 0
db/fields.h View File

@ -33,8 +33,11 @@ namespace leveldb {
// Fields编码为存入LevelDB的Value // Fields编码为存入LevelDB的Value
std::string Serialize() const; std::string Serialize() const;
uint64_t size() const { return size_; }
private: private:
std::map<std::string, std::string> _fields; std::map<std::string, std::string> _fields;
uint64_t size_ = 0;
}; };
} // namespace leveldb } // namespace leveldb
#endif //STORAGE_LEVELDB_FIELDS_H_ #endif //STORAGE_LEVELDB_FIELDS_H_

+ 10
- 1
db/filename.cc View File

@ -36,7 +36,7 @@ std::string TableFileName(const std::string& dbname, uint64_t number) {
} }
std::string VTableFileName(const std::string& dbname, uint64_t number) { std::string VTableFileName(const std::string& dbname, uint64_t number) {
assert(number > 0);
// assert(number > 0);
return MakeFileName(dbname, number, "vtb"); return MakeFileName(dbname, number, "vtb");
} }
@ -73,6 +73,10 @@ std::string OldInfoLogFileName(const std::string& dbname) {
return dbname + "/LOG.old"; return dbname + "/LOG.old";
} }
std::string VTableManagerFileName(const std::string& dbname) {
return dbname + "/VTableMeta";
}
// Owned filenames have the form: // Owned filenames have the form:
// dbname/CURRENT // dbname/CURRENT
// dbname/LOCK // dbname/LOCK
@ -89,6 +93,9 @@ bool ParseFileName(const std::string& filename, uint64_t* number,
} else if (rest == "LOCK") { } else if (rest == "LOCK") {
*number = 0; *number = 0;
*type = kDBLockFile; *type = kDBLockFile;
} else if (rest == "VTableMeta") {
*number = 0;
*type = kVTableManagerFile;
} else if (rest == "LOG" || rest == "LOG.old") { } else if (rest == "LOG" || rest == "LOG.old") {
*number = 0; *number = 0;
*type = kInfoLogFile; *type = kInfoLogFile;
@ -117,6 +124,8 @@ bool ParseFileName(const std::string& filename, uint64_t* number,
*type = kTableFile; *type = kTableFile;
} else if (suffix == Slice(".dbtmp")) { } else if (suffix == Slice(".dbtmp")) {
*type = kTempFile; *type = kTempFile;
} else if (suffix == Slice(".vtb")) {
*type = kVTableFile;
} else { } else {
return false; return false;
} }

+ 5
- 1
db/filename.h View File

@ -25,7 +25,9 @@ enum FileType {
kDescriptorFile, kDescriptorFile,
kCurrentFile, kCurrentFile,
kTempFile, kTempFile,
kInfoLogFile // Either the current one, or an old one
kInfoLogFile,
kVTableFile,
kVTableManagerFile// Either the current one, or an old one
}; };
// Return the name of the log file with the specified number // Return the name of the log file with the specified number
@ -72,6 +74,8 @@ std::string InfoLogFileName(const std::string& dbname);
// Return the name of the old info log file for "dbname". // Return the name of the old info log file for "dbname".
std::string OldInfoLogFileName(const std::string& dbname); std::string OldInfoLogFileName(const std::string& dbname);
std::string VTableManagerFileName(const std::string& dbname);
// If filename is a leveldb file, store the type of the file in *type. // If filename is a leveldb file, store the type of the file in *type.
// The number encoded in the filename is stored in *number. If the // The number encoded in the filename is stored in *number. If the
// filename was successfully parsed, returns true. Else return false. // filename was successfully parsed, returns true. Else return false.

+ 3
- 1
db/repair.cc View File

@ -201,9 +201,10 @@ class Repairer {
// Do not record a version edit for this conversion to a Table // Do not record a version edit for this conversion to a Table
// since ExtractMetaData() will also generate edits. // since ExtractMetaData() will also generate edits.
FileMetaData meta; FileMetaData meta;
VTableMeta vtable_meta;
meta.number = next_file_number_++; meta.number = next_file_number_++;
Iterator* iter = mem->NewIterator(); Iterator* iter = mem->NewIterator();
status = BuildTable(dbname_, env_, options_, table_cache_, iter, &meta);
status = BuildTable(dbname_, env_, options_, table_cache_, iter, &meta, &vtable_meta);
delete iter; delete iter;
mem->Unref(); mem->Unref();
mem = nullptr; mem = nullptr;
@ -212,6 +213,7 @@ class Repairer {
table_numbers_.push_back(meta.number); table_numbers_.push_back(meta.number);
} }
} }
Log(options_.info_log, "Log #%llu: %d ops saved to Table #%llu %s", Log(options_.info_log, "Log #%llu: %d ops saved to Table #%llu %s",
(unsigned long long)log, counter, (unsigned long long)meta.number, (unsigned long long)log, counter, (unsigned long long)meta.number,
status.ToString().c_str()); status.ToString().c_str());

+ 3
- 1
include/leveldb/options.h View File

@ -101,7 +101,7 @@ struct LEVELDB_EXPORT Options {
size_t block_size = 4 * 1024; size_t block_size = 4 * 1024;
// Threshold of value size that decide whether to separate the key and value // Threshold of value size that decide whether to separate the key and value
size_t kv_sep_size = 1;
size_t kv_sep_size = 1000;
// Number of keys between restart points for delta encoding of keys. // Number of keys between restart points for delta encoding of keys.
// This parameter can be changed dynamically. Most clients should // This parameter can be changed dynamically. Most clients should
@ -118,6 +118,8 @@ struct LEVELDB_EXPORT Options {
// initially populating a large database. // initially populating a large database.
size_t max_file_size = 2 * 1024 * 1024; size_t max_file_size = 2 * 1024 * 1024;
size_t gc_size_threshold = 1024 * 1024 * 1024;
// Compress blocks using the specified compression algorithm. This // Compress blocks using the specified compression algorithm. This
// parameter can be changed dynamically. // parameter can be changed dynamically.
// //

+ 7
- 1
include/leveldb/status.h View File

@ -52,6 +52,9 @@ class LEVELDB_EXPORT Status {
static Status IOError(const Slice& msg, const Slice& msg2 = Slice()) { static Status IOError(const Slice& msg, const Slice& msg2 = Slice()) {
return Status(kIOError, msg, msg2); return Status(kIOError, msg, msg2);
} }
static Status TimeOutRead(const Slice& msg, const Slice& msg2 = Slice()) {
return Status(kTimeOutRead, msg, msg2);
}
// Returns true iff the status indicates success. // Returns true iff the status indicates success.
bool ok() const { return (state_ == nullptr); } bool ok() const { return (state_ == nullptr); }
@ -71,6 +74,8 @@ class LEVELDB_EXPORT Status {
// Returns true iff the status indicates an InvalidArgument. // Returns true iff the status indicates an InvalidArgument.
bool IsInvalidArgument() const { return code() == kInvalidArgument; } bool IsInvalidArgument() const { return code() == kInvalidArgument; }
bool IsTimeOutReadError() const { return code() == kTimeOutRead; }
// Return a string representation of this status suitable for printing. // Return a string representation of this status suitable for printing.
// Returns the string "OK" for success. // Returns the string "OK" for success.
std::string ToString() const; std::string ToString() const;
@ -82,7 +87,8 @@ class LEVELDB_EXPORT Status {
kCorruption = 2, kCorruption = 2,
kNotSupported = 3, kNotSupported = 3,
kInvalidArgument = 4, kInvalidArgument = 4,
kIOError = 5
kIOError = 5,
kTimeOutRead = 6
}; };
Code code() const { Code code() const {

+ 1
- 0
table/vtable_builder.cc View File

@ -19,6 +19,7 @@ void VTableBuilder::Add(const VTableRecord& record, VTableHandle* handle) {
status_ = file_->Append(encoder_.GetHeader().ToString() + status_ = file_->Append(encoder_.GetHeader().ToString() +
encoder_.GetRecord().ToString()); encoder_.GetRecord().ToString());
record_number_ += 1;
assert(ok()); assert(ok());
//TODO: meta info support in the future //TODO: meta info support in the future
} }

+ 5
- 0
table/vtable_builder.h View File

@ -23,11 +23,16 @@ class VTableBuilder {
// Abandon building the vTable // Abandon building the vTable
void Abandon(); void Abandon();
uint64_t FileSize() const { return file_size_; }
uint64_t RecordNumber() const { return record_number_; }
private: private:
bool ok() const { return status().ok(); } bool ok() const { return status().ok(); }
WritableFile* file_; WritableFile* file_;
uint64_t file_size_{0}; uint64_t file_size_{0};
uint64_t record_number_{0};
Status status_; Status status_;

+ 15
- 4
table/vtable_format.h View File

@ -9,13 +9,17 @@ namespace leveldb {
const uint64_t kRecordHeaderSize = 4; const uint64_t kRecordHeaderSize = 4;
// VTable最基本的存储单位key和一个value
struct VTableRecord { struct VTableRecord {
Slice key; Slice key;
Slice value; Slice value;
// record编码为str
void Encode(std::string* target) const; void Encode(std::string* target) const;
// Slice解码为record
Status Decode(Slice* input); Status Decode(Slice* input);
// record的size
size_t size() const { return key.size() + value.size(); } size_t size() const { return key.size() + value.size(); }
friend bool operator==(const VTableRecord& a, const VTableRecord& b) { friend bool operator==(const VTableRecord& a, const VTableRecord& b) {
@ -28,16 +32,16 @@ class RecordEncoder {
// TODO: Support compression while encoding a record // TODO: Support compression while encoding a record
RecordEncoder() = default; RecordEncoder() = default;
// Encode a vTable record
// vTable record
void Encode(const VTableRecord& record); void Encode(const VTableRecord& record);
// Get the size of encoded record
// records的size
size_t GetEncodedSize() const { return sizeof(header_) + record_.size(); } size_t GetEncodedSize() const { return sizeof(header_) + record_.size(); }
// Get the header
// header
Slice GetHeader() const { return {header_, sizeof(header_)}; } Slice GetHeader() const { return {header_, sizeof(header_)}; }
// Get the encoded record
// record
Slice GetRecord() const { return record_; } Slice GetRecord() const { return record_; }
private: private:
char header_[kRecordHeaderSize]; char header_[kRecordHeaderSize];
@ -48,10 +52,14 @@ class RecordEncoder {
class RecordDecoder { class RecordDecoder {
public: public:
// record的header
Status DecodeHeader(Slice* input); Status DecodeHeader(Slice* input);
// record
Status DecodeRecord(Slice* input, VTableRecord* record) const; Status DecodeRecord(Slice* input, VTableRecord* record) const;
// record size
size_t GetDecodedSize() const { return record_size_; } size_t GetDecodedSize() const { return record_size_; }
private: private:
@ -59,6 +67,7 @@ class RecordDecoder {
}; };
struct VTableHandle { struct VTableHandle {
// record在VTable中的位置
uint64_t offset{0}; uint64_t offset{0};
uint64_t size{0}; uint64_t size{0};
@ -71,6 +80,7 @@ struct VTableHandle {
}; };
struct VTableIndex { struct VTableIndex {
// sstable中的index
enum Type : unsigned char { enum Type : unsigned char {
kVTableIndex = 1, kVTableIndex = 1,
}; };
@ -86,6 +96,7 @@ struct VTableIndex {
} }
}; };
// 便
template <typename T> template <typename T>
Status DecodeSrcIntoObj(const Slice& src, T* target) { Status DecodeSrcIntoObj(const Slice& src, T* target) {
Slice input = src; Slice input = src;

+ 195
- 0
table/vtable_manager.cc View File

@ -0,0 +1,195 @@
#include "table/vtable_manager.h"
#include "db/dbformat.h"
#include "db/filename.h"
#include <iostream>
#include <ostream>
#include "leveldb/env.h"
#include "leveldb/status.h"
#include "util/coding.h"
namespace leveldb {
struct GCInfo {
std::string dbname;
std::vector<uint64_t> file_list;
Env* env = nullptr;
};
void VTableMeta::Encode(std::string* target) const {
PutVarint64(target, number);
PutVarint64(target, records_num);
PutVarint64(target, invalid_num);
PutVarint64(target, table_size);
}
Status VTableMeta::Decode(Slice* input) {
if (!GetVarint64(input, &number) || !GetVarint64(input, &records_num) ||
!GetVarint64(input, &invalid_num) || !GetVarint64(input, &table_size)) {
return Status::Corruption("Error Decode VTable meta");
}
return Status::OK();
}
void VTableManager::AddVTable(const VTableMeta& vtable_meta) {
vtables_[vtable_meta.number] = vtable_meta;
}
void VTableManager::RemoveVTable(uint64_t file_num) {
const auto it = vtables_.find(file_num);
if (it == vtables_.end()) { return; }
vtables_.erase(it);
}
Status VTableManager::AddInvalid(uint64_t file_num) {
const auto it = vtables_.find(file_num);
if (it == vtables_.end()) {
return Status::Corruption("Invalid VTable number");
}
vtables_[file_num].invalid_num += 1;
if (vtables_[file_num].invalid_num >= vtables_[file_num].records_num) {
invalid_.emplace_back(file_num);
}
MaybeScheduleGarbageCollect();
return Status::OK();
}
Status VTableManager::SaveVTableMeta() const {
auto fname = VTableManagerFileName(dbname_);
WritableFile* file;
Status s = env_->NewWritableFile(fname, &file);
if (!s.ok()) {
return Status::Corruption("Failed to open vTable manager file");
}
const auto vtable_num = vtables_.size();
std::string target;
PutVarint64(&target, vtable_num);
for (auto & vtable : vtables_) {
vtable.second.Encode(&target);
}
s = file->Append(target);
if (!s.ok()) {
return Status::Corruption("Failed to append vTable manager file");
}
s = file->Flush();
if (s.ok()) {
s = file->Sync();
}
if (s.ok()) {
s = file->Close();
}
delete file;
file = nullptr;
if (!s.ok()) {
return Status::Corruption("Failed to write vTable meta file");
}
return Status::OK();
}
Status VTableManager::LoadVTableMeta() {
auto fname = VTableManagerFileName(dbname_);
if (!env_->FileExists(fname)) {
return Status::OK();
}
SequentialFile* file;
Status s = env_->NewSequentialFile(fname, &file);
if (!s.ok()) {
return Status::Corruption("Failed to open vTable manager file");
}
uint64_t file_size;
s = env_->GetFileSize(fname, &file_size);
if (!s.ok()) {
return Status::Corruption("Failed to get vTable manager file size");
}
auto buf = new char[file_size];
Slice input;
s = file->Read(file_size, &input, buf);
if (!s.ok()) {
return Status::Corruption("Failed to read vTable manager file");
}
uint64_t vtable_num;
if(!GetVarint64(&input, &vtable_num)) {
return Status::Corruption("Failed to get vTable num");
}
for (int i = 0; i < vtable_num; i++) {
VTableMeta vtable_meta;
s = vtable_meta.Decode(&input);
if (s.ok()) {
if (vtable_meta.number == 0) {
continue;
}
AddVTable(vtable_meta);
if (vtable_meta.invalid_num >= vtable_meta.records_num) {
invalid_.emplace_back(vtable_meta.number);
}
} else {
return s;
}
}
return s;
}
void VTableManager::MaybeScheduleGarbageCollect() {
size_t size = 0;
auto delete_list = std::vector<uint64_t>();
if (!invalid_.empty()) {
auto invalid = std::set<uint64_t>(invalid_.begin(), invalid_.end());
invalid_ = std::vector<uint64_t>(invalid.begin(), invalid.end());
for (auto & file_num : invalid) {
if (vtables_.find(file_num) != vtables_.end() && vtables_[file_num].ref <= 0) {
size += vtables_[file_num].table_size;
delete_list.emplace_back(file_num);
}
}
if (size >= gc_threshold_) {
for (auto & file_num : delete_list) {
auto it = std::remove(invalid_.begin(), invalid_.end(), file_num);
RemoveVTable(file_num);
}
auto* gc_info = new GCInfo;
gc_info->dbname = dbname_;
gc_info->file_list = delete_list;
gc_info->env = env_;
env_->StartThread(&VTableManager::BackgroudGC, gc_info);
// for (auto & file_num : gc_info->file_list) {
// RemoveVTable(file_num);
// auto it = std::remove(invalid_.begin(), invalid_.end(), file_num);
// }
}
}
}
void VTableManager::BackgroudGC(void* gc_info) {
auto info = reinterpret_cast<GCInfo*>(gc_info);
std::cout << "gc starts..." << std::endl;
auto start_time = std::chrono::steady_clock::now();
for (auto & file_num : info->file_list) {
// if (file_num <= 0) {continue;}
auto fname = VTableFileName(info->dbname, file_num);
info->env->RemoveFile(fname);
}
auto end_time = std::chrono::steady_clock::now();
auto duration = std::chrono::duration_cast<std::chrono::microseconds>(end_time - start_time).count();
std::cout << "gc lasts: " << duration << " micros" << std::endl;
}
void VTableManager::RefVTable(uint64_t file_num) {
vtables_[file_num].ref += 1;
}
void VTableManager::UnrefVTable(uint64_t file_num) {
vtables_[file_num].ref -= 1;
}
} // namespace leveldb

+ 75
- 0
table/vtable_manager.h View File

@ -0,0 +1,75 @@
#ifndef VTABLE_MANAGER_H
#define VTABLE_MANAGER_H
#include <map>
#include <set>
#include "leveldb/env.h"
#include "leveldb/slice.h"
#include "leveldb/status.h"
namespace leveldb {
struct VTableMeta {
uint64_t number;
uint64_t records_num;
uint64_t invalid_num;
uint64_t table_size;
uint64_t ref = 0;
void Encode(std::string* target) const;
Status Decode(Slice* input);
VTableMeta() : number(0), records_num(0), invalid_num(0), table_size(0) {}
};
class VTableManager {
public:
explicit VTableManager(const std::string& dbname, Env* env, size_t gc_threshold) :
dbname_(dbname),
env_(env),
gc_threshold_(gc_threshold) {}
~VTableManager() = default;
// sign a vtable to meta
void AddVTable(const VTableMeta& vtable_meta);
// remove a vtable from meta
void RemoveVTable(uint64_t file_num);
// add an invalid num to a vtable
Status AddInvalid(uint64_t file_num);
// save meta info to disk
Status SaveVTableMeta() const;
// recover meta info from disk
Status LoadVTableMeta();
// reference a vtable
void RefVTable(uint64_t file_num);
// unref a vtable
void UnrefVTable(uint64_t file_num);
// maybe schedule backgroud gc
void MaybeScheduleGarbageCollect();
// do backgroud gc work
static void BackgroudGC(void* gc_info);
private:
std::string dbname_;
Env* env_;
std::map<uint64_t, VTableMeta> vtables_;
std::vector<uint64_t> invalid_;
size_t gc_threshold_;
};
} // namespace leveldb
#endif //VTABLE_MANAGER_H

+ 18
- 3
table/vtable_reader.cc View File

@ -2,19 +2,28 @@
#include "leveldb/env.h" #include "leveldb/env.h"
#include &lt;table/vtable_reader.h>;
#include &#34;table/vtable_reader.h";
namespace leveldb { namespace leveldb {
Status VTableReader::Open(const Options& options, std::string fname) { Status VTableReader::Open(const Options& options, std::string fname) {
options_ = options; options_ = options;
return options_.env->NewRandomAccessFile(fname, &file_);
Status s = options_.env->NewRandomAccessFile(fname, &file_);
if (manager_ != nullptr) {
manager_->RefVTable(fnum_);
}
return s;
} }
Status VTableReader::Get(const VTableHandle& handle, Status VTableReader::Get(const VTableHandle& handle,
VTableRecord* record) const { VTableRecord* record) const {
auto buf = new char[handle.size]; auto buf = new char[handle.size];
Slice input; Slice input;
Status s = file_->Read(handle.offset, handle.size, &input, buf);
Status s;
if (file_ != nullptr) {
s = file_->Read(handle.offset, handle.size, &input, buf);
} else {
s = Status::TimeOutRead("Get for another time");
}
if (!s.ok()) { if (!s.ok()) {
return s; return s;
@ -35,5 +44,11 @@ namespace leveldb {
return s; return s;
} }
void VTableReader::Close() {
file_ = nullptr;
if (manager_ != nullptr) {
manager_->UnrefVTable(fnum_);
}
}
} // namespace leveldb } // namespace leveldb

+ 11
- 0
table/vtable_reader.h View File

@ -11,18 +11,29 @@
#include "util/coding.h" #include "util/coding.h"
#include "vtable_format.h" #include "vtable_format.h"
#include "vtable_manager.h"
namespace leveldb { namespace leveldb {
class VTableReader { class VTableReader {
public: public:
VTableReader() = default;
VTableReader(uint64_t fnum, VTableManager *manager) :
fnum_(fnum),
manager_(manager) {};
Status Open(const Options& options, std::string fname); Status Open(const Options& options, std::string fname);
Status Get(const VTableHandle& handle, Status Get(const VTableHandle& handle,
VTableRecord* record) const ; VTableRecord* record) const ;
void Close();
private: private:
Options options_; Options options_;
uint64_t fnum_;
RandomAccessFile* file_{nullptr}; RandomAccessFile* file_{nullptr};
VTableManager* manager_{nullptr};
}; };
} // namespace leveldb } // namespace leveldb

+ 2
- 2
test/test_basicio.cc View File

@ -3,7 +3,7 @@
#include "leveldb/db.h" #include "leveldb/db.h"
using namespace leveldb; using namespace leveldb;
constexpr int value_size = 2000;
constexpr int value_size = 2048;
constexpr int data_size = 128 << 20; constexpr int data_size = 128 << 20;
std::map<std::string, std::string> data; std::map<std::string, std::string> data;
@ -72,4 +72,4 @@ TEST(TestBasicIO, RangeQuery) {
int main(int argc, char **argv) { int main(int argc, char **argv) {
testing::InitGoogleTest(&argc, argv); testing::InitGoogleTest(&argc, argv);
return RUN_ALL_TESTS(); return RUN_ALL_TESTS();
}
}

+ 290
- 0
test/test_bench.cc View File

@ -0,0 +1,290 @@
#include <iostream>
#include <gtest/gtest.h>
#include <chrono>
#include <vector>
#include <random>
#include "leveldb/env.h"
#include "leveldb/db.h"
using namespace leveldb;
// Number of key/values to operate in database
constexpr int num_ = 100000;
// Size of each value
constexpr int value_size_ = 500;
// Number of read operations
constexpr int reads_ = 100000;
// Number of findkeysbyfield operations
constexpr int search_ = 10;
int64_t bytes_ = 0;
Status OpenDB(std::string dbName, DB **db) {
Options options;
options.create_if_missing = true;
return DB::Open(options, dbName, db);
}
// DB::Put()
void InsertData(DB *db, std::vector<int64_t> &lats) {
WriteOptions writeOptions;
bytes_ = 0;
int64_t bytes = 0;
srand(0);
// std::mt19937 value_seed(100);
// std::uniform_int_distribution<int> value_range(500, 2048);
int64_t latency = 0;
auto end_time = std::chrono::steady_clock::now();
auto last_time = end_time;
for (int i = 0; i < num_; i++) {
int key_ = rand() % num_+1;
int value_ = std::rand() % (num_ + 1);
// int value_size = value_range(value_seed);
std::string value(value_size_, 'a');
std::string key = std::to_string(key_);
FieldArray field_array = {
{"1", value},
};
auto fields = Fields(field_array);
db->Put(writeOptions, key, fields);
bytes += fields.size();
end_time = std::chrono::steady_clock::now();
latency = std::chrono::duration_cast<std::chrono::nanoseconds>(end_time - last_time).count();
last_time = end_time;
lats.emplace_back(latency);
}
bytes_ += bytes;
}
// DB::Get() PointQuery Random
void GetData(DB *db, std::vector<int64_t> &lats) {
ReadOptions readOptions;
bytes_ = 0;
int64_t bytes = 0;
srand(0);
int64_t latency = 0;
auto end_time = std::chrono::steady_clock::now();
auto last_time = end_time;
for (int i = 0; i < reads_; i++) {
int key_ = rand() % num_+1;
std::string key = std::to_string(key_);
Fields ret;
db->Get(readOptions, key, &ret);
bytes += ret.size();
end_time = std::chrono::steady_clock::now();
latency = std::chrono::duration_cast<std::chrono::nanoseconds>(end_time - last_time).count();
last_time = end_time;
lats.emplace_back(latency);
}
bytes_ += bytes;
}
// DB::Iterator()->Seek() PointQuery
void PointQuery(DB *db, std::vector<int64_t> &lats) {
ReadOptions options;
srand(0);
bytes_ = 0;
int64_t bytes = 0;
Iterator* iter = db->NewIterator(options);
int key_ = 0;
int64_t latency = 0;
auto end_time = std::chrono::steady_clock::now();
auto last_time = end_time;
for (int i = 0; i < reads_; i++) {
key_ = (key_ + rand()) % num_+1;
std::string key = std::to_string(key_);
iter->Seek(key);
bytes += iter->fields().size();
end_time = std::chrono::steady_clock::now();
latency = std::chrono::duration_cast<std::chrono::nanoseconds>(end_time - last_time).count();
last_time = end_time;
lats.emplace_back(latency);
}
bytes_+=bytes;
delete iter;
}
// DB::Iterator()->SeekToFirst() RangeQuery
void ReadOrdered(DB *db, std::vector<int64_t> &lats) {
Iterator* iter = db->NewIterator(ReadOptions());
int i = 0;
bytes_ = 0;
int64_t bytes = 0;
int64_t latency = 0;
auto end_time = std::chrono::steady_clock::now();
auto last_time = end_time;
for (iter->SeekToFirst(); i < reads_ && iter->Valid(); iter->Next()) {
++i;
bytes+=iter->fields().size();
end_time = std::chrono::steady_clock::now();
latency = std::chrono::duration_cast<std::chrono::nanoseconds>(end_time - last_time).count();
last_time = end_time;
lats.emplace_back(latency);
}
bytes_+=bytes;
delete iter;
}
// DB::FindKeysByField()
void SearchField(DB *db, std::vector<int64_t> &lats) {
int64_t latency = 0;
auto end_time = std::chrono::steady_clock::now();
auto last_time = end_time;
srand(0);
for (int i = 0; i < search_; i++) {
// Iterator *iter = db->NewIterator(ReadOptions());
int value_ = std::rand() % (num_ + 1);
Field field_to_search = {"1", std::to_string(value_)};
const std::vector<std::string> key_ret = db->FindKeysByField(field_to_search);
end_time = std::chrono::steady_clock::now();
latency = std::chrono::duration_cast<std::chrono::nanoseconds>(end_time - last_time).count();
last_time = end_time;
lats.emplace_back(latency);
}
}
// Insert many k/vs in order to start background GC
void InsertMany(DB *db) {
std::vector<int64_t> lats;
for (int i = 0; i < 2; i++) {
InsertData(db, lats);
GetData(db, lats);
db->CompactRange(nullptr, nullptr);
std::cout << "put and get " << i << " of Many" << std::endl;
}
}
double CalculatePercentile(const std::vector<int64_t>& latencies, double percentile) {
if (latencies.empty()) return 0.0;
std::vector<int64_t> sorted_latencies = latencies;
std::sort(sorted_latencies.begin(), sorted_latencies.end());
size_t index = static_cast<size_t>(percentile * sorted_latencies.size());
if (index >= sorted_latencies.size()) index = sorted_latencies.size() - 1;
return sorted_latencies[index];
}
TEST(TestBench, Throughput) {
DB *db;
if(OpenDB("testdb", &db).ok() == false) {
std::cerr << "open db failed" << std::endl;
abort();
}
// InsertMany(db);
std::vector<int64_t> lats;
// Put()
auto start_time = std::chrono::steady_clock::now();
InsertData(db, lats);
auto end_time = std::chrono::steady_clock::now();
auto duration = std::chrono::duration_cast<std::chrono::microseconds>(end_time - start_time).count();
// std::cout << "Throughput of Put(): " << std::fixed << num_ * 1e6 / duration << " ops/s" << std::endl;
std::cout << "Throughput of Put(): " << std::fixed << std::setprecision(2) << std::endl << (bytes_ / 1048576.0) / (duration * 1e-6) << " MB/s" << std::endl << std::endl;
// Get()
start_time = std::chrono::steady_clock::now();
GetData(db, lats);
end_time = std::chrono::steady_clock::now();
duration = std::chrono::duration_cast<std::chrono::microseconds>(end_time - start_time).count();
// std::cout << "Throughput of Get(): " << std::fixed << reads_ * 1e6 / duration << " ops/s" << std::endl;
std::cout << "Throughput of Get(): " << std::fixed << std::setprecision(2) << std::endl << (bytes_ / 1048576.0) / (duration * 1e-6) << " MB/s" << std::endl << std::endl;
// Iterator()
start_time = std::chrono::steady_clock::now();
ReadOrdered(db, lats);
end_time = std::chrono::steady_clock::now();
duration = std::chrono::duration_cast<std::chrono::microseconds>(end_time - start_time).count();
// std::cout << "Throughput of Iterator(): " << std::fixed << reads_ * 1e6 / duration << " ops/s" << std::endl;
std::cout << "Throughput of Iterator(): " << std::fixed << std::setprecision(2) << std::endl << (bytes_ / 1048576.0) / (duration * 1e-6) << " MB/s" << std::endl << std::endl;
// FindKeysbyField()
start_time = std::chrono::steady_clock::now();
SearchField(db, lats);
end_time = std::chrono::steady_clock::now();
duration = std::chrono::duration_cast<std::chrono::microseconds>(end_time - start_time).count();
std::cout << "Throughput of FindKeysbyField(): " << std::fixed << std::setprecision(2) << std::endl << search_ * 1e6 / duration << " ops/s" << std::endl << std::endl;
delete db;
}
TEST(TestBench, Latency) {
DB *db;
if(OpenDB("testdb", &db).ok() == false) {
std::cerr << "open db failed" << std::endl;
abort();
}
std::vector<int64_t> put_lats;
std::vector<int64_t> get_lats;
std::vector<int64_t> iter_lats;
std::vector<int64_t> search_lats;
auto calc_lat = [](const std::vector<int64_t>& latencies) {
double avg = 0.0;
for (auto latency : latencies) {
avg += latency;
}
avg /= latencies.size();
double p75 = CalculatePercentile(latencies, 0.75);
double p99 = CalculatePercentile(latencies, 0.99);
return std::make_tuple(avg, p75, p99);
};
InsertData(db, put_lats);
std::tuple<double, double, double> put_latency = calc_lat(put_lats);
double put_avg = std::get<0>(put_latency);
double put_p75 = std::get<1>(put_latency);
double put_p99 = std::get<2>(put_latency);
std::cout << "Put Latency (avg, P75, P99): " << std::fixed << std::endl << std::setprecision(2) << put_avg * 1e-3 << " micros/op, " << put_p75 * 1e-3 << " micros/op, " << put_p99 * 1e-3 << " micros/op" << std::endl << std::endl;
GetData(db, get_lats);
std::tuple<double, double, double> get_latency = calc_lat(get_lats);
double get_avg = std::get<0>(get_latency);
double get_p75 = std::get<1>(get_latency);
double get_p99 = std::get<2>(get_latency);
std::cout << "Get Latency (avg, P75, P99): " << std::fixed << std::endl << std::setprecision(2) << get_avg * 1e-3 << " micros/op, " << get_p75 * 1e-3 << " micros/op, " << get_p99 * 1e-3 << " micros/op" << std::endl << std::endl;
ReadOrdered(db, iter_lats);
std::tuple<double, double, double> iter_latency = calc_lat(iter_lats);
double iter_avg = std::get<0>(iter_latency);
double iter_p75 = std::get<1>(iter_latency);
double iter_p99 = std::get<2>(iter_latency);
std::cout << "Iterator Latency (avg, P75, P99): " << std::fixed << std::endl << std::setprecision(2) << iter_avg * 1e-3 << " micros/op, " << iter_p75 * 1e-3 << " micros/op, " << iter_p99 * 1e-3 << " micros/op" << std::endl << std::endl;
SearchField(db, search_lats);
std::tuple<double, double, double> search_latency = calc_lat(search_lats);
double search_avg = std::get<0>(search_latency);
double search_p75 = std::get<1>(search_latency);
double search_p99 = std::get<2>(search_latency);
std::cout << "FindKeysByField Latency (avg, P75, P99): " << std::fixed << std::endl << std::setprecision(2) << search_avg * 1e-3 << " micros/op, " << search_p75 * 1e-3 << " micros/op, " << search_p99 * 1e-3 << " micros/op" << std::endl << std::endl;
delete db;
}
TEST(TestBench, Write) {
DB *db;
if(OpenDB("testdb", &db).ok() == false) {
std::cerr << "open db failed" << std::endl;
abort();
}
std::vector<int64_t> lats;
InsertData(db, lats);
std::cout << "Write Size: " << bytes_ << " bytes altogether";
delete db;
}
int main(int argc, char **argv) {
testing::InitGoogleTest(&argc, argv);
return RUN_ALL_TESTS();
}

+ 276
- 0
test/test_bench_gc.cc View File

@ -0,0 +1,276 @@
#include <iostream>
#include <gtest/gtest.h>
#include <chrono>
#include <vector>
#include <random>
#include "leveldb/env.h"
#include "leveldb/db.h"
using namespace leveldb;
// Number of key/values to operate in database
constexpr int num_ = 100000;
// Size of each value
constexpr int value_size_ = 500;
// Number of read operations
constexpr int reads_ = 100000;
// Number of findkeysbyfield operations
constexpr int search_ = 20;
int64_t bytes_ = 0;
Status OpenDB(std::string dbName, DB **db) {
Options options;
options.create_if_missing = true;
return DB::Open(options, dbName, db);
}
// DB::Put()
void InsertData(DB *db, std::vector<int64_t> &lats) {
WriteOptions writeOptions;
bytes_ = 0;
int64_t bytes = 0;
srand(0);
// std::mt19937 value_seed(100);
// std::uniform_int_distribution<int> value_range(500, 2048);
int64_t latency = 0;
auto end_time = std::chrono::steady_clock::now();
auto last_time = end_time;
for (int i = 0; i < num_; i++) {
int key_ = rand() % num_+1;
int value_ = std::rand() % (num_ + 1);
// int value_size = value_range(value_seed);
std::string value(value_size_, 'a');
std::string key = std::to_string(key_);
FieldArray field_array = {
{"1", value},
};
auto fields = Fields(field_array);
db->Put(writeOptions, key, fields);
bytes += fields.size();
end_time = std::chrono::steady_clock::now();
latency = std::chrono::duration_cast<std::chrono::nanoseconds>(end_time - last_time).count();
last_time = end_time;
lats.emplace_back(latency);
}
bytes_ += bytes;
}
// DB::Get() PointQuery Random
void GetData(DB *db, std::vector<int64_t> &lats) {
ReadOptions readOptions;
bytes_ = 0;
int64_t bytes = 0;
srand(0);
int64_t latency = 0;
auto end_time = std::chrono::steady_clock::now();
auto last_time = end_time;
for (int i = 0; i < reads_; i++) {
int key_ = rand() % num_+1;
std::string key = std::to_string(key_);
Fields ret;
db->Get(readOptions, key, &ret);
bytes += ret.size();
end_time = std::chrono::steady_clock::now();
latency = std::chrono::duration_cast<std::chrono::nanoseconds>(end_time - last_time).count();
last_time = end_time;
lats.emplace_back(latency);
}
bytes_ += bytes;
}
// DB::Iterator()->Seek() PointQuery
void PointQuery(DB *db, std::vector<int64_t> &lats) {
ReadOptions options;
srand(0);
bytes_ = 0;
int64_t bytes = 0;
Iterator* iter = db->NewIterator(options);
int key_ = 0;
int64_t latency = 0;
auto end_time = std::chrono::steady_clock::now();
auto last_time = end_time;
for (int i = 0; i < reads_; i++) {
key_ = (key_ + rand()) % num_+1;
std::string key = std::to_string(key_);
iter->Seek(key);
bytes += iter->fields().size();
end_time = std::chrono::steady_clock::now();
latency = std::chrono::duration_cast<std::chrono::nanoseconds>(end_time - last_time).count();
last_time = end_time;
lats.emplace_back(latency);
}
bytes_+=bytes;
delete iter;
}
// DB::Iterator()->SeekToFirst() RangeQuery
void ReadOrdered(DB *db, std::vector<int64_t> &lats) {
Iterator* iter = db->NewIterator(ReadOptions());
int i = 0;
bytes_ = 0;
int64_t bytes = 0;
int64_t latency = 0;
auto end_time = std::chrono::steady_clock::now();
auto last_time = end_time;
for (iter->SeekToFirst(); i < reads_ && iter->Valid(); iter->Next()) {
++i;
bytes+=iter->fields().size();
end_time = std::chrono::steady_clock::now();
latency = std::chrono::duration_cast<std::chrono::nanoseconds>(end_time - last_time).count();
last_time = end_time;
lats.emplace_back(latency);
}
bytes_+=bytes;
delete iter;
}
// DB::FindKeysByField()
void SearchField(DB *db, std::vector<int64_t> &lats) {
int64_t latency = 0;
auto end_time = std::chrono::steady_clock::now();
auto last_time = end_time;
srand(0);
for (int i = 0; i < search_; i++) {
// Iterator *iter = db->NewIterator(ReadOptions());
int value_ = std::rand() % (num_ + 1);
Field field_to_search = {"1", std::to_string(value_)};
const std::vector<std::string> key_ret = db->FindKeysByField(field_to_search);
end_time = std::chrono::steady_clock::now();
latency = std::chrono::duration_cast<std::chrono::nanoseconds>(end_time - last_time).count();
last_time = end_time;
lats.emplace_back(latency);
}
}
// Insert many k/vs in order to start background GC
void InsertMany(DB *db) {
std::vector<int64_t> lats;
for (int i = 0; i < 2; i++) {
InsertData(db, lats);
GetData(db, lats);
db->CompactRange(nullptr, nullptr);
std::cout << "put and get " << i << " of Many" << std::endl;
}
}
double CalculatePercentile(const std::vector<int64_t>& latencies, double percentile) {
if (latencies.empty()) return 0.0;
std::vector<int64_t> sorted_latencies = latencies;
std::sort(sorted_latencies.begin(), sorted_latencies.end());
size_t index = static_cast<size_t>(percentile * sorted_latencies.size());
if (index >= sorted_latencies.size()) index = sorted_latencies.size() - 1;
return sorted_latencies[index];
}
TEST(TestBench, WithGC) {
DB *db;
if(OpenDB("testdb", &db).ok() == false) {
std::cerr << "open db failed" << std::endl;
abort();
}
std::vector<int64_t> put_lats;
std::vector<int64_t> get_lats;
std::vector<int64_t> iter_lats;
std::vector<int64_t> search_lats;
auto calc_lat = [](const std::vector<int64_t>& latencies) {
double avg = 0.0;
for (auto latency : latencies) {
avg += latency;
}
avg /= latencies.size();
double p75 = CalculatePercentile(latencies, 0.75);
double p99 = CalculatePercentile(latencies, 0.99);
return std::make_tuple(avg, p75, p99);
};
InsertMany(db);
// Put()
auto start_time = std::chrono::steady_clock::now();
InsertData(db, put_lats);
auto end_time = std::chrono::steady_clock::now();
auto duration = std::chrono::duration_cast<std::chrono::microseconds>(end_time - start_time).count();
// std::cout << "Throughput of Put(): " << std::fixed << num_ * 1e6 / duration << " ops/s" << std::endl;
std::cout << std::endl << "Write size: " << bytes_ << " bytes" << std::endl << std::endl;
std::cout << "Throughput of Put(): " << std::fixed << std::setprecision(2) << (bytes_ / 1048576.0) / (duration * 1e-6) << std::endl << std::endl; // << " MB/s" << std::endl << std::endl;
std::tuple<double, double, double> put_latency = calc_lat(put_lats);
double put_avg = std::get<0>(put_latency);
double put_p75 = std::get<1>(put_latency);
double put_p99 = std::get<2>(put_latency);
std::cout << "Put Latency (avg, P75, P99): " << std::endl << std::setprecision(2) << put_avg * 1e-3 // << " micros/op, "
<< std::endl << put_p75 * 1e-3 // << " micros/op, "
<< std::endl << put_p99 * 1e-3 // << " micros/op"
<< std::endl << std::endl;
// Get()
start_time = std::chrono::steady_clock::now();
GetData(db, get_lats);
end_time = std::chrono::steady_clock::now();
duration = std::chrono::duration_cast<std::chrono::microseconds>(end_time - start_time).count();
// std::cout << "Throughput of Get(): " << std::fixed << reads_ * 1e6 / duration << " ops/s" << std::endl;
std::cout << "Throughput of Get(): " << std::fixed << std::setprecision(2) << (bytes_ / 1048576.0) / (duration * 1e-6) << std::endl << std::endl; // << " MB/s" << std::endl << std::endl;
std::tuple<double, double, double> get_latency = calc_lat(get_lats);
double get_avg = std::get<0>(get_latency);
double get_p75 = std::get<1>(get_latency);
double get_p99 = std::get<2>(get_latency);
std::cout << "Put Latency (avg, P75, P99): " << std::endl << std::setprecision(2) << get_avg * 1e-3 // << " micros/op, "
<< std::endl << get_p75 * 1e-3 // << " micros/op, "
<< std::endl << get_p99 * 1e-3 // << " micros/op"
<< std::endl << std::endl;
// Iterator()
start_time = std::chrono::steady_clock::now();
ReadOrdered(db, iter_lats);
end_time = std::chrono::steady_clock::now();
duration = std::chrono::duration_cast<std::chrono::microseconds>(end_time - start_time).count();
// std::cout << "Throughput of Iterator(): " << std::fixed << reads_ * 1e6 / duration << " ops/s" << std::endl;
std::cout << "Throughput of Iterator(): " << std::fixed << std::setprecision(2) << (bytes_ / 1048576.0) / (duration * 1e-6) << std::endl << std::endl; // << " MB/s" << std::endl << std::endl;
std::tuple<double, double, double> iter_latency = calc_lat(iter_lats);
double iter_avg = std::get<0>(iter_latency);
double iter_p75 = std::get<1>(iter_latency);
double iter_p99 = std::get<2>(iter_latency);
std::cout << "Put Latency (avg, P75, P99): " << std::endl << std::setprecision(2) << iter_avg * 1e-3 // << " micros/op, "
<< std::endl << iter_p75 * 1e-3 // << " micros/op, "
<< std::endl << iter_p99 * 1e-3 // << " micros/op"
<< std::endl << std::endl;
// FindKeysByField()
start_time = std::chrono::steady_clock::now();
SearchField(db, search_lats);
end_time = std::chrono::steady_clock::now();
duration = std::chrono::duration_cast<std::chrono::microseconds>(end_time - start_time).count();
std::cout << "Throughput of FindKeysbyField(): " << std::setprecision(2) << search_ * 1e6 / duration << std::endl << std::endl; // << " ops/s" << std::endl << std::endl;
std::tuple<double, double, double> search_latency = calc_lat(search_lats);
double search_avg = std::get<0>(search_latency);
double search_p75 = std::get<1>(search_latency);
double search_p99 = std::get<2>(search_latency);
std::cout << "Put Latency (avg, P75, P99): " << std::endl << std::setprecision(2) << search_avg * 1e-3 // << " micros/op, "
<< std::endl << search_p75 * 1e-3 // << " micros/op, "
<< std::endl << search_p99 * 1e-3 // << " micros/op"
<< std::endl << std::endl;
delete db;
}
int main(int argc, char **argv) {
testing::InitGoogleTest(&argc, argv);
return RUN_ALL_TESTS();
}

+ 2
- 2
test/test_fields.cc View File

@ -113,11 +113,11 @@ TEST(TestFields, SearchKey) {
for (const auto& key : keys_wo_field) { for (const auto& key : keys_wo_field) {
db->Put(WriteOptions(), key, fields_wo_field); db->Put(WriteOptions(), key, fields_wo_field);
} }
Iterator *iter = db->NewIterator(ReadOptions());
const std::vector<std::string> key_ret = db->FindKeysByField(field_test); const std::vector<std::string> key_ret = db->FindKeysByField(field_test);
ASSERT_EQ(CompareVector<std::string>(key_ret, keys_have_field), true); ASSERT_EQ(CompareVector<std::string>(key_ret, keys_have_field), true);
delete iter;
delete db; delete db;
} }

Loading…
Cancel
Save