Skip to content

Commit b3105cd

Browse files
committed
SLazy<T> improvements
1 parent 6274c3e commit b3105cd

File tree

4 files changed

+107
-115
lines changed

4 files changed

+107
-115
lines changed

Sources/Towel/SLazy.cs

Lines changed: 53 additions & 61 deletions
Original file line numberDiff line numberDiff line change
@@ -10,17 +10,67 @@ internal class Reference
1010
{
1111
internal Func<T>? _func;
1212
internal T? _value;
13+
1314
internal Reference(Func<T> func) => _func = func;
15+
16+
internal T SafeGetValue()
17+
{
18+
if (_func is not null)
19+
{
20+
lock (this)
21+
{
22+
if (_func is not null)
23+
{
24+
try
25+
{
26+
T value = _func();
27+
_value = value;
28+
_func = null;
29+
}
30+
catch (Exception exception)
31+
{
32+
_func = () => throw exception;
33+
throw;
34+
}
35+
}
36+
}
37+
}
38+
return _value!;
39+
}
1440
}
1541

1642
internal Reference? _reference;
1743
internal T? _value;
1844

1945
/// <summary>True if <see cref="Value"/> has been initialized.</summary>
20-
public bool IsValueCreated => _reference is null ? true : GetIsValueCreated();
46+
public bool IsValueCreated
47+
{
48+
get
49+
{
50+
Reference? reference = _reference;
51+
if (reference is not null && reference._func is null)
52+
{
53+
_value = reference._value;
54+
_reference = null;
55+
return true;
56+
}
57+
return reference is null;
58+
}
59+
}
2160

2261
/// <summary>Gets the lazily initialized value.</summary>
23-
public T Value => _reference is null ? _value! : GetValue();
62+
public T Value
63+
{
64+
get
65+
{
66+
if (_reference is not null)
67+
{
68+
_value = _reference.SafeGetValue();
69+
_reference = null;
70+
}
71+
return _value!;
72+
}
73+
}
2474

2575
/// <summary>Constructs a new <see cref="SLazy{T}"/> from a <typeparamref name="T"/>.</summary>
2676
/// <param name="value">The value to initialize <see cref="Value"/> with.</param>
@@ -36,66 +86,8 @@ public SLazy(T value)
3686
public SLazy(Func<T> func)
3787
{
3888
if (func is null) throw new ArgumentNullException(nameof(func));
39-
_reference = new(func);
4089
_value = default;
41-
}
42-
43-
internal bool GetIsValueCreated()
44-
{
45-
Reference? reference = _reference;
46-
if (reference is not null)
47-
{
48-
if (reference._func is null)
49-
{
50-
_value = reference._value;
51-
_reference = null;
52-
return true;
53-
}
54-
}
55-
return false;
56-
}
57-
58-
internal T GetValue()
59-
{
60-
Reference? reference = _reference;
61-
if (reference is not null)
62-
{
63-
if (reference._func is not null)
64-
{
65-
lock (reference)
66-
{
67-
if (_reference is not null)
68-
{
69-
if (reference._func is null)
70-
{
71-
_value = reference._value;
72-
}
73-
else
74-
{
75-
try
76-
{
77-
T value = reference._func.Invoke();
78-
reference._value = value;
79-
reference._func = null;
80-
_value = value;
81-
}
82-
catch (Exception exception)
83-
{
84-
reference._func = () => throw exception;
85-
throw;
86-
}
87-
}
88-
_reference = null;
89-
}
90-
}
91-
}
92-
else
93-
{
94-
_value = reference._value;
95-
_reference = null;
96-
}
97-
}
98-
return _value!;
90+
_reference = new(func);
9991
}
10092

10193
/// <summary>Constructs a new <see cref="SLazy{T}"/> from a <see cref="Func{T}"/>.</summary>

Tools/docfx_project/benchmarks/SLazyCachingBenchmarks.md

Lines changed: 17 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -14,21 +14,21 @@ Intel Core i7-4790K CPU 4.00GHz (Haswell), 1 CPU, 8 logical and 4 physical cores
1414

1515

