为了学习的目的,我试图想出一个字符串替换函数,这就是我现在所拥有的:
let string_replace where what replacement =
let wlength = (String.length what - 1) in
let length = (String.length where - 1) in
let rec loop i shift =
let [shift, i] =
if wlength == shift then
(String.blit replacement 0 where (i - wlength) (wlength + 1); [0, i])
else if (String.get where i == String.get what shift) then
[shift + 1, i]
else [0, i - shift]
in if i < length then loop (i + 1) shift
in loop 0 0; where;;
现在,这里有一个测试:http ://raid6.com.au/~onlyjob/posts/arena/所以我想看看我相对而言做得如何。而且,在这里,我编写了测试:
let test =
let initial = "abcdefgh" ^ "efghefgh" in
let initial_time = Sys.time() in
let initial_length = String.length initial in
let imax = (1024 / (String.length initial)) * 1024 * 4 in
let rec loop s i =
if i < imax then
let ns = string_replace (s ^ initial) "efgh" "____" in
let sl = initial_length * i in
if (sl mod 1024) * 256 == 0 then
Printf.printf "%f s | %d Kb |\n" (Sys.time() -. initial_time) (sl / 1024);
loop ns (i + 1)
in loop initial 0;;
test;;
我试图尽可能地关注 JavaScript 测试,以便能够比较结果(我在这里做了一些格式化,也让你不用搜索):
function test() {
var str = "abcdefgh" + "efghefgh",
imax = 1024 / str.length * 1024 * 4,
time = new Date(), gstr = "", i = 0, lngth;
console.log("exec.tm.sec\tstr.length");
while (i++ < imax + 1000) {
gstr += str;
gstr = gstr.replace(/efgh/g, "____");
lngth = str.length * i;
if (lngth % 1024 * 256 === 0) {
var curdate = new Date();
console.log((curdate.getTime() - time.getTime()) / 1000 +
"sec\t\t" + lngth / 1024 + "kb");
}
}
}
这是我得到的结果......
| JavaScript | OCaml | String size |
|------------+--------------+-------------|
| 0.78 s | 14.576784 s | 256 Kb |
| 3.266 s | 58.468111 s | 512 Kb |
| 7.618 s | 132.954788 s | 768 Kb |
| 13.849 s | 238.793697 s | 1024 Kb |
| 46.243 s | 379.175356 s | 1280 Kb |
| 86.046 s | 550.838260 s | 1536 Kb |
所以,我的问题是:我的字符串替换功能有什么特别的问题吗?或者这个速度是可以预期的?我已经用ocamlopt
.
这是我的另一个尝试:
let string_index_of where what =
let length = (String.length where - 1) in
let pattern = (1 lsl (String.length what + 1)) - 1 in
let rec loop i j mask =
if i == length + 1 then (-1)
else if mask == pattern then i - j
else if (where.[i]) == (what.[j]) then
loop (i + 1) (j + 1) ((mask lsl 1) lor 1)
else loop (i + 1 - j) 0 1
in loop 0 0 1;;
let test =
let initial = "abcdefgh" ^ "efghefgh" in
let replacement = "____" in
let replacement_length = String.length replacement in
let initial_time = Sys.time() in
let initial_length = String.length initial in
let imax = (1024 / (String.length initial)) * 1024 * 4 in
let rec loop s i =
if i < imax then
let concatenated = s ^ "efgh" in
let sl = initial_length * i in
let rec replace_loop st =
let index = string_index_of st "efgh" in
if index >= 0 then
((String.blit replacement 0 st index replacement_length);
replace_loop st)
in replace_loop concatenated;
if sl mod (1024 * 256) == 0 then
Printf.printf "%f s | %d Kb |\n" (Sys.time() -. initial_time) (sl / 1024);
loop concatenated (i + 1)
in loop initial 0;;
test;;
我还制作了一个更大的表格(包括一些其他语言进行比较):
| JavaScript V8 | ocamlopt | ocamlopt bitup | SBCL | C gcc 4 -O3 | String size |
|---------------+--------------+----------------+-----------+-------------+-------------|
| 0.78 s | 14.576784 s | 4.615298 s | 17.463 s | 1 s | 256 Kb |
| 3.266 s | 58.468111 s | 18.474191 s | 68.484 s | 4 s | 512 Kb |
| 7.618 s | 132.954788 s | 41.673664 s | 153.99 s | 10 s | 768 Kb |
| 13.849 s | 238.793697 s | 74.652651 s | 275.204 s | 17 s | 1024 Kb |
| 46.243 s | 379.175356 s | 116.517287 s | 431.768 s | 27 s | 1280 Kb |
| 86.046 s | 550.838260 s | 166.662663 s | 624.559 s | 38 s | 1536 Kb |
我仍然希望能做得更好。