Skip to content

Commit a27707f

Browse files
committed
is_symlink: prefer native as it's 4x faster
read_symlink: prefer native create_symlink: faster native
1 parent ae09b26 commit a27707f

File tree

10 files changed

+60
-71
lines changed

10 files changed

+60
-71
lines changed

+stdlib/+native/create_symlink.m

Lines changed: 0 additions & 17 deletions
This file was deleted.

+stdlib/+native/is_symlink.m

Lines changed: 0 additions & 5 deletions
This file was deleted.

+stdlib/+native/read_symlink.m

Lines changed: 0 additions & 10 deletions
This file was deleted.

+stdlib/Backend.m

Lines changed: 0 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -105,14 +105,6 @@
105105
case 'native'
106106

107107
switch functionName
108-
case 'create_symlink'
109-
% Some Windows R2025a give error 'MATLAB:io:filesystem:symlink:NeedsAdminPerms'
110-
% 25.1.0.2973910 (R2025a) Update 1 gave this error for example.
111-
if stdlib.matlabOlderThan('R2024b') || ispc()
112-
continue
113-
end
114-
case {'is_symlink', 'read_symlink'}
115-
if stdlib.matlabOlderThan('R2024b'), continue, end
116108
case {'get_permissions', 'set_permissions'}
117109
if stdlib.matlabOlderThan('R2025a'), continue, end
118110
end

+stdlib/create_symlink.m

Lines changed: 26 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,9 @@
66
%%% Outputs
77
% * ok: true if successful
88
% * b: backend used
9+
%
10+
% Some Windows Matlab R2025a give error 'MATLAB:io:filesystem:symlink:NeedsAdminPerms'
11+
% For example, Matlab 25.1.0.2973910 R2025a Update 1 gave this error.
912

1013
function [ok, b] = create_symlink(target, link, backend)
1114
arguments
@@ -14,8 +17,30 @@
1417
backend (1,:) string = ["native", "dotnet", "python", "sys"]
1518
end
1619

20+
21+
if ismember('native', backend) || stdlib.strempty(backend)
22+
try
23+
createSymbolicLink(link, target);
24+
ok = true;
25+
b = "native";
26+
return
27+
catch e
28+
switch e.identifier
29+
case {'MATLAB:UndefinedFunction', 'MATLAB:io:filesystem:symlink:NeedsAdminPerms'}
30+
% pass through to stdlib.Backend
31+
case {'MATLAB:io:filesystem:symlink:FileExists', 'MATLAB:io:filesystem:symlink:TargetNotFound'}
32+
ok = false;
33+
return
34+
otherwise
35+
rethrow(e)
36+
end
37+
end
38+
39+
backend(ismember(backend, 'native')) = [];
40+
end
41+
1742
o = stdlib.Backend(mfilename(), backend);
43+
b = o.backend;
1844
ok = o.func(target, link);
1945

20-
b = o.backend;
2146
end

+stdlib/is_symlink.m

Lines changed: 13 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -13,14 +13,22 @@
1313
backend (1,:) string = ["native", "java", "python", "dotnet", "sys"]
1414
end
1515

16-
o = stdlib.Backend(mfilename(), backend);
16+
if ismember('native', backend) || stdlib.strempty(backend)
17+
try
18+
ok = isSymbolicLink(file);
19+
b = "native";
20+
return
21+
catch e
22+
if e.identifier ~= "MATLAB:UndefinedFunction"
23+
rethrow(e)
24+
end
25+
end
1726

18-
if isscalar(file)
19-
ok = o.func(file);
20-
else
21-
ok = arrayfun(o.func, file);
27+
backend(ismember(backend, 'native')) = [];
2228
end
2329

30+
o = stdlib.Backend(mfilename(), backend);
2431
b = o.backend;
32+
ok = o.func(file);
2533

2634
end

+stdlib/read_symlink.m

Lines changed: 15 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -16,15 +16,24 @@
1616
backend (1,:) string = ["native", "java", "dotnet", "python", "sys"]
1717
end
1818