1616
```
17-
| Method | N | Mean | Error | StdDev | Ratio | RatioSD |
18-
|---------------------------- |----- |----------:|----------:|----------:|------:|--------:|
19-
| **Lazy** | **1** | **33.33 ns** | **0.691 ns** | **1.076 ns** | **1.00** | **0.00** |
20-
| LazyExecutionAndPublication | 1 | 32.84 ns | 0.662 ns | 0.680 ns | 0.98 | 0.03 |
21-
| SLazy | 1 | 25.77 ns | 0.264 ns | 0.247 ns | 0.77 | 0.02 |
22-
| | | | | | | |
23-
| **Lazy** | **10** | **38.30 ns** | **0.327 ns** | **0.306 ns** | **1.00** | **0.00** |
24-
| LazyExecutionAndPublication | 10 | 38.25 ns | 0.550 ns | 0.487 ns | 1.00 | 0.02 |
25-
| SLazy | 10 | 30.19 ns | 0.213 ns | 0.188 ns | 0.79 | 0.01 |
26-
| | | | | | | |
27-
| **Lazy** | **100** | **95.82 ns** | **1.104 ns** | **1.032 ns** | **1.00** | **0.00** |
28-
| LazyExecutionAndPublication | 100 | 96.57 ns | 0.873 ns | 0.774 ns | 1.01 | 0.02 |
29-
| SLazy | 100 | 85.34 ns | 0.895 ns | 0.793 ns | 0.89 | 0.01 |
30-
| | | | | | | |
31-
| **Lazy** | **1000** | **563.30 ns** | **4.441 ns** | **4.154 ns** | **1.00** | **0.00** |
32-
| LazyExecutionAndPublication | 1000 | 572.02 ns | 11.437 ns | 15.269 ns | 1.02 | 0.03 |
33-
| SLazy | 1000 | 551.57 ns | 3.831 ns | 3.583 ns | 0.98 | 0.01 |
17+
| Method | N | Mean | Error | StdDev | Median | Ratio | RatioSD |
18+
|---------------------------- |----- |----------:|---------:|---------:|----------:|------:|--------:|
19+
| **Lazy** | **1** | **32.33 ns** | **0.674 ns** | **1.422 ns** | **32.05 ns** | **1.00** | **0.00** |
20+
| LazyExecutionAndPublication | 1 | 30.87 ns | 0.498 ns | 0.511 ns | 30.87 ns | 0.98 | 0.05 |
21+
| SLazy | 1 | 25.03 ns | 0.524 ns | 0.514 ns | 24.86 ns | 0.79 | 0.03 |
22+
| | | | | | | | |
23+
| **Lazy** | **10** | **35.87 ns** | **0.157 ns** | **0.139 ns** | **35.83 ns** | **1.00** | **0.00** |
24+
| LazyExecutionAndPublication | 10 | 36.09 ns | 0.699 ns | 0.748 ns | 35.84 ns | 1.01 | 0.02 |
25+
| SLazy | 10 | 29.76 ns | 0.624 ns | 0.694 ns | 29.85 ns | 0.83 | 0.02 |
26+
| | | | | | | | |
27+
| **Lazy** | **100** | **95.12 ns** | **2.716 ns** | **7.661 ns** | **91.62 ns** | **1.00** | **0.00** |
28+
| LazyExecutionAndPublication | 100 | 92.24 ns | 1.494 ns | 1.397 ns | 91.86 ns | 0.94 | 0.09 |
29+
| SLazy | 100 | 81.92 ns | 1.615 ns | 1.795 ns | 82.14 ns | 0.82 | 0.08 |
30+
| | | | | | | | |
31+
| **Lazy** | **1000** | **534.87 ns** | **7.279 ns** | **6.452 ns** | **532.73 ns** | **1.00** | **0.00** |
32+
| LazyExecutionAndPublication | 1000 | 534.40 ns | 3.536 ns | 3.308 ns | 533.46 ns | 1.00 | 0.01 |
33+
| SLazy | 1000 | 520.42 ns | 2.383 ns | 2.229 ns | 520.21 ns | 0.97 | 0.01 |
3434

Tools/docfx_project/benchmarks/SLazyConstructionBenchmarks.md

Lines changed: 21 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -14,25 +14,25 @@ Intel Core i7-4790K CPU 4.00GHz (Haswell), 1 CPU, 8 logical and 4 physical cores
1414

1515

1616
```
17-
| Method | N | Mean | Error | StdDev | Median | Ratio | RatioSD | Gen 0 | Gen 1 | Gen 2 | Allocated |
18-
|---------------------------- |------ |--------------:|-------------:|-------------:|--------------:|------:|--------:|---------:|------:|------:|------------:|
19-
| **Lazy** | **1** | **22.20 ns** | **0.147 ns** | **0.130 ns** | **22.23 ns** | **1.00** | **0.00** | **0.0382** | **-** | **-** | **160 B** |
20-
| LazyExecutionAndPublication | 1 | 22.13 ns | 0.078 ns | 0.070 ns | 22.13 ns | 1.00 | 0.01 | 0.0382 | - | - | 160 B |
21-
| SLazy | 1 | 15.54 ns | 0.116 ns | 0.097 ns | 15.53 ns | 0.70 | 0.01 | 0.0287 | - | - | 120 B |
22-
| | | | | | | | | | | | |
23-
| **Lazy** | **10** | **208.97 ns** | **4.112 ns** | **8.116 ns** | **204.83 ns** | **1.00** | **0.00** | **0.3309** | **-** | **-** | **1,384 B** |
24-
| LazyExecutionAndPublication | 10 | 201.07 ns | 1.125 ns | 0.997 ns | 200.83 ns | 0.96 | 0.04 | 0.3309 | - | - | 1,384 B |
25-
| SLazy | 10 | 142.71 ns | 0.798 ns | 0.707 ns | 142.77 ns | 0.68 | 0.03 | 0.2351 | - | - | 984 B |
26-
| | | | | | | | | | | | |
27-
| **Lazy** | **100** | **1,973.65 ns** | **38.768 ns** | **80.063 ns** | **1,932.24 ns** | **1.00** | **0.00** | **3.2539** | **-** | **-** | **13,624 B** |
28-
| LazyExecutionAndPublication | 100 | 1,960.29 ns | 14.341 ns | 11.976 ns | 1,953.84 ns | 0.95 | 0.03 | 3.2578 | - | - | 13,624 B |
29-
| SLazy | 100 | 1,406.01 ns | 27.404 ns | 45.786 ns | 1,399.79 ns | 0.71 | 0.04 | 2.3003 | - | - | 9,624 B |
30-
| | | | | | | | | | | | |
31-
| **Lazy** | **1000** | **19,776.75 ns** | **391.643 ns** | **621.187 ns** | **19,699.88 ns** | **1.00** | **0.00** | **32.5012** | **-** | **-** | **136,024 B** |
32-
| LazyExecutionAndPublication | 1000 | 19,512.20 ns | 387.086 ns | 489.540 ns | 19,246.26 ns | 0.99 | 0.04 | 32.5012 | - | - | 136,024 B |
33-
| SLazy | 1000 | 12,911.30 ns | 249.429 ns | 503.859 ns | 12,677.52 ns | 0.66 | 0.04 | 22.9492 | - | - | 96,024 B |
34-
| | | | | | | | | | | | |
35-
| **Lazy** | **10000** | **191,085.52 ns** | **1,097.719 ns** | **973.099 ns** | **190,886.58 ns** | **1.00** | **0.00** | **325.1953** | **-** | **-** | **1,360,024 B** |
36-
| LazyExecutionAndPublication | 10000 | 193,555.10 ns | 514.903 ns | 456.448 ns | 193,557.75 ns | 1.01 | 0.01 | 325.1953 | - | - | 1,360,024 B |
37-
| SLazy | 10000 | 128,945.22 ns | 2,566.185 ns | 5,005.146 ns | 126,364.55 ns | 0.68 | 0.03 | 229.4922 | - | - | 960,024 B |
17+
| Method | N | Mean | Error | StdDev | Median | Ratio | RatioSD | Gen 0 | Gen 1 | Gen 2 | Allocated |
18+
|---------------------------- |------ |--------------:|-------------:|--------------:|--------------:|------:|--------:|---------:|------:|------:|------------:|
19+
| **Lazy** | **1** | **23.49 ns** | **0.075 ns** | **0.066 ns** | **23.48 ns** | **1.00** | **0.00** | **0.0382** | **-** | **-** | **160 B** |
20+
| LazyExecutionAndPublication | 1 | 21.54 ns | 0.143 ns | 0.127 ns | 21.55 ns | 0.92 | 0.01 | 0.0382 | - | - | 160 B |
21+
| SLazy | 1 | 16.10 ns | 0.263 ns | 0.246 ns | 15.99 ns | 0.69 | 0.01 | 0.0287 | - | - | 120 B |
22+
| | | | | | | | | | | | |
23+
| **Lazy** | **10** | **195.37 ns** | **1.385 ns** | **1.295 ns** | **195.02 ns** | **1.00** | **0.00** | **0.3309** | **-** | **-** | **1,384 B** |
24+
| LazyExecutionAndPublication | 10 | 207.25 ns | 4.024 ns | 6.264 ns | 206.40 ns | 1.07 | 0.03 | 0.3309 | - | - | 1,384 B |
25+
| SLazy | 10 | 147.05 ns | 1.701 ns | 1.420 ns | 147.27 ns | 0.75 | 0.01 | 0.2351 | - | - | 984 B |
26+
| | | | | | | | | | | | |
27+
| **Lazy** | **100** | **1,890.13 ns** | **28.512 ns** | **23.809 ns** | **1,881.19 ns** | **1.00** | **0.00** | **3.2558** | **-** | **-** | **13,624 B** |
28+
| LazyExecutionAndPublication | 100 | 1,996.97 ns | 38.941 ns | 41.666 ns | 1,978.26 ns | 1.06 | 0.03 | 3.2539 | - | - | 13,624 B |
29+
| SLazy | 100 | 1,339.82 ns | 25.846 ns | 26.542 ns | 1,336.61 ns | 0.71 | 0.02 | 2.3003 | - | - | 9,624 B |
30+
| | | | | | | | | | | | |
31+
| **Lazy** | **1000** | **19,320.80 ns** | **381.224 ns** | **423.730 ns** | **19,347.76 ns** | **1.00** | **0.00** | **32.5012** | **-** | **-** | **136,024 B** |
32+
| LazyExecutionAndPublication | 1000 | 19,640.55 ns | 347.447 ns | 325.002 ns | 19,690.26 ns | 1.01 | 0.03 | 32.5012 | - | - | 136,024 B |
33+
| SLazy | 1000 | 13,186.66 ns | 209.667 ns | 185.865 ns | 13,151.21 ns | 0.68 | 0.02 | 22.9492 | - | - | 96,024 B |
34+
| | | | | | | | | | | | |
35+
| **Lazy** | **10000** | **213,004.25 ns** | **9,668.635 ns** | **27,741.126 ns** | **198,535.77 ns** | **1.00** | **0.00** | **325.1953** | **-** | **-** | **1,360,024 B** |
36+
| LazyExecutionAndPublication | 10000 | 192,453.36 ns | 3,600.379 ns | 3,367.797 ns | 190,729.71 ns | 0.92 | 0.10 | 325.1953 | - | - | 1,360,024 B |
37+
| SLazy | 10000 | 129,510.58 ns | 2,045.435 ns | 2,799.815 ns | 128,340.17 ns | 0.60 | 0.07 | 229.4922 | - | - | 960,024 B |
3838

