Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/javascript/364.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/performance/5.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/.net/21.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
针对命令式香草JavaScript的ReasonML性能_Javascript_Performance_Reason_Bucklescript - Fatal编程技术网

针对命令式香草JavaScript的ReasonML性能

针对命令式香草JavaScript的ReasonML性能,javascript,performance,reason,bucklescript,Javascript,Performance,Reason,Bucklescript,免责声明:我是初学者 我最近开始使用ReasonML,我注意到它与普通JavaScript在性能上有很大的不同。下面是我针对一个简单的谜题解决函数的示例(谜题取自:) ReasonML let head = str => switch (str) { | "" => "" | _ => String.sub(str, 0, 1) }; let tail = str => switch (str) { | "" => "" | _ =&g

免责声明:我是初学者

我最近开始使用ReasonML,我注意到它与普通JavaScript在性能上有很大的不同。下面是我针对一个简单的谜题解决函数的示例(谜题取自:)

ReasonML

let head = str =>
  switch (str) {
  | "" => ""
  | _ => String.sub(str, 0, 1)
  };

let tail = str =>
  switch (str) {
  | "" => ""
  | _ => String.sub(str, 1, String.length(str) - 1)
  };

let rec stringToList = str =>
  switch (str) {
  | "" => []
  | _ => [[head(str)], tail(str) |> stringToList] |> List.concat
  };

let rec findFloor = code =>
  switch (head(code)) {
  | "" => 0
  | "(" => 1 + findFloor(tail(code))
  | ")" => (-1) + findFloor(tail(code))
  | _ => 0
  };

let findFloorFold = code => {
  let calc = (a, b) =>
    switch (b) {
    | "" => a
    | "(" => a + 1
    | ")" => a - 1
    | _ => a
    };

  code |> stringToList |> List.fold_left(calc, 0);
};
JavaScript

const solve = code => {
  let level = 0;
  for (let i = 0, l = code.length; i < l; i++) {
    const el = code[i];
    if (el === "(") {
      ++level;
      continue;
    }
    if (el === ")") {
      --level;
      continue;
    }
  }
  return level;
};
const solve=code=>{
设水平=0;
for(设i=0,l=code.length;i
结果

  • JavaScript:5ms
  • ReasonML(递归):470ms
  • ReasonML(非递归):7185ms
这是预期的还是我的ReasonML函数实现太慢

提前感谢您的澄清/建议


诚然,由于字符串到数组的转换,第二种解决方案(非rec)的速度很慢,但这是因为在ReasonML中,字符串不是由字符列表表示的

您可以合理地编写与JS中相同的命令式代码,并且实际速度更快(在我的计算机上提高30%):

这个递归解决方案几乎同样快:

let findFloorRecursiveNoList = code => {  
  let rec helper = (level, i) =>
    if (i < String.length(code)) {
      switch (code.[i]) {
      | '(' => helper(level + 1, i + 1)
      | ')' => helper(level - 1, i + 1)
      | _   => failwith("invalid code")
      }
    } else {
      level
    };

  helper(0, 0)
};

在非递归实现中,您可以使用该方法将函数应用于每个字符,而不是将字符串转换为列表,然后遍历列表吗?
string.iter
返回一个
单元
类型,因此我希望能够累积操作结果(可能我误解了您的建议..)我认为,一般来说,由另一种语言生成的JavaScript比手动调整的JavaScript优化程度要低,但差别似乎太大了。生成的JavaScript似乎也有很多开销,比如加载库、
List.
方法和很多函数调用,我只是把它扔了出去。我从来没有写过任何ReasonML,也没有写过任何标准ML已经将近20年了,但我似乎记得有一种方法可以将累加器作为传递给迭代器的函数的一部分。您的
stringToList
转换似乎效率极低。我不知道ReasonML,我希望标准库中有一个本机转换函数(或者至少有一个
字符串
数组(char)
一个)。我会使用
Str.split(regex“”)
thoughHmm,如果您对函数进行压力测试,您会发现JavaScript速度更快。(见reddit回复:)这很有趣,我们从Js版本慢了15%到Reason命令快了3%。同样,随着我们的扩展,递归虽然是这两种情况中最慢的,但它的性能提高了27%。@wegry“默认Curring”?@glennsl我的意思是使用[@bs]强制不修剪。不过,在这种情况下,codegen似乎不受影响。我想我不确定什么时候从bsb开始进行uncurring。是的,编译器既知道实现,也知道它的用法。它可以做这样的优化。在模块级,而不仅仅是在函数中。
let findFloorRecursiveNoList = code => {  
  let rec helper = (level, i) =>
    if (i < String.length(code)) {
      switch (code.[i]) {
      | '(' => helper(level + 1, i + 1)
      | ')' => helper(level - 1, i + 1)
      | _   => failwith("invalid code")
      }
    } else {
      level
    };

  helper(0, 0)
};
Reason, imperative:            19,246,043 ops/sec
Reason, recursive, no list:    18,113,602 ops/sec
JavaScript, imperative:        13,761,780 ops/sec
Reason, recursive, list:       481,426 ops/sec
Reason, folding, list:         239,761 ops/sec