Created
November 30, 2020 02:09
-
-
Save dralletje/cab0ef927e8928150583e2ad631fd082 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
### A Pluto.jl notebook ### | |
# v0.12.15 | |
using Markdown | |
using InteractiveUtils | |
# ╔═╡ d07a2949-f621-4714-9edf-33660d83ee0a | |
md""" | |
# Experiments with Garbage Collection | |
I create a variable, either an array wrapped in an MemoryHog (for clarity) or a module. Then I do some things with it (define it in local scope, global scope, putting it inside a module) and then the status message at the top tells me if **after this cell is done running**, the variable is GC'ed or not. | |
""" | |
# ╔═╡ 6703fcad-3748-4c8a-9dc0-d0b8a65d5ad1 | |
md"### Local definition" | |
# ╔═╡ a17357a7-eee7-4f94-aa05-93f0a3449642 | |
md"#### Simple, just defined and track it" | |
# ╔═╡ 6680f2a2-27a0-418c-b892-f3c75da6aed9 | |
md"#### Also define a function that uses it, and expose that" | |
# ╔═╡ ddf6ebb7-0e4a-4f3c-80e7-e5d957811873 | |
md"#### Same function, just local this time" | |
# ╔═╡ 8f180aeb-80d5-49a5-9533-45e49daba447 | |
md""" | |
### Global definition | |
Looking at the current allocation status doesn't make sense here: we put the variable in the global scope, so obviously it needs to be available for other cells still. | |
Re-run the `global_allocation` cell repeatedly to see the status of | |
previous values update. There should be "1 out of X not finalized", which is the current one. | |
""" | |
# ╔═╡ 32e6e8d0-be99-4f9b-9102-be6f43f53c1c | |
tracked_memory_hog = [] | |
# ╔═╡ b6a7aad1-72e6-4e40-a0d0-94d3a6ab9093 | |
md"#### GC'ing a module" | |
# ╔═╡ 4d43b24c-e63f-4500-abea-d7d247be1a63 | |
md"#### GC'ing a module with struct or function" | |
# ╔═╡ 2335237e-103c-4e30-aae1-42bc65e016bf | |
md"#### Injected into a new, local, module" | |
# ╔═╡ bedb3e48-f827-47a2-87be-445ba0543efa | |
md"#### GC'ing a 'real' module" | |
# ╔═╡ aaca5e61-ccd1-4653-ad07-9db5762d787d | |
md"#### Inside module with function inside" | |
# ╔═╡ 84a0fdb2-6523-4cc8-be9b-334beb3ddfca | |
md""" | |
#### Imported into module, deleted in original module | |
(This is what Pluto does) | |
""" | |
# ╔═╡ 022f2b42-bcd7-4cb5-9f88-08be483dfd50 | |
md"#### Inside a module with a const" | |
# ╔═╡ 4eb741b5-0d10-4385-bf31-32909b2f263a | |
md"#### Defined in new module, but also deleted" | |
# ╔═╡ c6e8c5e1-f441-4569-aab3-d958389f1d19 | |
md"#### Defined in a module that gets 'replaced'" | |
# ╔═╡ 6c10d6ec-2554-4d5f-9319-ff678c4acdec | |
md""" | |
#### Weird contraption with extension to Base | |
Don't do this. | |
(change `include_memory_hog_in_result` for Julia magic) | |
""" | |
# ╔═╡ e61ac897-1872-4a05-8ef3-f30f95db9178 | |
struct UselessStruct end | |
# ╔═╡ 181ebdb1-3789-4bf5-b67a-e73298d55fa7 | |
include_memory_hog_in_result = false | |
# ╔═╡ d6e32657-3ed9-4845-bda8-0ee58bb4dcf0 | |
base_extension_trackers = [] | |
# ╔═╡ 294467a8-20dc-4dcd-8f93-89b3dc548ce9 | |
md"## Appendix" | |
# ╔═╡ 442c27aa-9a34-4b33-b228-d473823e0e76 | |
md"**Bytes**" | |
# ╔═╡ 47b9494a-1d84-4b7e-adb1-40e2e04a79e2 | |
struct Bytes | |
value | |
end | |
# ╔═╡ 491310d3-dfe3-41a8-927c-446886c6913c | |
function Base.show(io::IO, ::MIME"text/plain", bytes::Bytes) | |
amount, unit = if bytes.value > 1e9 | |
(bytes.value / 1e9, "gb") | |
elseif bytes.value > 1e6 | |
(bytes.value / 1e6, "mb") | |
elseif bytes.value > 1e3 | |
(bytes.value / 1e3, "kb") | |
else | |
(bytes.value, "b") | |
end | |
print(io, "$(round(amount, digits=2))$(unit)") | |
end | |
# ╔═╡ 878aa1d1-39d2-434d-8af8-08ed2e0c6d4b | |
md"**Finalization helper**" | |
# ╔═╡ 5f26becf-b856-49c5-ae31-bf48fe76ee72 | |
Base.@kwdef mutable struct FinalizeTracker | |
is_finalized::Bool = false | |
end | |
# ╔═╡ f23464a2-9844-448b-a60e-dbc542ddc2a3 | |
function track_finalize(@nospecialize(object)) | |
tracker = FinalizeTracker() | |
# ref = Ref(false) | |
finalizer(object) do x | |
tracker.is_finalized = true | |
# ref[] = true | |
end | |
tracker | |
# ref | |
end | |
# ╔═╡ 532b773e-2bee-4899-a6b6-03296422b71d | |
module_definition_plus = begin | |
local module_definition_module = Module(:MemoryHogModule) | |
Core.eval(module_definition_module, quote function X() nothing end end) | |
# Core.eval(module_definition_module, quote struct X nothing end end) | |
track_finalize(module_definition_module) | |
end | |
# ╔═╡ ad41c1c9-436e-4c35-ae11-363f081a3ae2 | |
module_definition_real = begin | |
local module_definition_module = Core.eval(Main, :(module MemoryHogModule end)) | |
# Try replacing it even | |
Core.eval(Main, :(module MemoryHogModule end)) | |
track_finalize(module_definition_module) | |
end | |
# ╔═╡ c4af3d7c-920e-4e86-b58e-50de840fa108 | |
function status_message(color, message) | |
HTML(""" | |
<div style=" | |
display: flex; | |
flex-direction: row; | |
align-items: center; | |
padding: 4px; | |
"> | |
<div style=" | |
width: 16px; | |
height: 16px; | |
border-radius: 8px; | |
background-color: $(color); | |
"></div> | |
<div style="width: 8px"></div> | |
<div>$(message)</div> | |
</div> | |
""") | |
end | |
# ╔═╡ f1b31e9f-7f8a-4ac9-8cb3-88fe1e25cd46 | |
function force_gc(tracker::FinalizeTracker) | |
if tracker.is_finalized | |
status_message("black", "Already finalized?!") | |
else | |
GC.gc(false) | |
if tracker.is_finalized | |
status_message("green", "Finalized after shallow GC") | |
else | |
GC.gc(true) | |
if tracker.is_finalized | |
status_message("lightgreen", "Finalized after deep GC") | |
else | |
status_message("red", "Not finalized after GC") | |
end | |
end | |
end | |
end | |
# ╔═╡ 153bd296-6b7f-49e7-9911-8311e33aa793 | |
force_gc(module_definition_plus) | |
# ╔═╡ 42247aa2-29d8-49df-81fc-a22230b0f170 | |
force_gc(module_definition_real) | |
# ╔═╡ 58cc3ce8-1fb2-4bda-8d83-5cb32dafad8d | |
Base.@kwdef mutable struct MemoryHog | |
value = zeros(10, 10, 10) | |
end | |
# ╔═╡ 21d5544d-ed06-4bfc-87c7-0a64e9a77802 | |
local_allocation = begin | |
local memory_hog = MemoryHog() | |
track_finalize(memory_hog) | |
end | |
# ╔═╡ 7c8d062b-54b5-46a8-9a67-7e8c0f3070bc | |
force_gc(local_allocation) | |
# ╔═╡ 4fc8797c-3d15-4a89-989f-4bc0d2107b05 | |
local_allocation_with_closure = begin | |
local memory_hog = MemoryHog() | |
fn = () -> memory_hog | |
track_finalize(memory_hog) | |
end | |
# ╔═╡ fb7aac8d-703d-4b30-8c36-bfd019966efe | |
force_gc(local_allocation_with_closure) | |
# ╔═╡ 72ba1f46-0e0d-4853-9dd9-d9306a84b079 | |
local_allocation_with_local_closure = begin | |
local memory_hog = MemoryHog() | |
track_finalize(memory_hog) | |
end | |
# ╔═╡ 925d61f4-3087-4dc0-a4a3-ddfd8ee6ce6e | |
force_gc(local_allocation_with_local_closure) | |
# ╔═╡ d36cc63b-25ac-47e4-b1d7-64961e43a89b | |
global_allocation = begin | |
# @__MODULE__ # Uncomment this to try the non-fast-tracked version | |
memory_hog = MemoryHog() | |
local tracking = track_finalize(memory_hog) | |
# Even though functions can't be finalized, | |
# they sure are being dereferences (and thus memory_hog) | |
fn2 = () -> memory_hog | |
# push!(cached_modules, @__MODULE__) | |
push!(tracked_memory_hog, tracking) | |
tracking | |
end | |
# ╔═╡ 26433879-4009-41b7-a04c-a748b04f8752 | |
global_allocation; begin | |
force_gc(global_allocation); | |
local finalized = length(filter(tracked_memory_hog) do tracker | |
tracker.is_finalized | |
end) | |
local not_finalized = length(filter(tracked_memory_hog) do tracker | |
!tracker.is_finalized | |
end) | |
Text("$(not_finalized) out of $(not_finalized + finalized) not finalized") | |
end | |
# ╔═╡ 2942b097-9962-4840-9570-438d15b9775b | |
module_definition = begin | |
local memory_hog = MemoryHog(Module(:MemoryHogModule)) | |
track_finalize(memory_hog) | |
end | |
# ╔═╡ 788e9fcc-ed6e-4bbc-a706-6500df81ff7f | |
force_gc(module_definition) | |
# ╔═╡ d3f38b6b-5614-46fe-93ca-c084c389469d | |
new_module_definition = begin | |
local memory_hog = MemoryHog() | |
local m = Module(:MemoryHogModule) | |
Core.eval(m, quote inner_memory_hog = $(memory_hog) end) | |
track_finalize(memory_hog) | |
end | |
# ╔═╡ d49e7cc7-3903-4bef-b457-1e2ca1543642 | |
force_gc(new_module_definition) | |
# ╔═╡ 60042f23-9c6d-490a-8cda-6c6ffbf3a6e8 | |
module_with_function_definition = begin | |
local memory_hog = MemoryHog() | |
local m = Module(:NewModuleDefinition) | |
Core.eval(m, quote inner_memory_hog = $(memory_hog) end) | |
Core.eval(m, quote function() nothing end end) | |
track_finalize(memory_hog) | |
end | |
# ╔═╡ 3539a896-20c8-4d86-98d9-872ee63f41a1 | |
force_gc(module_with_function_definition) | |
# ╔═╡ 9c557295-cfc8-47d1-a88d-ecf42a774046 | |
module_import_module = begin | |
local memory_hog = MemoryHog() | |
local First = Core.eval(Main, :( | |
module First | |
inner_memory_hog = $(memory_hog) | |
end | |
)) | |
local Second = Core.eval(Main, :( | |
module Second | |
First = $(First) | |
import .First: inner_memory_hog | |
end | |
)) | |
Core.eval(First, quote | |
inner_memory_hog = nothing | |
end) | |
track_finalize(memory_hog) | |
end | |
# ╔═╡ cede163c-7a76-4d9b-95ee-fae936550f39 | |
force_gc(module_import_module) | |
# ╔═╡ 433321fe-69d1-4c89-ad3f-61f53b01720e | |
module_with_const_definition = begin | |
local memory_hog = MemoryHog() | |
local m = Module(:NewModuleDefinition) | |
Core.eval(m, quote inner_memory_hog = $(memory_hog) end) | |
Core.eval(m, quote const X = Dict() end) | |
track_finalize(memory_hog) | |
end | |
# ╔═╡ 6651459d-959a-49ea-991f-f3bb8cf32d38 | |
force_gc(module_with_const_definition) | |
# ╔═╡ 1f2cce18-66fb-4e31-a846-90fdb11f15b1 | |
new_module_and_removed_definition = begin | |
local memory_hog = MemoryHog() | |
local m = Module(:NewModuleDefinition) | |
Core.eval(m, quote inner_memory_hog = $(memory_hog) end) | |
Core.eval(m, quote function() nothing end end) | |
Core.eval(m, quote inner_memory_hog = nothing end) | |
track_finalize(memory_hog) | |
end | |
# ╔═╡ 9ee2e44c-39b0-4c80-ad95-e8e14a93d775 | |
force_gc(new_module_and_removed_definition) | |
# ╔═╡ b1aa2274-258c-417d-84c7-851330691db5 | |
real_module_creation = begin | |
local memory_hog = MemoryHog() | |
local m1 = Core.eval(Main, :(module MemoryHogModule inner_memory_hog = $(memory_hog) end)) | |
local m1 = Core.eval(Main, :(module MemoryHogModule end)) | |
track_finalize(memory_hog) | |
end | |
# ╔═╡ cf2c91c7-ab09-4f38-9b23-ffe8bdd2d55d | |
force_gc(real_module_creation) | |
# ╔═╡ 21908ca8-ff1b-48f4-8ffc-fdd22d19a765 | |
reference_in_base_extension = begin | |
local memory_hog = MemoryHog(Module(:ModuleDefinition)) | |
if include_memory_hog_in_result | |
function Base.:+(::UselessStruct, ::UselessStruct) | |
"We are useless" | |
memory_hog | |
end | |
else | |
# It's still in the function, but julia sees it is being useless | |
function Base.:+(::UselessStruct, ::UselessStruct) | |
memory_hog | |
"We are useless" | |
end | |
end | |
push!(base_extension_trackers, track_finalize(memory_hog)) | |
end | |
# ╔═╡ 284c94a5-b1a7-416d-9e03-91f165874b6a | |
reference_in_base_extension; begin | |
GC.gc(true); | |
local finalized = length(filter(base_extension_trackers) do tracker | |
tracker.is_finalized | |
end) | |
local not_finalized = length(filter(base_extension_trackers) do tracker | |
!tracker.is_finalized | |
end) | |
Text("$(not_finalized) out of $(not_finalized + finalized) not finalized") | |
end | |
# ╔═╡ 5c8c0690-5b1b-485b-9abe-7a9daa2f2e98 | |
status_message("red", "Just an example") | |
# ╔═╡ 203c2942-f626-405b-a492-0aa9e8623ae6 | |
status_message("green", "Whatcha looking at?") | |
# ╔═╡ Cell order: | |
# ╟─d07a2949-f621-4714-9edf-33660d83ee0a | |
# ╟─6703fcad-3748-4c8a-9dc0-d0b8a65d5ad1 | |
# ╟─a17357a7-eee7-4f94-aa05-93f0a3449642 | |
# ╟─7c8d062b-54b5-46a8-9a67-7e8c0f3070bc | |
# ╠═21d5544d-ed06-4bfc-87c7-0a64e9a77802 | |
# ╟─6680f2a2-27a0-418c-b892-f3c75da6aed9 | |
# ╟─fb7aac8d-703d-4b30-8c36-bfd019966efe | |
# ╠═4fc8797c-3d15-4a89-989f-4bc0d2107b05 | |
# ╟─ddf6ebb7-0e4a-4f3c-80e7-e5d957811873 | |
# ╟─925d61f4-3087-4dc0-a4a3-ddfd8ee6ce6e | |
# ╠═72ba1f46-0e0d-4853-9dd9-d9306a84b079 | |
# ╟─8f180aeb-80d5-49a5-9533-45e49daba447 | |
# ╟─26433879-4009-41b7-a04c-a748b04f8752 | |
# ╠═d36cc63b-25ac-47e4-b1d7-64961e43a89b | |
# ╟─32e6e8d0-be99-4f9b-9102-be6f43f53c1c | |
# ╟─b6a7aad1-72e6-4e40-a0d0-94d3a6ab9093 | |
# ╟─788e9fcc-ed6e-4bbc-a706-6500df81ff7f | |
# ╠═2942b097-9962-4840-9570-438d15b9775b | |
# ╟─4d43b24c-e63f-4500-abea-d7d247be1a63 | |
# ╟─153bd296-6b7f-49e7-9911-8311e33aa793 | |
# ╠═532b773e-2bee-4899-a6b6-03296422b71d | |
# ╟─2335237e-103c-4e30-aae1-42bc65e016bf | |
# ╟─d49e7cc7-3903-4bef-b457-1e2ca1543642 | |
# ╠═d3f38b6b-5614-46fe-93ca-c084c389469d | |
# ╟─bedb3e48-f827-47a2-87be-445ba0543efa | |
# ╟─42247aa2-29d8-49df-81fc-a22230b0f170 | |
# ╠═ad41c1c9-436e-4c35-ae11-363f081a3ae2 | |
# ╟─aaca5e61-ccd1-4653-ad07-9db5762d787d | |
# ╟─3539a896-20c8-4d86-98d9-872ee63f41a1 | |
# ╠═60042f23-9c6d-490a-8cda-6c6ffbf3a6e8 | |
# ╟─84a0fdb2-6523-4cc8-be9b-334beb3ddfca | |
# ╟─cede163c-7a76-4d9b-95ee-fae936550f39 | |
# ╠═9c557295-cfc8-47d1-a88d-ecf42a774046 | |
# ╟─022f2b42-bcd7-4cb5-9f88-08be483dfd50 | |
# ╟─6651459d-959a-49ea-991f-f3bb8cf32d38 | |
# ╠═433321fe-69d1-4c89-ad3f-61f53b01720e | |
# ╟─4eb741b5-0d10-4385-bf31-32909b2f263a | |
# ╟─9ee2e44c-39b0-4c80-ad95-e8e14a93d775 | |
# ╠═1f2cce18-66fb-4e31-a846-90fdb11f15b1 | |
# ╟─c6e8c5e1-f441-4569-aab3-d958389f1d19 | |
# ╟─cf2c91c7-ab09-4f38-9b23-ffe8bdd2d55d | |
# ╠═b1aa2274-258c-417d-84c7-851330691db5 | |
# ╟─6c10d6ec-2554-4d5f-9319-ff678c4acdec | |
# ╠═e61ac897-1872-4a05-8ef3-f30f95db9178 | |
# ╟─284c94a5-b1a7-416d-9e03-91f165874b6a | |
# ╠═181ebdb1-3789-4bf5-b67a-e73298d55fa7 | |
# ╠═21908ca8-ff1b-48f4-8ffc-fdd22d19a765 | |
# ╟─d6e32657-3ed9-4845-bda8-0ee58bb4dcf0 | |
# ╟─294467a8-20dc-4dcd-8f93-89b3dc548ce9 | |
# ╟─442c27aa-9a34-4b33-b228-d473823e0e76 | |
# ╟─47b9494a-1d84-4b7e-adb1-40e2e04a79e2 | |
# ╟─491310d3-dfe3-41a8-927c-446886c6913c | |
# ╟─878aa1d1-39d2-434d-8af8-08ed2e0c6d4b | |
# ╟─5f26becf-b856-49c5-ae31-bf48fe76ee72 | |
# ╟─f23464a2-9844-448b-a60e-dbc542ddc2a3 | |
# ╟─c4af3d7c-920e-4e86-b58e-50de840fa108 | |
# ╟─f1b31e9f-7f8a-4ac9-8cb3-88fe1e25cd46 | |
# ╠═58cc3ce8-1fb2-4bda-8d83-5cb32dafad8d | |
# ╠═5c8c0690-5b1b-485b-9abe-7a9daa2f2e98 | |
# ╠═203c2942-f626-405b-a492-0aa9e8623ae6 |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment