Skip to content

Commit 54f33bb

Browse files
committed
sys.is_symlink: 100x speedup
1 parent 8fe4bd0 commit 54f33bb

File tree

4 files changed

+85
-15
lines changed

4 files changed

+85
-15
lines changed

+stdlib/+sys/is_symlink.m

Lines changed: 5 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,23 +1,14 @@
11
function [ok, cmd] = is_symlink(file)
2-
arguments
3-
file (1,1) string
4-
end
5-
6-
ok = false;
72

83
if ispc()
9-
cmd = sprintf('pwsh -command "(Get-Item -Path ''%s'').Attributes"', file);
4+
cmd = sprintf('fsutil reparsepoint query "%s"', file);
5+
% cmd = sprintf('pwsh -command "(Get-Item -Path ''%s'').Attributes"', file);
6+
% works (examine output for ReparsePoint) but is like 100x slower
107
else
118
cmd = sprintf('test -L "%s"', file);
129
end
1310

14-
if strlength(file)
15-
[s, m] = system(cmd);
16-
ok = s == 0;
17-
18-
if ispc()
19-
ok = ok && contains(m, 'ReparsePoint');
20-
end
21-
end
11+
[s, ~] = system(cmd);
12+
ok = s == 0;
2213

2314
end

+stdlib/is_symlink.m

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@
1010
function [ok, b] = is_symlink(file, backend)
1111
arguments
1212
file string
13-
backend (1,:) string = ["native", "java", "dotnet", "python", "sys"]
13+
backend (1,:) string = ["native", "java", "python", "dotnet", "sys"]
1414
end
1515

1616
o = stdlib.Backend(mfilename(), backend);

example/BenchmarkIsSymlink.m

Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
classdef (SharedTestFixtures={ matlab.unittest.fixtures.PathFixture("..")}) ...
2+
BenchmarkIsSymlink < matlab.perftest.TestCase
3+
4+
properties
5+
link
6+
target
7+
not_exist = tempname()
8+
fun = @stdlib.is_symlink
9+
end
10+
11+
properties(TestParameter)
12+
backend
13+
end
14+
15+
methods (TestParameterDefinition, Static)
16+
function backend = setupBackend()
17+
backend = init_backend('is_symlink');
18+
end
19+
end
20+
21+
22+
methods(TestClassSetup)
23+
function setup_symlink(tc)
24+
tc.applyFixture(matlab.unittest.fixtures.WorkingFolderFixture())
25+
26+
tc.link = fullfile(pwd(), 'my.lnk');
27+
28+
tc.target = [mfilename("fullpath") '.m'];
29+
30+
tc.assertTrue(stdlib.create_symlink(tc.target, tc.link))
31+
end
32+
end
33+
34+
35+
methods (Test)
36+
37+
function bench_exist(tc, backend)
38+
tc.startMeasuring()
39+
i = tc.fun(tc.link, backend);
40+
tc.stopMeasuring()
41+
42+
tc.verifyClass(i, 'logical')
43+
tc.verifyTrue(i)
44+
end
45+
46+
47+
function bench_not_exist(tc, backend)
48+
tc.startMeasuring()
49+
i = tc.fun(tc.not_exist, backend);
50+
tc.stopMeasuring()
51+
52+
tc.verifyClass(i, 'logical')
53+
tc.assertNotEmpty(i)
54+
tc.verifyFalse(i)
55+
end
56+
57+
end
58+
59+
end

example/BenchmarkIsSymlinkRun.m

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
function [r, s] = BenchmarkIsSymlinkRun()
2+
tname = "BenchmarkIsSymlink";
3+
4+
%% Exist
5+
r.same = run_bench(tname + "/bench_exist");
6+
s.exist = sampleSummary(r.same);
7+
disp(sortrows(s.exist, "Median"))
8+
%% Not Exist
9+
r.not = run_bench(tname + "/bench_not_exist");
10+
s.not = sampleSummary(r.not);
11+
disp(sortrows(s.not, "Median"))
12+
13+
end
14+
15+
16+
function result = run_bench(name)
17+
suite = testsuite(name);
18+
exp = matlab.perftest.TimeExperiment.limitingSamplingError(MaxSamples=20, RelativeMarginOfError=0.1);
19+
result = exp.run(suite);
20+
end

0 commit comments

Comments
 (0)