First try

master
nixo 2020-02-28 09:55:03 +01:00
commit 3dfe01a86e
4 changed files with 304 additions and 0 deletions

146
Manifest.toml Normal file
View File

@ -0,0 +1,146 @@
# This file is machine-generated - editing it directly is not advised
[[Base64]]
uuid = "2a0f44e3-6c83-55bd-87e4-b1978d98bd5f"
[[BinaryProvider]]
deps = ["Libdl", "SHA"]
git-tree-sha1 = "5b08ed6036d9d3f0ee6369410b830f8873d4024c"
uuid = "b99e7846-7c00-51b0-8f62-c81ae34c0232"
version = "0.5.8"
[[CodecZlib]]
deps = ["BinaryProvider", "Libdl", "TranscodingStreams"]
git-tree-sha1 = "05916673a2627dd91b4969ff8ba6941bc85a960e"
uuid = "944b1d66-785c-5afd-91f1-9de20f533193"
version = "0.6.0"
[[DataStructures]]
deps = ["InteractiveUtils", "OrderedCollections"]
git-tree-sha1 = "5a431d46abf2ef2a4d5d00bd0ae61f651cf854c8"
uuid = "864edb3b-99cc-5e75-8d2d-829cb0a9cfe8"
version = "0.17.10"
[[Dates]]
deps = ["Printf"]
uuid = "ade2ca70-3891-5945-98fb-dc099432e06a"
[[Distributed]]
deps = ["Random", "Serialization", "Sockets"]
uuid = "8ba89e20-285c-5b6f-9357-94700520ee1b"
[[FileIO]]
deps = ["Pkg"]
git-tree-sha1 = "2c84c57aced468fa21763c66d3bef33adcd09ec7"
uuid = "5789e2e9-d7fb-5bc7-8068-2c6fae9b9549"
version = "1.2.2"
[[InteractiveUtils]]
deps = ["Markdown"]
uuid = "b77e0a4c-d291-57a0-90e8-8db25a27a240"
[[JLD2]]
deps = ["CodecZlib", "DataStructures", "FileIO", "Mmap", "Pkg", "Printf", "UUIDs"]
git-tree-sha1 = "d6cfa7c24e27d7eaa2290372739c8298257dae16"
uuid = "033835bb-8acc-5ee8-8aae-3f567f8a3819"
version = "0.1.12"
[[JSON2]]
deps = ["Dates", "Parsers", "Test"]
git-tree-sha1 = "6cbbbab27d9411946725f5d5c91e8b8fb5f7d5db"
uuid = "2535ab7d-5cd8-5a07-80ac-9b1792aadce3"
version = "0.3.1"
[[JSON3]]
deps = ["Dates", "Mmap", "Parsers", "StructTypes", "Test", "UUIDs"]
git-tree-sha1 = "68cf28e37c70fd9a161dcaa13dc9e9209b415014"
uuid = "0f8b85d8-7281-11e9-16c2-39a750bddbf1"
version = "1.0.1"
[[LibGit2]]
uuid = "76f85450-5226-5b5a-8eaa-529ad045b433"
[[Libdl]]
uuid = "8f399da3-3557-5675-b5ff-fb832c97cbdb"
[[Logging]]
uuid = "56ddb016-857b-54e1-b83d-db4d58db5568"
[[Markdown]]
deps = ["Base64"]
uuid = "d6f4376e-aef5-505a-96c1-9c027394607a"
[[MemPool]]
deps = ["DataStructures", "Distributed", "Mmap", "Random", "Serialization", "Sockets", "Test"]
git-tree-sha1 = "d52799152697059353a8eac1000d32ba8d92aa25"
uuid = "f9f48841-c794-520a-933b-121f7ba6ed94"
version = "0.2.0"
[[Mmap]]
uuid = "a63ad114-7e13-5084-954f-fe012c677804"
[[MsgPack]]
deps = ["Serialization"]
git-tree-sha1 = "a8cbf066b54d793b9a48c5daa5d586cf2b5bd43d"
uuid = "99f44e22-a591-53d1-9472-aa23ef4bd671"
version = "1.1.0"
[[OrderedCollections]]
deps = ["Random", "Serialization", "Test"]
git-tree-sha1 = "c4c13474d23c60d20a67b217f1d7f22a40edf8f1"
uuid = "bac558e1-5e72-5ebc-8fee-abe8a469f55d"
version = "1.1.0"
[[Parsers]]
deps = ["Dates", "Test"]
git-tree-sha1 = "d112c19ccca00924d5d3a38b11ae2b4b268dda39"
uuid = "69de0a69-1ddd-5017-9359-2bf0b02dc9f0"
version = "0.3.11"
[[Pkg]]
deps = ["Dates", "LibGit2", "Libdl", "Logging", "Markdown", "Printf", "REPL", "Random", "SHA", "Test", "UUIDs"]
uuid = "44cfe95a-1eb2-52ea-b672-e2afdf69b78f"
[[Printf]]
deps = ["Unicode"]
uuid = "de0858da-6303-5e67-8744-51eddeeeb8d7"
[[REPL]]
deps = ["InteractiveUtils", "Markdown", "Sockets"]
uuid = "3fa0cd96-eef1-5676-8a61-b3b8758bbffb"
[[Random]]
deps = ["Serialization"]
uuid = "9a3f8284-a2c9-5f02-9a11-845980a1fd5c"
[[SHA]]
uuid = "ea8e919c-243c-51af-8825-aaa63cd721ce"
[[Serialization]]
uuid = "9e88b42a-f829-5b0c-bbe9-9e923198166b"
[[Sockets]]
uuid = "6462fe0b-24de-5631-8697-dd941f90decc"
[[StructTypes]]
deps = ["Dates", "UUIDs"]
git-tree-sha1 = "1ed04f622a39d2e5a6747c3a70be040c00333933"
uuid = "856f2bd8-1eba-4b0a-8007-ebc267875bd4"
version = "1.1.0"
[[Test]]
deps = ["Distributed", "InteractiveUtils", "Logging", "Random"]
uuid = "8dfed614-e22c-5e08-85e1-65c5234f0b40"
[[TranscodingStreams]]
deps = ["Random", "Test"]
git-tree-sha1 = "7c53c35547de1c5b9d46a4797cf6d8253807108c"
uuid = "3bb67fe8-82b1-5028-8e26-92a6c54297fa"
version = "0.9.5"
[[UUIDs]]
deps = ["Random", "SHA"]
uuid = "cf7118a7-6976-5b1a-9a39-7adc72f591a4"
[[Unicode]]
uuid = "4ec0a83e-493e-50e2-b9ac-8f72acf5a8f5"

11
Project.toml Normal file
View File

@ -0,0 +1,11 @@
name = "InMemoryLoggedDB"
uuid = "0b408f8b-f764-4985-8a89-4195658babf6"
authors = ["nixo <nicolo@nixo.xyz>"]
version = "0.1.0"
[deps]
JLD2 = "033835bb-8acc-5ee8-8aae-3f567f8a3819"
JSON2 = "2535ab7d-5cd8-5a07-80ac-9b1792aadce3"
JSON3 = "0f8b85d8-7281-11e9-16c2-39a750bddbf1"
MemPool = "f9f48841-c794-520a-933b-121f7ba6ed94"
MsgPack = "99f44e22-a591-53d1-9472-aa23ef4bd671"

67
src/InMemoryLoggedDB.jl Normal file
View File

@ -0,0 +1,67 @@
module InMemoryLoggedDB
export Buffer, flush!, restore
using MsgPack
mutable struct Buffer{T}
size::UInt32 # Save transactions when buffer is full
delay_ns::UInt64 # Force save transactions after this period
io::IOStream # File handle (or other stream where data is saved)
transactions::Array{T} # Circular buffer
position::UInt32 # Position of next element in the buffer
last_ns::UInt64
state
end
function Buffer(size::Int, filename::String, sttype::DataType, delay_ns = 10^9)
log = Array{sttype}(undef, size)
Buffer{sttype}(size, delay_ns, jlopen(filename, "a"),
log, 0, time_ns(), [])
end
function Base.push!(buffer::Buffer, element)
# Store element in the buffer, taking care of saving it to file if needed
buffer.transactions[buffer.position+=1] = element
@debug "Stored element" e=element pos=buffer.position
flush = false
# If buffer if full, go back and save
buffer.position >= buffer.size && (flush = true)
# If enough time passed, we save the data
# flush || (((time_ns() - buffer.last_ns) > buffer.delay_ns) && (flush = true))
flush && flush!(buffer)
nothing
end
function flush!(buffer::Buffer)
wrote = 0
@debug "Flush!: " pos = buffer.position
for p in 1:buffer.position
@debug "writing" p=p el=buffer.transactions[p]
# TODO: This convertion to string must be removed
wrote += write(buffer.io, pack(buffer.transactions[p]))
end
buffer.last_ns = time_ns()
buffer.position = 0
wrote
end
Base.flush(buffer::Buffer) = (flush!(buffer); flush(buffer.io))
function Base.close(buffer::Buffer)
flush(buffer)
close(buffer.io)
empty!(buffer.transactions)
buffer.position = 0
end
function restore(file, T)
out = []
open(file) do io
while !eof(io)
push!(out, unpack(io, T))
end
end
out
end
end # module

80
test/store.jl Normal file
View File

@ -0,0 +1,80 @@
using MsgPack
struct Timing
label::String
time::Float64
end
MsgPack.msgpack_type(::Type{Timing}) = MsgPack.StructType()
const timings = Buffer(1_000_000, "timings.msgpack", Timing)
struct X
el::Bool
N::Int
c::String
end
MsgPack.msgpack_type(::Type{X}) = MsgPack.StructType()
mkpath("results")
function microtest(t, ns)
label = "$(t)_$(ns)"
buf = Buffer(t, "results/$(label).msgpack", X, ns)
res = @timed begin
for i in 1:10000
push!(buf, X(1,i,string("c is: ", i)))
end
flush(buf)
end
close(buf)
(label, res[2])
end
function test(range)
for ns in range
for t in 1:1000
push!(timings,
Timing(microtest(t, ns)...))
end
end
end
test(1:5)
test(6:15:31)
test(10_000_000:10_000_000)
close(timing)
# Compare with the dumbest Array implementation
const dumbtimings = Buffer(1_000_000, "dumbtimings.msgpack", Timing)
function dumb(t, ns)
label = "dumb_$(t)_$(ns)"
name = "results/$(label).msgpack"
res = open(name, "a+") do out
buf = X[]
@timed begin
for i in 1:10000
push!(buf, X(1,i,string("c is: ", i)))
end
write.(Ref(out), pack.(buf))
empty!(buf)
end
end
(label, res[2])
end
function test_dumb(range)
for ns in range
for t in 1:1000
push!(dumbtimings,
Timing(dumb(t, ns)...))
end
end
end
test_dumb(1:5)
test_dumb(6:15:31)
test_dumb(10_000_000:10_000_000)