{"action":"opened","issue":{"url":"https://api.github.com/repos/nim-lang/Nim/issues/3155","labels_url":"https://api.github.com/repos/nim-lang/Nim/issues/3155/labels{/name}","comments_url":"https://api.github.com/repos/nim-lang/Nim/issues/3155/comments","events_url":"https://api.github.com/repos/nim-lang/Nim/issues/3155/events","html_url":"https://github.com/nim-lang/Nim/issues/3155","id":97788136,"number":3155,"title":"Slow string search","user":{"login":"scriptum","id":695971,"avatar_url":"https://avatars.githubusercontent.com/u/695971?v=3","gravatar_id":"","url":"https://api.github.com/users/scriptum","html_url":"https://github.com/scriptum","followers_url":"https://api.github.com/users/scriptum/followers","following_url":"https://api.github.com/users/scriptum/following{/other_user}","gists_url":"https://api.github.com/users/scriptum/gists{/gist_id}","starred_url":"https://api.github.com/users/scriptum/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/scriptum/subscriptions","organizations_url":"https://api.github.com/users/scriptum/orgs","repos_url":"https://api.github.com/users/scriptum/repos","events_url":"https://api.github.com/users/scriptum/events{/privacy}","received_events_url":"https://api.github.com/users/scriptum/received_events","type":"User","site_admin":false},"labels":[],"state":"open","locked":false,"assignee":null,"milestone":null,"comments":0,"created_at":"2015-07-28T19:53:34Z","updated_at":"2015-07-28T19:53:34Z","closed_at":null,"body":"libc always beats Nim's implementation (tested Linux x86_64):\r\n```\r\nimport strutils, times\r\n\r\nproc altfind(s, sub: string, start: Natural = 0): int {.inline.} =\r\n  proc memmem(a: pointer, alen: csize, b: pointer, blen: csize): pointer {.importc, header: \"string.h\".}\r\n  if s.len < sub.len + start: return -1\r\n  let res = cast[int](memmem(cstring(s), s.len, cstring(sub), sub.len))\r\n  if res != 0: return res - cast[int](cstring(s))\r\n  return -1\r\nproc altfind(s: string, sub: char, start: Natural = 0): int {.inline.} =\r\n  proc memchr(a: pointer, b: cint, alen: csize): pointer {.importc, header: \"string.h\".}\r\n  if s.len < 1 + start: return -1\r\n  let res = cast[int](memchr(cstring(s), sub.ord, s.len))\r\n  if res != 0: return res - cast[int](cstring(s))\r\n  return -1\r\n\r\nwhen isMainModule:\r\n  var res: int\r\n  # long string\r\n  let a = 'x'.repeat(1024*1024*1024)\r\n  for needle in [\"hello\", \"hello\".repeat 10, \"hello\".repeat 1000]:\r\n    var cpu1 = cpuTime()\r\n    res = a.find(needle)\r\n    echo \"old \", cpuTime() - cpu1, \" \", res\r\n    cpu1 = cpuTime()\r\n    res = a.altfind(needle)\r\n    echo \"new \", cpuTime() - cpu1, \" \", res\r\n  var cpu1 = cpuTime()\r\n  res = a.find('c')\r\n  echo \"old \", cpuTime() - cpu1, \" \", res\r\n  cpu1 = cpuTime()\r\n  res = a.altfind('c')\r\n  echo \"new \", cpuTime() - cpu1, \" \", res\r\n  # short strings\r\n  let b = 'x'.repeat(128)\r\n  cpu1 = cpuTime()\r\n  for i in 0..1000000:\r\n    res += b.find(\"hello\")\r\n  echo \"old \", cpuTime() - cpu1, \" \", res\r\n  cpu1 = cpuTime()\r\n  for i in 0..1000000:\r\n    res += b.altfind(\"hello\")\r\n  echo \"new \", cpuTime() - cpu1, \" \", res\r\n  cpu1 = cpuTime()\r\n  for i in 0..1000000:\r\n    res += b.find('c')\r\n  echo \"old \", cpuTime() - cpu1, \" \", res\r\n  cpu1 = cpuTime()\r\n  for i in 0..1000000:\r\n    res += b.altfind('c')\r\n  echo \"new \", cpuTime() - cpu1, \" \", res\r\n\r\nold 0.578103 -1\r\nnew 0.1501140000000001 -1\r\nold 0.192072 -1\r\nnew 0.1860760000000001 -1\r\nold 0.01996299999999973 -1\r\nnew 0.01987700000000014 -1\r\nold 0.8332839999999999 -1\r\nnew 0.1506780000000001 -1\r\nold 0.257072 -1000002\r\nnew 0.0171490000000003 -2000003\r\nold 0.1070769999999999 -3000004\r\nnew 0.01177099999999998 -4000005\r\n```\r\nWhy not just use libc functions for Nim strings? It's simpler, faster, shorter."}}