Skip to content

Commit 6c83dde

Browse files
Merge pull request #93 from LilithHafner/patch-1
Remove dynamic dispatch from (General)LazyBufferCache
2 parents 0b194df + 8a0064d commit 6c83dde

File tree

3 files changed

+12
-19
lines changed

3 files changed

+12
-19
lines changed

README.md

Lines changed: 4 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -218,12 +218,9 @@ A `LazyBufferCache` is a `Dict`-like type for the caches which automatically def
218218
new cache arrays on demand when they are required. The function `f` maps
219219
`size_of_cache = f(size(u))`, which by default creates cache arrays of the same size.
220220

221-
Note that `LazyBufferCache` does cause a dynamic dispatch, though it is type-stable.
222-
This gives it a ~100ns overhead, and thus on very small problems it can reduce
223-
performance, but for any sufficiently sized calculation (e.g. >20 ODEs) this
224-
may not be even measurable. The upside of `LazyBufferCache` is that the user does
225-
not have to worry about potential issues with chunk sizes and such: `LazyBufferCache`
226-
is much easier!
221+
Note that `LazyBufferCache` is type-stable and contains no dynamic dispatch. This gives
222+
it a ~15ns overhead. The upside of `LazyBufferCache` is that the user does not have to
223+
worry about potential issues with chunk sizes and such: `LazyBufferCache` is much easier!
227224

228225
### Example
229226

@@ -250,7 +247,7 @@ new caches on demand when they are required. The function `f` generates the cach
250247
for the type of `u`, and subsequent indexing reuses that cache if that type of `u` has
251248
already ben seen.
252249

253-
Note that `LazyBufferCache` does cause a dynamic dispatch and its return is not type-inferred.
250+
Note that `GeneralLazyBufferCache`'s return is not type-inferred.
254251
This means it's the slowest of the preallocation methods, but it's the most general.
255252

256253
### Example

docs/src/index.md

Lines changed: 5 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -208,12 +208,9 @@ A `LazyBufferCache` is a `Dict`-like type for the caches, which automatically de
208208
new cache arrays on demand when they are required. The function `f` maps
209209
`size_of_cache = f(size(u))`, which by default creates cache arrays of the same size.
210210

211-
Note that `LazyBufferCache` does cause a dynamic dispatch, though it is type-stable.
212-
This gives it a ~100ns overhead, and thus on very small problems it can reduce
213-
performance, but for any sufficiently sized calculation (e.g. >20 ODEs) this
214-
may not be even measurable. The upside of `LazyBufferCache` is that the user does
215-
not have to worry about potential issues with chunk sizes and such: `LazyBufferCache`
216-
is much easier!
211+
Note that `LazyBufferCache` is type-stable and contains no dynamic dispatch. This gives
212+
it a ~15ns overhead. The upside of `LazyBufferCache` is that the user does not have to
213+
worry about potential issues with chunk sizes and such: `LazyBufferCache` is much easier!
217214

218215
### Example
219216

@@ -245,7 +242,7 @@ new caches on demand when they are required. The function `f` generates the cach
245242
for the type of `u`, and subsequent indexing reuses that cache if that type of `u` has
246243
already been seen.
247244

248-
Note that `LazyBufferCache` does cause a dynamic dispatch and its return is not type-inferred.
245+
Note that `GeneralLazyBufferCache`'s return is not type-inferred.
249246
This means it's the slowest of the preallocation methods, but it's the most general.
250247

251248
### Example
@@ -319,7 +316,7 @@ tries to do this with a bump allocator.
319316

320317
- See the [SciML Style Guide](https://github.com/SciML/SciMLStyle) for common coding practices and other style decisions.
321318
- There are a few community forums:
322-
319+
323320
+ The #diffeq-bridged and #sciml-bridged channels in the
324321
[Julia Slack](https://julialang.org/slack/)
325322
+ The #diffeq-bridged and #sciml-bridged channels in the

src/PreallocationTools.jl

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -204,18 +204,17 @@ same type and size `f(size(u))` (defaulting to the same size), which is allocate
204204
needed and then cached within `b` for subsequent usage.
205205
"""
206206
struct LazyBufferCache{F <: Function}
207-
bufs::Dict # a dictionary mapping types to buffers
207+
bufs::Dict{Any, Any} # a dictionary mapping (type, size) pairs to buffers
208208
sizemap::F
209209
LazyBufferCache(f::F = identity) where {F <: Function} = new{F}(Dict(), f) # start with empty dict
210210
end
211211

212212
# override the [] method
213213
function Base.getindex(b::LazyBufferCache, u::T) where {T <: AbstractArray}
214214
s = b.sizemap(size(u)) # required buffer size
215-
buf = get!(b.bufs, (T, s)) do
215+
get!(b.bufs, (T, s)) do
216216
similar(u, s) # buffer to allocate if it was not found in b.bufs
217217
end::T # declare type since b.bufs dictionary is untyped
218-
return buf
219218
end
220219

221220
# GeneralLazyBufferCache
@@ -235,7 +234,7 @@ correct using things like function barriers, then this is a general technique th
235234
is sufficiently fast.
236235
"""
237236
struct GeneralLazyBufferCache{F <: Function}
238-
bufs::Dict # a dictionary mapping types to buffers
237+
bufs::Dict{Any, Any} # a dictionary mapping types to buffers
239238
f::F
240239
GeneralLazyBufferCache(f::F = identity) where {F <: Function} = new{F}(Dict(), f) # start with empty dict
241240
end

0 commit comments

Comments
 (0)