19-
o = stdlib.Backend(mfilename(), backend);
2019

21-
if isscalar(file)
22-
r = o.func(file);
23-
else
24-
r = arrayfun(o.func, file);
20+
if ismember('native', backend) || stdlib.strempty(backend)
21+
try
22+
[ok, r] = isSymbolicLink(file);
23+
r(~ok) = "";
24+
b = "native";
25+
return
26+
catch e
27+
if e.identifier ~= "MATLAB:UndefinedFunction"
28+
rethrow(e)
29+
end
30+
end
31+
32+
backend(ismember(backend, 'native')) = [];
2533
end
2634

35+
o = stdlib.Backend(mfilename(), backend);
2736
b = o.backend;
28-
37+
r = o.func(file);
2938

3039
end

example/BenchmarkIsSymlinkRun.m

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,6 @@
1515

1616
function result = run_bench(name)
1717
suite = testsuite(name);
18-
exp = matlab.perftest.TimeExperiment.limitingSamplingError(MaxSamples=20, RelativeMarginOfError=0.1);
18+
exp = matlab.perftest.TimeExperiment.limitingSamplingError(MaxSamples=50, RelativeMarginOfError=0.1);
1919
result = exp.run(suite);
2020
end

example/BenchmarkSymlink.m

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,8 +14,8 @@
1414

1515
methods (TestParameterDefinition, Static)
1616
function [is_backend, rs_backend] = setupBackend()
17-
is_backend = init_backend('is_symlink');
18-
rs_backend = init_backend('read_symlink');
17+
is_backend = cellstr(["native", init_backend('is_symlink')]);
18+
rs_backend = cellstr(["native", init_backend('read_symlink')]);
1919
end
2020
end
2121

test/TestSymlink.m

Lines changed: 3 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -20,9 +20,9 @@
2020

2121
methods (TestParameterDefinition, Static)
2222
function [B_create_symlink, B_read_symlink, B_is_symlink] = setupBackends()
23-
B_create_symlink = init_backend("create_symlink");
24-
B_read_symlink = init_backend("read_symlink");
25-
B_is_symlink = init_backend("is_symlink");
23+
B_create_symlink = cellstr(["native", init_backend("create_symlink")]);
24+
B_read_symlink = cellstr(["native", init_backend("read_symlink")]);
25+
B_is_symlink = cellstr(["native", init_backend("is_symlink")]);
2626
end
2727
end
2828

@@ -51,11 +51,6 @@ function test_is_symlink(tc, p, B_is_symlink)
5151
tc.verifyEqual(stdlib.is_symlink(p{1}, B_is_symlink), p{2}, p{1})
5252
end
5353

54-
function test_is_symlink_array(tc, B_is_symlink)
55-
r = stdlib.is_symlink([tc.link, mfilename() + ".m"], B_is_symlink);
56-
tc.verifyEqual(r, [true, false], "failed to detect own link")
57-
end
58-
5954

6055
function test_read_symlink_empty(tc, Pre, B_read_symlink)
6156
tc.verifyEqual(stdlib.read_symlink(Pre, B_read_symlink), "")
@@ -69,14 +64,6 @@ function test_read_symlink(tc, B_read_symlink)
6964
end
7065

7166

72-
function test_read_symlink_array(tc, B_read_symlink)
73-
r = stdlib.read_symlink([tc.link, mfilename() + ".m"], B_read_symlink);
74-
exp = [tc.target, ""];
75-
tc.verifyClass(r, 'string')
76-
tc.verifyEqual(r, exp, "failed to detect own link")
77-
end
78-
79-
8067
function test_create_symlink(tc, B_create_symlink)
8168
tc.applyFixture(matlab.unittest.fixtures.SuppressedWarningsFixture(["MATLAB:io:filesystem:symlink:TargetNotFound","MATLAB:io:filesystem:symlink:FileExists"]))
8269

0 commit comments

Comments
 (0)