哈希临时表行

时间:2016-07-14 10:51:22

标签: progress-4gl openedge

背景故事

我在Android客户端的后端工作。有很多数据要显示,需要一些离线功能,所以我必须解决同步问题。所述数据由临时表组成。

我们的解决方案

现在,为了让客户端知道可能的更改而不执行完整的客户端数据库擦除和创建(花费大量时间),我为每个临时表创建了一个哈希行。通过获取临时表行,为其创建JSON,然后从该JSON中创建散列来创建所述散列。它正在发挥作用。

我对此解决方案的问题

我认为这不是理想的解决方案。所有这些操作看起来都很苛刻,从我的测试中可以看出:

  • 对于某些数据;基线,无动作= 90毫秒
  • 使用buffer-copy = 400 ms
  • 为每个内容设置一个临时表
  • 在每个= 2 880 ms
  • 内的填充之后用上述解决方案计算哈希值

我想要什么

如果我们做错了什么,我感兴趣。这个问题有更好的解决方案吗?是否有不太苛刻的方法来创建每个临时表记录的哈希值?

我们目前正在使用 OpenEdge 10.2B

负责哈希创建的程序, create_hash     创建widget-pool。

define input parameter inp_hBuffer as handle no-undo.
define output parameter out_cHash as c no-undo.

define var ttDynamic as handle no-undo.
define var hBufferTT as handle no-undo.

define var lResult as l no-undo.
define var cDataTT as longchar no-undo.

define var itime as i.

do on error undo,return error:
   if not(valid-handle(inp_hBuffer) and inp_hBuffer:type = 'BUFFER':u) then
      return error substitute('Neplatny typ vstupniho parametru predaneho procedure "&1".','m_ghashb':u).

   create temp-table ttDynamic.
   ttDynamic:add-fields-from(inp_hBuffer).
   ttDynamic:temp-table-prepare(inp_hBuffer:table).

   hBufferTT = ttDynamic:default-buffer-handle.

   hBufferTT:buffer-copy(inp_hBuffer).
   ttDynamic:write-json('longchar':u,cDataTT).

   out_cHash = hex-encode(md5-digest(cDataTT)).
end.

return.

及其用法

for first lbUsrtab where
    lbUsrtab.ucje = GetUcje('m_usrtab':U) and
    lbUsrtab.login-name = LoginName no-lock,
each lbWcesta where
    lbWcesta.ucje = GetUcje('wcesta':U) and
    lbWcesta.kodu = lbUsrtab.kodu no-lock,
each lbWciorg where
    lbWciorg.ucje = GetUcje('wciorg':U) and
    lbWciorg.cest = lbWcesta.cest no-lock,
each lbKontaktr where
    lbKontaktr.ucje = GetUcje('kontaktr':U) and
    lbKontaktr.corg = lbWciorg.corg no-lock
    by lbKontaktr.zako descending
    on error undo, return error return-value:

    create ttKontaktr.
    buffer-copy lbKontaktr to ttKontaktr.
    run create_hash(input buffer ttKontaktr:handle, output ttKontaktr.hash).
end.

我想要什么

  • 要知道我们是否做错了什么,这个解决方案由于某些原因看起来并不正确,我相信有人也必须面对这个问题(创建一个临时表的哈希)
  • 它确实需要花费很多时间,而且将来应该成为一个问题,所以我希望尽早解决这个问题

2 个答案:

答案 0 :(得分:4)

这是你的哈希值的近20倍的解决方案(对于1000次调用,它是320毫秒对17毫秒):

PROCEDURE hash2:
    DEFINE INPUT  PARAMETER inp_hBuffer AS HANDLE    NO-UNDO .
    DEFINE OUTPUT PARAMETER out_cHash   AS CHARACTER NO-UNDO .

    inp_hBuffer:RAW-TRANSFER (TRUE, hRawField) .

    out_cHash = HEX-ENCODE (MD5-DIGEST (ttWithRaw.raw_field)).
END PROCEDURE .

你需要一个带有RAW字段和单个记录的辅助临时表,因为缓冲区对象句柄的RAW-TRANSFER方法只适用于缓冲区字段对象句柄,所以在hash2过程之外有这样的东西,你我只需要运行一次:

DEFINE VARIABLE hRawField AS HANDLE NO-UNDO.

DEFINE TEMP-TABLE ttWithRaw NO-UNDO
    FIELD raw_field AS RAW .

ASSIGN hRawField = BUFFER ttWithRaw:BUFFER-FIELD("raw_field") .

CREATE ttWithRaw .

我还没有尝试优化您的代码。

  

如果我们做错了什么,我感兴趣。这个问题有更好的解决方案吗?是否有不太苛刻的方法来创建每个临时表记录的哈希值?

运行时的很大一部分将来自为每条记录创建动态临时表 - 我怀疑你需要一遍又一遍地为每条记录创建临时表。

也许,通过移动这部分

   create temp-table ttDynamic.
   ttDynamic:add-fields-from(inp_hBuffer).
   ttDynamic:temp-table-prepare(inp_hBuffer:table).

在哈希过程之外,您的代码也将得到改进。但我怀疑它会比基于RAW-TRANSFER方法的版本更快。

答案 1 :(得分:0)

(代表OP发布)

解决方案

我实施了迈克建议的解决方案。对于我们的结构,我无法按照建议在程序之外移动帮助程序内容。在实现我的现实世界问题并测量整个过程的时间之后,通过2450次调用,我获得了2054ms的先前解决方案,而迈克的解决方案只需要240ms。这意味着我无法在现实世界的实施中获得全部收益,但即便快8.5倍也适合我。我会记住所有这些并回到它,以便在我有时间时进一步优化。

以下是我的程序的样子

DEFINE INPUT  PARAMETER inp_hBuffer AS HANDLE    NO-UNDO .
DEFINE OUTPUT PARAMETER out_cHash   AS CHARACTER NO-UNDO .

DEFINE VARIABLE hRawField AS HANDLE NO-UNDO.
DEFINE TEMP-TABLE ttWithRaw NO-UNDO
    FIELD raw_field AS RAW .

ASSIGN hRawField = BUFFER ttWithRaw:BUFFER-FIELD("raw_field") .
CREATE ttWithRaw .

inp_hBuffer:RAW-TRANSFER (TRUE, hRawField) .
out_cHash = HEX-ENCODE (MD5-DIGEST (ttWithRaw.raw_field)).

我们遇到的问题

根据迈克的建议(临时表定义和创建仅调用一次),我们终于有时间进一步优化它,现在它甚至更快。我真的不明白为什么临时表定义,但主要是创建一个记录,是“慢”。

另请注意,raw-transfer方法不适用于大于32kB的字段。