我使用线性相关方法在XQUERY 1.0中编写了(伪)随机数生成器。它有效,但很慢。帮助我改进代码:
xquery version "1.0";
(:pseudorandom number generator using Linear Congruential Method (LCM). The number generated will be less than $m :)
declare namespace mg = "https://www.linkedin.com/in/maria-kedzierski-36088513b/";
declare variable $m:= 32768; (: select $m to be power of 2 :)
declare variable $a:= 25173; (: $a=1+4k, where k is an integer and $a < $m :)
declare variable $c:= 13849; (: $c is relative prime to $m and $c < $m :)
declare variable $x0:= 16384; (: $X0 < $m :)
declare function mg:random($num as xs:integer) as xs:integer {
if ($num = 1) then (($a * $x0 + $c) mod $m) else (($a * mg:random($num - 1) + $c) mod $m) };
for $i in (1 to 100) return mg:random($i)
答案 0 :(得分:1)
当我在MarkLogic中分析代码执行时,大部分时间花在重新计算已经生成的数字上。利用地图,您可以缓存这些计算值。
以下是使用MarkLogic map functions的 XQuery 1.0-ml 转换。它将转换时间从16ms减少到1ms。
xquery version "1.0-ml";
(:pseudorandom number generator using Linear Congruential Method (LCM). The number generated will be less than $m :)
declare namespace mg = "https://www.linkedin.com/in/maria-kedzierski-36088513b/";
declare variable $m:= 32768; (: select $m to be power of 2 :)
declare variable $a:= 25173; (: $a=1+4k, where k is an integer and $a < $m :)
declare variable $c:= 13849; (: $c is relative prime to $m and $c < $m :)
declare variable $x0:= 16384; (: $X0 < $m :)
declare variable $cache := map:new();
declare function mg:random($num as xs:integer) as xs:integer {
let $key := xs:string($num)
let $cached-value := map:get($cache, $key)
return
if ($cached-value) then
$cached-value
else
let $random-value :=
if ($num = 1) then
($a * $x0 + $c) mod $m
else
($a * mg:random($num - 1) + $c) mod $m
return
(
$random-value,
map:put($cache, $key, $random-value)
)
};
for $i in (1 to 100)
return mg:random($i)
下面是使用标准地图的纯XQuery 3.1模块。尽管MarkLogic具有许多3.x语言功能,但它尚不允许标准map constructors的语法。当我在eXist中分析这个模块时,它实际上将时间从57ms增加到151ms:
xquery version "3.1";
(:pseudorandom number generator using Linear Congruential Method (LCM). The number generated will be less than $m :)
declare namespace mg = "https://www.linkedin.com/in/maria-kedzierski-36088513b/";
declare variable $m:= 32768; (: select $m to be power of 2 :)
declare variable $a:= 25173; (: $a=1+4k, where k is an integer and $a < $m :)
declare variable $c:= 13849; (: $c is relative prime to $m and $c < $m :)
declare variable $x0:= 16384; (: $X0 < $m :)
declare variable $cache := map {};
declare function mg:random($num as xs:integer) as xs:integer {
let $key := xs:string($num)
let $cached-value := map:get($cache, $key)
return
if ($cached-value) then
$cached-value
else
let $random-value :=
if ($num = 1) then
($a * $x0 + $c) mod $m
else
($a * mg:random($num - 1) + $c) mod $m
return
(
$random-value,
map:put($cache, $key, $random-value)
)[1]
};
for $i in (1 to 100)
return mg:random($i)