Tools/docfx_project/benchmarks/SLazyInitializationBenchmarks.md

Lines changed: 16 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -10,30 +10,30 @@ BenchmarkDotNet=v0.13.0, OS=Windows 10.0.19042.1110 (20H2/October2020Update)
1010
Intel Core i7-4790K CPU 4.00GHz (Haswell), 1 CPU, 8 logical and 4 physical cores
1111
.NET SDK=6.0.100-preview.6.21355.2
1212
[Host] : .NET 5.0.8 (5.0.821.31504), X64 RyuJIT
13-
Job-PABSZC : .NET 5.0.8 (5.0.821.31504), X64 RyuJIT
13+
Job-BJDLWC : .NET 5.0.8 (5.0.821.31504), X64 RyuJIT
1414

1515
InvocationCount=1 UnrollFactor=1
1616

1717
```
1818
| Method | N | Mean | Error | StdDev | Median | Ratio | RatioSD |
1919
|---------------------------- |------ |-------------:|-------------:|-------------:|-------------:|------:|--------:|
20-
| **Lazy** | **1** | **442.7 ns** | **20.58 ns** | **59.37 ns** | **400.0 ns** | **1.00** | **0.00** |
21-
| LazyExecutionAndPublication | 1 | 400.0 ns | 0.00 ns | 0.00 ns | 400.0 ns | 0.87 | 0.12 |
22-
| SLazy | 1 | 300.0 ns | 0.00 ns | 0.00 ns | 300.0 ns | 0.66 | 0.09 |
20+
| **Lazy** | **1** | **350.5 ns** | **23.02 ns** | **65.31 ns** | **300.0 ns** | **1.00** | **0.00** |
21+
| LazyExecutionAndPublication | 1 | 389.0 ns | 11.22 ns | 31.45 ns | 400.0 ns | 1.14 | 0.21 |
22+
| SLazy | 1 | 300.0 ns | 0.00 ns | 0.00 ns | 300.0 ns | 0.78 | 0.14 |
2323
| | | | | | | | |
24-
| **Lazy** | **10** | **689.8 ns** | **15.31 ns** | **30.58 ns** | **700.0 ns** | **1.00** | **0.00** |
25-
| LazyExecutionAndPublication | 10 | 661.7 ns | 20.63 ns | 58.85 ns | 700.0 ns | 0.96 | 0.10 |
26-
| SLazy | 10 | 474.4 ns | 17.03 ns | 43.95 ns | 500.0 ns | 0.70 | 0.07 |
24+
| **Lazy** | **10** | **665.7 ns** | **18.97 ns** | **55.63 ns** | **700.0 ns** | **1.00** | **0.00** |
25+
| LazyExecutionAndPublication | 10 | 654.9 ns | 21.44 ns | 60.12 ns | 700.0 ns | 0.99 | 0.12 |
26+
| SLazy | 10 | 476.9 ns | 21.32 ns | 59.77 ns | 500.0 ns | 0.72 | 0.11 |
2727
| | | | | | | | |
28-
| **Lazy** | **100** | **2,929.4 ns** | **57.25 ns** | **58.79 ns** | **2,900.0 ns** | **1.00** | **0.00** |
29-
| LazyExecutionAndPublication | 100 | 2,941.2 ns | 60.21 ns | 61.83 ns | 2,900.0 ns | 1.00 | 0.03 |
30-
| SLazy | 100 | 2,338.9 ns | 46.88 ns | 50.16 ns | 2,300.0 ns | 0.80 | 0.02 |
28+
| **Lazy** | **100** | **2,926.3 ns** | **58.78 ns** | **65.34 ns** | **2,900.0 ns** | **1.00** | **0.00** |
29+
| LazyExecutionAndPublication | 100 | 2,868.2 ns | 58.32 ns | 71.62 ns | 2,900.0 ns | 0.98 | 0.03 |
30+
| SLazy | 100 | 2,268.2 ns | 38.82 ns | 47.67 ns | 2,300.0 ns | 0.78 | 0.02 |
3131
| | | | | | | | |
32-
| **Lazy** | **1000** | **25,378.6 ns** | **391.22 ns** | **346.81 ns** | **25,200.0 ns** | **1.00** | **0.00** |
33-
| LazyExecutionAndPublication | 1000 | 25,107.7 ns | 424.70 ns | 354.64 ns | 24,900.0 ns | 0.99 | 0.02 |
34-
| SLazy | 1000 | 20,475.0 ns | 57.93 ns | 45.23 ns | 20,500.0 ns | 0.81 | 0.01 |
32+
| **Lazy** | **1000** | **25,041.7 ns** | **85.63 ns** | **66.86 ns** | **25,050.0 ns** | **1.00** | **0.00** |
33+
| LazyExecutionAndPublication | 1000 | 25,133.3 ns | 406.26 ns | 317.18 ns | 25,150.0 ns | 1.00 | 0.01 |
34+
| SLazy | 1000 | 19,976.9 ns | 263.97 ns | 220.43 ns | 19,900.0 ns | 0.80 | 0.01 |
3535
| | | | | | | | |
36-
| **Lazy** | **10000** | **224,441.9 ns** | **11,506.62 ns** | **32,642.35 ns** | **215,300.0 ns** | **1.00** | **0.00** |
37-
| LazyExecutionAndPublication | 10000 | 234,046.4 ns | 13,531.38 ns | 39,257.00 ns | 222,500.0 ns | 1.07 | 0.20 |
38-
| SLazy | 10000 | 207,803.3 ns | 8,491.96 ns | 23,951.73 ns | 204,700.0 ns | 0.94 | 0.14 |
36+
| **Lazy** | **10000** | **218,455.6 ns** | **11,333.33 ns** | **33,238.69 ns** | **201,200.0 ns** | **1.00** | **0.00** |
37+
| LazyExecutionAndPublication | 10000 | 242,215.4 ns | 3,729.99 ns | 3,114.71 ns | 243,200.0 ns | 0.96 | 0.09 |
38+
| SLazy | 10000 | 187,578.5 ns | 4,858.01 ns | 13,781.37 ns | 185,700.0 ns | 0.88 | 0.13 |
3939

0 commit comments

Comments
 (0)