{"action":"created","issue":{"url":"https://api.github.com/repos/nodejs/node/issues/2680","labels_url":"https://api.github.com/repos/nodejs/node/issues/2680/labels{/name}","comments_url":"https://api.github.com/repos/nodejs/node/issues/2680/comments","events_url":"https://api.github.com/repos/nodejs/node/issues/2680/events","html_url":"https://github.com/nodejs/node/issues/2680","id":104710833,"number":2680,"title":"fs.realpath 70x slower than native ","user":{"login":"stefanpenner","id":1377,"avatar_url":"https://avatars.githubusercontent.com/u/1377?v=3","gravatar_id":"","url":"https://api.github.com/users/stefanpenner","html_url":"https://github.com/stefanpenner","followers_url":"https://api.github.com/users/stefanpenner/followers","following_url":"https://api.github.com/users/stefanpenner/following{/other_user}","gists_url":"https://api.github.com/users/stefanpenner/gists{/gist_id}","starred_url":"https://api.github.com/users/stefanpenner/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/stefanpenner/subscriptions","organizations_url":"https://api.github.com/users/stefanpenner/orgs","repos_url":"https://api.github.com/users/stefanpenner/repos","events_url":"https://api.github.com/users/stefanpenner/events{/privacy}","received_events_url":"https://api.github.com/users/stefanpenner/received_events","type":"User","site_admin":false},"labels":[{"url":"https://api.github.com/repos/nodejs/node/labels/feature%20request","name":"feature request","color":"0D7BDE"},{"url":"https://api.github.com/repos/nodejs/node/labels/fs","name":"fs","color":"0052cc"}],"state":"open","locked":false,"assignee":null,"milestone":null,"comments":17,"created_at":"2015-09-03T14:41:13Z","updated_at":"2015-09-04T18:01:57Z","closed_at":null,"body":"repost of https://github.com/nodejs/node-v0.x-archive/issues/7902 to ensure it is not lost, as per @jasnell suggestion.\r\n\r\ncredit goes to @joliss I am merely transplanting the issue.\r\n\r\n----\r\n\r\nThe [fs.realpath](https://nodejs.org/api/fs.html#fs_fs_realpath_path_cache_callback) function is 70x slower than native C [realpath](http://man7.org/linux/man-pages/man3/realpath.3.html). On my system, fs.realpath takes 32 µs, while C realpath takes 0.45 µs.\r\n\r\nThis is a real problem in the Broccoli build tool, where we need to resolve symlinks in hot code paths. Resolving 1000 symlinked files - not an unusual case - would take 45 ms, slowing down the build considerably. [1]\r\n\r\nAs for a solution: I haven't looked at the fs.js source in detail, but it seems we might be able to call the realpath function in the C standard library, where available, instead of using our [own implementation](https://github.com/nodejs/node-v0.x-archive/blob/df205360f5cdf3310a69748e74c636ec011d2e64/lib/fs.js#L1216-L1433).\r\n\r\nBenchmark code for Node:\r\n\r\n```js\r\nvar fs = require('fs')\r\n\r\nvar start = Date.now()\r\nvar n = 10000\r\nfor (var i = 0; i < n; i++) {\r\n  if (fs.realpathSync('.') === 'dummy') throw new Error('never happens')\r\n}\r\nconsole.log(((Date.now() - start) * 1000 / n) + ' us') // => 32 us on Node 0.11.13\r\n```\r\n\r\nBenchmark code for C:\r\n\r\n```js\r\n#include <limits.h> /* PATH_MAX */\r\n#include <stdio.h>\r\n#include <stdlib.h>\r\n\r\n// Adapted from http://stackoverflow.com/a/1563237/525872\r\n\r\nint main(void) {\r\n  char buf[PATH_MAX + 1]; /* not sure about the \"+ 1\" */\r\n  int i;\r\n  for (i = 0; i < 1000000; i++) {\r\n    char *res = realpath(\".\", buf);\r\n    if (res) {\r\n      // printf(\"This source is at %s.\\n\", buf);\r\n    } else {\r\n      perror(\"realpath\");\r\n      exit(EXIT_FAILURE);\r\n    }\r\n  }\r\n  return 0;\r\n}\r\n```\r\n\r\nRun with `gcc -std=gnu99 realpath-benchmark.c -o realpath-benchmark && time ./realpath-benchmark`. This yields 0.45 µs per iteration on my Linux system.\r\n\r\n[1] We cannot work around this by using naïve string concatenation, because [path_resolution(7)](http://man7.org/linux/man-pages/man7/path_resolution.7.html) requires that we resolve symlinks in all path components. Here is a [gist](https://gist.github.com/joliss/3292eda35cd4d564cdd7) to show why this matters."},"comment":{"url":"https://api.github.com/repos/nodejs/node/issues/comments/137807166","html_url":"https://github.com/nodejs/node/issues/2680#issuecomment-137807166","issue_url":"https://api.github.com/repos/nodejs/node/issues/2680","id":137807166,"user":{"login":"trevnorris","id":289174,"avatar_url":"https://avatars.githubusercontent.com/u/289174?v=3","gravatar_id":"","url":"https://api.github.com/users/trevnorris","html_url":"https://github.com/trevnorris","followers_url":"https://api.github.com/users/trevnorris/followers","following_url":"https://api.github.com/users/trevnorris/following{/other_user}","gists_url":"https://api.github.com/users/trevnorris/gists{/gist_id}","starred_url":"https://api.github.com/users/trevnorris/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/trevnorris/subscriptions","organizations_url":"https://api.github.com/users/trevnorris/orgs","repos_url":"https://api.github.com/users/trevnorris/repos","events_url":"https://api.github.com/users/trevnorris/events{/privacy}","received_events_url":"https://api.github.com/users/trevnorris/received_events","type":"User","site_admin":false},"created_at":"2015-09-04T18:01:57Z","updated_at":"2015-09-04T18:01:57Z","body":"Is the consensus then to wait for `uv_realpath()` before implementing anything here?"}}