javascript之ReasonML 对命令式 vanilla JavaScript 的性能

pander-it 阅读:189 2025-06-02 22:19:02 评论:0

免责声明:我是 ReasonML 初学者。

我最近开始使用 ReasonML,我注意到与普通 JavaScript 相比,性能有很大差异。这是我针对一个简单的解谜功能的示例(谜题取自:https://adventofcode.com/2015/day/1)

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; 
}; 

结果
  • JavaScript: 5ms
  • ReasonML(递归): 470ms
  • ReasonML(非递归): 7185ms

  • 这是预期的还是我的 ReasonML 函数实现太慢了?

    提前感谢您的澄清/建议。

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

    请您参考如下方法:

    您可以在 Reason 中编写与在 JS 中相同的命令式代码,并且实际上让它更快(在我的计算机上快 30%):

    let findFloorImperative = code => { 
      let level = ref(0); 
      for (i in 0 to String.length(code) - 1) { 
        switch (code.[i]) { 
        | '(' => level := level^ + 1 
        | ')' => level := level^ - 1 
        | _   => failwith("invalid code") 
        } 
      }; 
      level^ 
    }; 
    

    这个递归解决方案几乎同样快:
    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 
    

    Source: re:bench


    标签:JavaScript
    声明

    1.本站遵循行业规范,任何转载的稿件都会明确标注作者和来源;2.本站的原创文章,请转载时务必注明文章作者和来源,不尊重原创的行为我们将追究责任;3.作者投稿可能会经我们编辑修改或补充。

    关注我们

    一个IT知识分享的公众号