ZCL_ABAPGIT_GIT_PACK=>DECODE_TREE performance (#1218)

* refactor tests

* this is around twice as fast

+minor cleanups in class

* add test for off by 1
This commit is contained in:
Lars Hvam 2018-02-24 10:03:05 +01:00 committed by GitHub
parent 64bc80ebe4
commit 6578b39959
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 117 additions and 71 deletions

View File

@ -23,8 +23,8 @@ CLASS zcl_abapgit_git_pack DEFINITION
END OF ty_commit .
TYPES:
BEGIN OF ty_adler32,
sha1 TYPE zif_abapgit_definitions=>ty_sha1,
type TYPE zif_abapgit_definitions=>ty_type,
sha1 TYPE zif_abapgit_definitions=>ty_sha1,
type TYPE zif_abapgit_definitions=>ty_type,
END OF ty_adler32 .
CLASS-METHODS decode
@ -275,10 +275,6 @@ CLASS ZCL_ABAPGIT_GIT_PACK IMPLEMENTATION.
SPLIT lv_string AT zif_abapgit_definitions=>gc_newline INTO TABLE lt_string.
LOOP AT lt_string ASSIGNING <lv_string>.
* IF NOT rs_commit-committer IS INITIAL.
* CONCATENATE rs_commit-body <lv_string> INTO rs_commit-body
* SEPARATED BY zif_abapgit_definitions=>gc_newline.
* ELSE.
lv_length = strlen( <lv_string> ) + 1.
lv_string = lv_string+lv_length.
@ -300,17 +296,10 @@ CLASS ZCL_ABAPGIT_GIT_PACK IMPLEMENTATION.
WHEN OTHERS.
ASSERT 0 = 1.
ENDCASE.
* ENDIF.
ENDLOOP.
rs_commit-body = lv_string+1.
* strip first newline
* IF strlen( rs_commit-body ) >= 2.
* rs_commit-body = rs_commit-body+2.
* ENDIF.
IF rs_commit-author IS INITIAL
OR rs_commit-committer IS INITIAL
OR rs_commit-tree IS INITIAL.
@ -359,42 +348,38 @@ CLASS ZCL_ABAPGIT_GIT_PACK IMPLEMENTATION.
lv_len TYPE i,
lv_offset TYPE i,
lv_cursor TYPE i,
ls_node TYPE ty_node,
lv_start TYPE i.
lv_match TYPE i,
ls_node TYPE ty_node.
DO.
IF lv_cursor >= xstrlen( iv_data ).
EXIT. " current loop
FIND FIRST OCCURRENCE OF lc_null IN SECTION OFFSET lv_cursor OF iv_data
IN BYTE MODE MATCH OFFSET lv_match.
IF sy-subrc <> 0.
EXIT.
ENDIF.
IF iv_data+lv_cursor(1) = lc_null.
lv_len = lv_cursor - lv_start.
lv_xstring = iv_data+lv_start(lv_len).
lv_len = lv_match - lv_cursor.
lv_xstring = iv_data+lv_cursor(lv_len).
lv_string = zcl_abapgit_convert=>xstring_to_string_utf8( lv_xstring ).
SPLIT lv_string AT space INTO lv_chmod lv_name.
lv_string = zcl_abapgit_convert=>xstring_to_string_utf8( lv_xstring ).
SPLIT lv_string AT space INTO lv_chmod lv_name.
lv_offset = lv_cursor + 1.
CLEAR ls_node.
ls_node-chmod = lv_chmod.
IF ls_node-chmod <> zif_abapgit_definitions=>gc_chmod-dir
AND ls_node-chmod <> zif_abapgit_definitions=>gc_chmod-file
AND ls_node-chmod <> zif_abapgit_definitions=>gc_chmod-executable.
zcx_abapgit_exception=>raise( 'Unknown chmod' ).
ENDIF.
ls_node-name = lv_name.
ls_node-sha1 = iv_data+lv_offset(lc_sha_length).
TRANSLATE ls_node-sha1 TO LOWER CASE.
APPEND ls_node TO rt_nodes.
lv_start = lv_cursor + 1 + lc_sha_length.
lv_cursor = lv_start.
ELSE.
lv_cursor = lv_cursor + 1.
CLEAR ls_node.
ls_node-chmod = lv_chmod.
IF ls_node-chmod <> zif_abapgit_definitions=>gc_chmod-dir
AND ls_node-chmod <> zif_abapgit_definitions=>gc_chmod-file
AND ls_node-chmod <> zif_abapgit_definitions=>gc_chmod-executable.
zcx_abapgit_exception=>raise( 'Unknown chmod' ).
ENDIF.
lv_offset = lv_match + 1.
ls_node-name = lv_name.
ls_node-sha1 = iv_data+lv_offset(lc_sha_length).
TRANSLATE ls_node-sha1 TO LOWER CASE.
APPEND ls_node TO rt_nodes.
lv_cursor = lv_match + 1 + lc_sha_length.
ENDDO.
ENDMETHOD. "decode_tree
@ -760,8 +745,7 @@ CLASS ZCL_ABAPGIT_GIT_PACK IMPLEMENTATION.
* see http://stefan.saasen.me/articles/git-clone-in-haskell-from-the-bottom-up/#pack_file_objects
DATA: lv_result TYPE i,
lv_type TYPE i,
DATA: lv_type TYPE i,
lv_length TYPE i,
lv_hex TYPE x LENGTH 1.

View File

@ -1,7 +1,94 @@
CLASS ltcl_tree DEFINITION FOR TESTING DURATION SHORT RISK LEVEL HARMLESS FINAL.
PRIVATE SECTION.
METHODS:
test01 FOR TESTING RAISING zcx_abapgit_exception,
test02 FOR TESTING RAISING zcx_abapgit_exception,
test03 FOR TESTING RAISING zcx_abapgit_exception.
ENDCLASS.
CLASS ltcl_tree IMPLEMENTATION.
METHOD test01.
DATA: lt_nodes TYPE zcl_abapgit_git_pack=>ty_nodes_tt,
ls_node LIKE LINE OF lt_nodes,
lv_data TYPE xstring,
lt_result TYPE zcl_abapgit_git_pack=>ty_nodes_tt.
CLEAR ls_node.
ls_node-chmod = zif_abapgit_definitions=>gc_chmod-file.
ls_node-name = 'foobar.txt'.
ls_node-sha1 = '5f46cb3c4b7f0b3600b64f744cde614a283a88dc'.
APPEND ls_node TO lt_nodes.
lv_data = zcl_abapgit_git_pack=>encode_tree( lt_nodes ).
lt_result = zcl_abapgit_git_pack=>decode_tree( lv_data ).
cl_abap_unit_assert=>assert_equals(
exp = lt_nodes
act = lt_result ).
ENDMETHOD.
METHOD test02.
DATA: lt_nodes TYPE zcl_abapgit_git_pack=>ty_nodes_tt,
ls_node LIKE LINE OF lt_nodes,
lv_data TYPE xstring,
lt_result TYPE zcl_abapgit_git_pack=>ty_nodes_tt.
CLEAR ls_node.
ls_node-chmod = zif_abapgit_definitions=>gc_chmod-file.
ls_node-name = 'foobar.txt'.
ls_node-sha1 = '5f46cb3c4b7f0b3600b64f744cde614a283a88dc'.
APPEND ls_node TO lt_nodes.
CLEAR ls_node.
ls_node-chmod = zif_abapgit_definitions=>gc_chmod-file.
ls_node-name = 'something.md'.
ls_node-sha1 = '1236cb3c4b7f0b3600b64f744cde614a283a88dc'.
APPEND ls_node TO lt_nodes.
lv_data = zcl_abapgit_git_pack=>encode_tree( lt_nodes ).
lt_result = zcl_abapgit_git_pack=>decode_tree( lv_data ).
cl_abap_unit_assert=>assert_equals(
exp = lt_nodes
act = lt_result ).
ENDMETHOD.
METHOD test03.
DATA: lt_nodes TYPE zcl_abapgit_git_pack=>ty_nodes_tt,
ls_node LIKE LINE OF lt_nodes,
lv_data TYPE xstring,
lt_result TYPE zcl_abapgit_git_pack=>ty_nodes_tt.
CLEAR ls_node.
ls_node-chmod = zif_abapgit_definitions=>gc_chmod-file.
ls_node-name = 'foobar.txt'.
ls_node-sha1 = '0000003c4b7f0b3600b64f744cde614a28000000'.
APPEND ls_node TO lt_nodes.
lv_data = zcl_abapgit_git_pack=>encode_tree( lt_nodes ).
lt_result = zcl_abapgit_git_pack=>decode_tree( lv_data ).
cl_abap_unit_assert=>assert_equals(
exp = lt_nodes
act = lt_result ).
ENDMETHOD.
ENDCLASS.
CLASS ltcl_type_and_length DEFINITION DEFERRED.
CLASS zcl_abapgit_git_pack DEFINITION LOCAL FRIENDS ltcl_type_and_length.
CLASS ltcl_type_and_length DEFINITION FOR TESTING DURATION SHORT RISK LEVEL HARMLESS.
CLASS ltcl_type_and_length DEFINITION FOR TESTING DURATION SHORT RISK LEVEL HARMLESS FINAL.
PRIVATE SECTION.
METHODS:
@ -72,19 +159,16 @@ CLASS ltcl_type_and_length IMPLEMENTATION.
ENDCLASS.
CLASS ltcl_pack DEFINITION DEFERRED.
CLASS zcl_abapgit_git_pack DEFINITION LOCAL FRIENDS ltcl_pack.
CLASS ltcl_pack DEFINITION FOR TESTING DURATION SHORT RISK LEVEL HARMLESS.
CLASS ltcl_pack DEFINITION FOR TESTING DURATION SHORT RISK LEVEL HARMLESS FINAL.
PRIVATE SECTION.
CONSTANTS: c_sha TYPE zif_abapgit_definitions=>ty_sha1 VALUE '5f46cb3c4b7f0b3600b64f744cde614a283a88dc'.
METHODS:
tree FOR TESTING
RAISING zcx_abapgit_exception,
commit FOR TESTING
RAISING zcx_abapgit_exception,
commit_newline FOR TESTING
@ -290,29 +374,7 @@ CLASS ltcl_pack IMPLEMENTATION.
exp = lt_objects
act = lt_result ).
ENDMETHOD. "encode_decode_pack_long
METHOD tree.
DATA: lt_nodes TYPE zcl_abapgit_git_pack=>ty_nodes_tt,
ls_node LIKE LINE OF lt_nodes,
lv_data TYPE xstring,
lt_result TYPE zcl_abapgit_git_pack=>ty_nodes_tt.
CLEAR ls_node.
ls_node-chmod = zif_abapgit_definitions=>gc_chmod-file.
ls_node-name = 'foobar.txt'.
ls_node-sha1 = c_sha.
APPEND ls_node TO lt_nodes.
lv_data = zcl_abapgit_git_pack=>encode_tree( lt_nodes ).
lt_result = zcl_abapgit_git_pack=>decode_tree( lv_data ).
cl_abap_unit_assert=>assert_equals(
exp = lt_nodes
act = lt_result ).
ENDMETHOD. "tree
ENDMETHOD.
METHOD commit.