Skip to content

Instantly share code, notes, and snippets.

@PilotFlying
Last active October 21, 2022 09:06
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save PilotFlying/9e5965c50ed40a9207bfa9dff40e2732 to your computer and use it in GitHub Desktop.
Save PilotFlying/9e5965c50ed40a9207bfa9dff40e2732 to your computer and use it in GitHub Desktop.
PROGRAM zlocal_test_it_hash.
CLASS gcl_test_runtimes DEFINITION DEFERRED.
CLASS gcl_main DEFINITION.
PUBLIC SECTION.
TYPES:
BEGIN OF t_line,
field1 TYPE char128, "try type string to raise exception cx_sy_assign_cast_illegal_cast
field2 TYPE char128,
END OF t_line,
tt_lines TYPE STANDARD TABLE OF t_line WITH EMPTY KEY.
CLASS-METHODS run_program.
ENDCLASS.
CLASS gcl_test_runtimes DEFINITION.
PUBLIC SECTION.
TYPES:
t_internal_table_hash TYPE string,
BEGIN OF t_measurements,
executions TYPE syst-tabix,
loop_serialization TYPE i,
shortloop_serialization TYPE i,
export_serialization TYPE i,
sha1_function_module TYPE i,
sha2_method TYPE i,
END OF t_measurements.
CLASS-METHODS:
hash_internal_table IMPORTING it TYPE ANY TABLE
RETURNING VALUE(rv_hash) TYPE t_internal_table_hash
RAISING cx_abap_error_analyze.
PROTECTED SECTION.
CLASS-METHODS:
display IMPORTING is_averages TYPE t_measurements.
ENDCLASS.
CLASS gcl_main IMPLEMENTATION.
METHOD run_program.
DATA(lt) = VALUE tt_lines( ( field1 = 'https://blogs.sap.com/2020/01/20/calculate-hash-value-for-internal-table/'
field2 = 'Αβγδεζηθικλμπνξοπρστυφχψω' )
( field1 = 'System characters stored in'
field2 = |{ cl_abap_char_utilities=>charsize } bytes| ) ).
DO 16 TIMES.
APPEND LINES OF lt TO lt. "lines( lt ) = 2^17
ENDDO.
TRY.
gcl_test_runtimes=>hash_internal_table( lt ).
CATCH cx_abap_error_analyze INTO DATA(lo_exc).
MESSAGE lo_exc->message TYPE lo_exc->kind.
ENDTRY.
ENDMETHOD.
ENDCLASS.
CLASS gcl_test_runtimes IMPLEMENTATION.
METHOD hash_internal_table.
DATA:
ls_measurements TYPE t_measurements.
DATA:
lv_table_line_bytes TYPE xstring,
lv_xbuffer TYPE xstring,
lv_shortloop_xbuffer TYPE xstring,
lv_hash TYPE t_internal_table_hash,
lv_sha1_hash TYPE hash160.
DO 10 TIMES.
CLEAR:
lv_xbuffer, lv_shortloop_xbuffer.
TRY.
GET RUN TIME FIELD DATA(lv_start).
LOOP AT it ASSIGNING FIELD-SYMBOL(<ls_line>).
DATA(lv_field_index) = 1.
CLEAR lv_table_line_bytes.
DO.
ASSIGN COMPONENT lv_field_index OF STRUCTURE <ls_line> TO FIELD-SYMBOL(<lv_field>) CASTING TYPE x.
IF sy-subrc <> 0.
EXIT.
ENDIF.
CONCATENATE lv_table_line_bytes <lv_field> INTO lv_table_line_bytes IN BYTE MODE.
lv_field_index = lv_field_index + 1.
ENDDO.
CONCATENATE lv_xbuffer lv_table_line_bytes INTO lv_xbuffer IN BYTE MODE.
ENDLOOP.
GET RUN TIME FIELD DATA(lv_end).
ls_measurements-loop_serialization = ls_measurements-loop_serialization + ( lv_end - lv_start ).
GET RUN TIME FIELD lv_start.
LOOP AT it ASSIGNING <ls_line>.
ASSIGN COMPONENT 0 OF STRUCTURE <ls_line> TO FIELD-SYMBOL(<lv_all_fields>) CASTING TYPE x.
IF sy-subrc <> 0.
MESSAGE 'Should be unreachable' TYPE 'X'.
ENDIF.
CONCATENATE lv_shortloop_xbuffer <lv_all_fields> INTO lv_shortloop_xbuffer IN BYTE MODE.
ENDLOOP.
GET RUN TIME FIELD lv_end.
ls_measurements-shortloop_serialization = ls_measurements-shortloop_serialization + ( lv_end - lv_start ).
IF lv_xbuffer <> lv_shortloop_xbuffer.
BREAK-POINT.
ENDIF.
CATCH cx_sy_assign_cast_illegal_cast. "when, e.g., it_table contains string-type fields
BREAK-POINT.
* EXPORT it = lt TO DATA BUFFER lv_xbuffer COMPRESSION OFF.
ENDTRY.
GET RUN TIME FIELD lv_start.
EXPORT zident = it TO DATA BUFFER lv_xbuffer COMPRESSION OFF.
GET RUN TIME FIELD lv_end.
ls_measurements-export_serialization = ls_measurements-export_serialization + ( lv_end - lv_start ).
GET RUN TIME FIELD lv_start.
CALL FUNCTION 'CALCULATE_HASH_FOR_RAW' "SHA1
EXPORTING
data = lv_xbuffer
IMPORTING
hash = lv_sha1_hash
EXCEPTIONS
unknown_alg = 1
param_error = 2
internal_error = 3
OTHERS = 4.
IF sy-subrc <> 0.
RAISE EXCEPTION TYPE cx_abap_error_analyze
EXPORTING
message = |CALCULATE_HASH_FOR_RAW sy-subrc: { sy-subrc }|
kind = 'E'.
ENDIF.
GET RUN TIME FIELD lv_end.
ls_measurements-sha1_function_module = ls_measurements-sha1_function_module + ( lv_end - lv_start ).
TRY.
GET RUN TIME FIELD lv_start.
cl_abap_message_digest=>calculate_hash_for_raw(
EXPORTING
if_algorithm = 'SHA512' "1848999 - Central Note for CommonCryptoLib 8 (SAPCRYPTOLIB)
if_data = lv_xbuffer
IMPORTING
ef_hashstring = lv_hash " Hash value as hex encoded string
* ef_hashxstring = ef_hashxstring " Binary hash value as XString
* ef_hashb64string = ef_hashb64string " Hash value as base64 encoded string
* ef_hashx = ef_hashx " Hash value as XSequence
).
GET RUN TIME FIELD lv_end.
ls_measurements-sha2_method = ls_measurements-sha2_method + ( lv_end - lv_start ).
CATCH cx_abap_message_digest INTO DATA(lo_mdx).
RAISE EXCEPTION TYPE cx_abap_error_analyze
EXPORTING
previous = lo_mdx
message = |CALCULATE_HASH_FOR_RAW sy-subrc: { sy-subrc }|
kind = 'E'.
ENDTRY.
ls_measurements-executions = ls_measurements-executions + 1.
ENDDO.
TRY.
DATA ls_averages TYPE t_measurements.
ls_averages-executions = ls_measurements-executions.
DEFINE mav.
ls_averages-&1 = ls_measurements-&1 / ls_measurements-executions.
end-of-definition.
mav: loop_serialization, shortloop_serialization, export_serialization, sha1_function_module, sha2_method.
CATCH cx_sy_zerodivide.
RAISE EXCEPTION TYPE cx_abap_error_analyze
EXPORTING
previous = lo_mdx
message = |Zero executions?|
kind = 'E'.
ENDTRY.
display( ls_averages ).
ENDMETHOD.
METHOD display.
SELECT SINGLE laiso FROM t002 WHERE spras = @sy-langu INTO @DATA(lv_lang).
DATA(lv_html) = |<html lang="{ lv_lang }">| &&
`<head>` &&
`<meta name="description" content="https://blogs.sap.com/2020/01/20/calculate-hash-value-for-internal-table/">` &&
`<style type="text/css">` &&
`span.cn {font-family: Courier New;}` &&
`span.ve {font-family: Arial; font-size:-1;}` &&
`</style>` &&
`</head>` &&
`<body>` &&
|<h3 style="font-family:Verdana">{ is_averages-executions NUMBER = USER } Repetitions </h3>| &&
'<span class="ve">' &&
`Average execution times in μs (1 millionth of a second) <br/>` &&
'</span>' &&
'<span class="cn">' &&
|<hr align=left>| &&
`<table>` &&
|<tr><th align=left>Operation</th><th align=left>Time</th><th align=right>Speedup</th></tr>| &&
|<tr><td>Loop serialization:</td><td>{ is_averages-loop_serialization }</td>| &&
| <td align=right>{ round( val = is_averages-loop_serialization / is_averages-loop_serialization dec = 2 ) }</td></tr><br/>| &&
|<tr><td>Short loop serialization:</td><td>{ is_averages-shortloop_serialization }</td>| &&
| <td align=right>{ round( val = is_averages-loop_serialization / is_averages-shortloop_serialization dec = 2 ) }</td></tr><br/>| &&
|<tr><td>EXPORT serialization:</td><td>{ is_averages-export_serialization }</td>| &&
| <td align=right>{ round( val = is_averages-shortloop_serialization / is_averages-export_serialization dec = 2 ) }</td></tr><br/>| &&
|<tr><td>&nbsp;</td><td>&nbsp;</td></tr>| &&
|<tr><td>SHA-1 Function module:</td><td>{ is_averages-sha1_function_module }</td>| &&
| <td align=right>{ round( val = is_averages-sha1_function_module / is_averages-sha1_function_module dec = 2 ) }</td></tr><br/>| &&
|<tr><td>SHA-2 Method:</td><td>{ is_averages-sha2_method }</td>| &&
| <td align=right>{ round( val = is_averages-sha1_function_module / is_averages-sha2_method dec = 2 ) }</td></tr><br/>| &&
`</table></br>` &&
|<hr align=left>| &&
'</span>' &&
`</body>` &&
`</html>`.
cl_abap_browser=>show_html(
EXPORTING
* html = html " HTML Table, Line Width 255 Characters
title = 'Loop serialization vs EXPORT' " Window Title
size = cl_abap_browser=>medium " Size (S,M.L,XL)
* modal = abap_true " Dialog box is modal (else modeless)
html_string = lv_html " HTML String
printing = abap_true " Key for printing
* buttons = navigate_off " Navigation Keys navigate_...
format = cl_abap_browser=>portrait " Landscape/portrait format
position = cl_abap_browser=>middle " Position
* data_table = data_table " External data
* anchor = anchor " Goto Point
context_menu = abap_true " Display context menu in browser
* html_xstring = html_xstring " HTML Binary String
* check_html = abap_true " Test of HTML File
* container = container " Container for display
* dialog = abap_true " Display in dialog box
* IMPORTING
* html_errors = html_errors " Error List from Test
).
ENDMETHOD.
ENDCLASS.
START-OF-SELECTION.
gcl_main=>run_program( ).
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment