From 6be6ba9be25f241d957a32a5e28fdc546572f21a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tom=C3=A1=C5=A1=20Drvo=C5=A1t=C4=9Bp?= Date: Fri, 10 Nov 2023 16:09:07 +0100 Subject: [PATCH] [NFC] Add README, reorg code a bit, add comments and docstrings (#7) * Add README.md * Tweak code organization, add comments and docstrings * Fix flakey test * Fix test flakiness on nightly when tasks have some uninitialized fields --------- Co-authored-by: Nathan Daly --- README.md | 145 +++++++++++++++++++++++++++++++++ docs/diagrams/chunked_base.png | Bin 0 -> 182437 bytes src/ChunkedBase.jl | 114 +++++++------------------- src/ChunkingContext.jl | 119 +++++++++++++++++++++++++++ src/ConsumeContexts.jl | 25 ++++-- src/ParsingContexts.jl | 65 +++++++++++++++ src/_traces.jl | 13 +-- src/exceptions.jl | 4 +- src/parser_parallel.jl | 52 +++++++++++- src/parser_serial.jl | 19 +++++ src/payload.jl | 81 +++++++++++++++--- src/read_and_lex.jl | 18 ++-- src/read_and_lex_utils.jl | 21 ++++- test/e2e_tests.jl | 34 ++++---- test/runtests.jl | 4 + 15 files changed, 576 insertions(+), 138 deletions(-) create mode 100644 docs/diagrams/chunked_base.png create mode 100644 src/ChunkingContext.jl create mode 100644 src/ParsingContexts.jl diff --git a/README.md b/README.md index e5aa95a..3ac490b 100644 --- a/README.md +++ b/README.md @@ -1 +1,146 @@ # ChunkedBase.jl + +The package handles the ingestion of data chunks and the distribution & synchronization of work that happens on these chunks in parallel. It came into existence while refactoring the [`ChunkedCSV.jl`](https://github.com/RelationalAI/ChunkedCSV.jl) and [`ChunkedJSONL.jl`](https://github.com/RelationalAI/ChunkedJSONL.jl) packages and was designed to be extended by packages like these. It is a package used to write parser packages. + +## Overview + +The purpose of the package is to provide a framework for creating parsers for textual formats, where each record is separated by a newline character. Examples of such formats include CSV and JSONLines. The package is designed to operate on data chunks and to reuse preallocated buffers for each of these chunks. It simplifies the process of ingesting data, locating newlines, distributing work among multiple tasks, and synchronizing them. To implement a parsing package, one only needs to define how to *parse* the records and how to *consume* the parsed results. + +Parsing refers to taking the raw input bytes and the position of newlines that will be available to the user, and using a package like `Parsers.jl` or `JSON3.jl`, or some custom parsing code to produce records of Julia types that could be stored in user-defined result buffers, which can be customized e.g for row-oriented or column-oriented storage. + +Consuming refers to taking the parsed results and doing something with them, such as inserting them into a database, appending them to a `DataFrame`, or writing them to a file. + +## How it works + +Internally, `ChunkedBase.jl` uses a coordinator task and a set number of worker tasks to process data. The coordinator task is responsible for handling IO operations and acts as a coordinator for the worker tasks. It reads bytes from an input buffer and uses the [`NewlineLexers.jl`](https://github.com/JuliaData/NewlineLexers.jl) package to identify newlines in the data. Since the data is delimited by newlines, these newlines are used to split up the work among the worker tasks. + +The coordinator task alternates between two buffers, processing one while the workers process the other. This ensures that there is always data available for the workers to consume, which maximizes throughput across all tasks. We call this technique double-buffering. + +The process looks something like this, with the coordinator task at the bottom: + +| ![Diagram](/docs/diagrams/chunked_base.png) | +|:--:| +| *The coordinator uses a counter behind a mutex to synchronize with the workers. There is one such counter per buffer, and the counter is incremented by N after the coordinator splits the newlines into N segments and distributes them. After distributing the work, the coordinator starts to process the second chunk of data while the first buffer is still being worked on. A handoff occurs between the two buffers, where the bytes after the last newline from the first buffer are copied to the second. Each worker decrements the counter after completing the `consume!` operation, and the coordinator waits for the counter to reach 0 before overwriting the buffer with new data.* | + +Packages like `ChunkedCSV.jl` and `ChunkedJSONL.jl` hook into this structure by defining their own `populate_result_buffer!` methods that parse the records they were assigned into their custom `Result` buffers which are then handed to the `consume!` method (e.g. to be inserted into a database). + +The main entry point of this package is the `parse_file_parallel` function, which accepts several "context" arguments, each controlling a different aspect of the process: +```julia +function parse_file_parallel( + lexer::Lexer, + parsing_ctx::AbstractParsingContext, # user-defined + consume_ctx::AbstractConsumeContext, # user-defined + chunking_ctx::ChunkingContext, + result_buffers::Vector{<:AbstractResultBuffer}, # user-defined + ::Type{CT}=Tuple{} # ignore this for now +) where {CT} +``` +Let's break it down: +* `lexer` controls how we find newlines in the ingested chunks of data. Newlines serve as record delimiters and knowing their positions allows us to split work safely among multiple workers, which are spawned internally. `Lexer`s are defined in the `NewlineLexers.jl` package. +* `parsing_ctx` controls how we parse the data. It allows the user to dispatch on custom `populate_result_buffer!` overload and to forward configurations to it. `populate_result_buffer!` is where we take the records identified by the `lexer` and parse them into `result_buffers`. +* `consume_ctx` controls how the parsed results are consumed (e.g. inserted into a database, appended to a `DataFrame`...). `consume_ctx` allows the user to dispatch on their `consume!` method and hold any state necessary for consumption. This happens immediately after `populate_result_buffer!`. +* `chunking_ctx` controls how the work on individual chunks of data is scheduled. It contains buffers for input bytes and found newlines. Through this struct the user controls the size of the chunks and the number of spawned tasks that carry out the parsing and consuming. If there is enough data in the input, a secondary `chunking_ctx` is created internally to facilitate the double-buffering described above. +* `result_buffers` controls in which format the results are stored. These result buffers hold results from `populate_result_buffer!` and are passed to `consume!`. This allows the user to have multiple result formats for the same `parsing_ctx` e.g. row-oriented vs column-oriented buffers. + +There is also `parse_file_serial` which doesn't spawn any tasks and just calls `populate_result_buffer!` and `consume!` sequentially without double-buffering. This can be useful for debugging or for small files. + +See the docstring of `populate_result_buffer!` and `consume!` for more information about how to integrate with them. + +## Example: Examining the results of the Lexer + +Since `ChunkedBase.jl` handles newline detection automatically, a very simple chunked processor could just show the newline positions to the user. Of course, this is not very useful apart from demonstrating how to use this package. + +```julia +using ChunkedBase + +# Our chunked processor doesn't require any settings nor does it need to maintain +# any additional state, so we'll define our `ParsingContext` and `ConsumeContext` only +# for dispatch reasons. +struct ParsingContext <: AbstractParsingContext end +struct ConsumeContext <: AbstractConsumeContext end +# Our buffer will hold the newline positions in the current chunk +struct ResultBuffer <: AbstractResultBuffer + newlines_in_chunk::Vector{Int} +end + +# Our overload copies `newlines_segment` to our result buffer +function ChunkedBase.populate_result_buffer!( + result_buf::ResultBuffer, + newlines_segment::AbstractVector{Int32}, + ::ParsingContext, + ::Vector{UInt8}, + ::Union{Nothing,Vector{UInt8}}=nothing, + ::Type=Tuple{} +) + resize!(result_buf.newlines_in_chunk, length(newlines_segment)) + result_buf.newlines_in_chunk .= newlines_segment + return nothing +end + +# We consume result buffer by simply printing it +function ChunkedBase.consume!(::ConsumeContext, payload::ParsedPayload) + # The ParsedPayload wraps the result buffer and the other contexts + chunking_ctx = payload.chunking_ctx + result_buffer = payload.results + + # To demonstrate how double-buffering works, print the buffer id and the refill number + chunk_info = (chunking_ctx.id, chunking_ctx.buffer_refills[]) + @info "Newlines in chunk (id:$chunk_info): $(result_buffer.newlines_in_chunk)" + return nothing +end +``` + +Now that we defined all overloads and contexts we can define our user-facing function: + +```julia +# Prints relative positions of `\n` in each ingested chunk of size `buffersize`, +# using `nworkers` spawned tasks. +function print_newlines(io, buffersize, nworkers) + lexer = Lexer(io, nothing, '\n') + parsing_ctx = ParsingContext() + consume_ctx = ConsumeContext() + chunking_ctx = ChunkingContext(buffersize, nworkers) + # ChunkedBase.jl requires 2 result buffers per worker task, we'd get an error otherwise + result_buffers = [ResultBuffer(Int[]) for _ in 1:2nworkers] + + parse_file_parallel(lexer, parsing_ctx, consume_ctx, chunking_ctx, result_buffers) + return nothing +end +``` +Let's run it on some data: +```julia +julia> io = IOBuffer((("x" ^ 4095) * "\n") ^ 64); # 256KiB +julia> print_newlines(io, 64 * 1024, 4); +# [ Info: Newlines in chunk (id:(1, 1)): [16384, 20480, 24576, 28672, 32768, 36864] +# [ Info: Newlines in chunk (id:(1, 1)): [0, 4096, 8192, 12288, 16384] +# [ Info: Newlines in chunk (id:(1, 1)): [36864, 40960, 45056, 49152, 53248, 57344] +# [ Info: Newlines in chunk (id:(1, 1)): [57344, 61440, 65536] +# [ Info: Newlines in chunk (id:(2, 1)): [16384, 20480, 24576, 28672, 32768, 36864] +# [ Info: Newlines in chunk (id:(2, 1)): [0, 4096, 8192, 12288, 16384] +# [ Info: Newlines in chunk (id:(2, 1)): [36864, 40960, 45056, 49152, 53248, 57344] +# [ Info: Newlines in chunk (id:(2, 1)): [57344, 61440, 65536] +# [ Info: Newlines in chunk (id:(1, 2)): [0, 4096, 8192, 12288, 16384] +# [ Info: Newlines in chunk (id:(1, 2)): [36864, 40960, 45056, 49152, 53248, 57344] +# [ Info: Newlines in chunk (id:(1, 2)): [16384, 20480, 24576, 28672, 32768, 36864] +# [ Info: Newlines in chunk (id:(1, 2)): [57344, 61440, 65536] +# [ Info: Newlines in chunk (id:(2, 2)): [0, 4096, 8192, 12288, 16384] +# [ Info: Newlines in chunk (id:(2, 2)): [16384, 20480, 24576, 28672, 32768, 36864] +# [ Info: Newlines in chunk (id:(2, 2)): [36864, 40960, 45056, 49152, 53248, 57344] +# [ Info: Newlines in chunk (id:(2, 2)): [57344, 61440, 65536] +``` +Behind the scenes, `ChunkedBase.jl` was using two 64KiB buffers, finding newlines in them, and splitting the found newlines among 4 tasks. We can see that each of the buffers (identified by the first number in the `id` tuple) was refilled two times (the refill number is the second element of the tuple). +The way we set up our data, there should be one newline every 4KiB of input, so we'd expect 16 newlines per chunk, but we could see that there are 20 numbers reported per chunk -- this is because each newline segment we send to the tasks starts with the last newline position from the previous segment or 0 for the first segment, so we get 4 duplicated elements in this case. + +## Advanced usage + +### Customizing work coordination + +Internally, the coordination of work happens through `setup_tasks!`, `task_done!` and `sync_tasks` functions which are defined in the `ConsumeContexts.jl` file. `setup_tasks!` sets the counter for the number of units of work that are expected to happen on the current chunk. `task_done!` is called by the worker tasks when they are done with their work, which will decrement the counter. `sync_tasks` is called by the coordinator task to wait for all workers to finish their work, i.e. for the counter to be 0. These functions are exposed to the user through the `AbstractConsumeContext` interface, so they can be overloaded to implement custom synchronization strategies. For example, if the user wants to send the parsed result buffers to external tasks from their `consume!` method and wait for *them* to be done with their work, they can overload `setup_tasks!` to increase the expected number of units of work and then call `task_done!` from the external tasks when they are done. This way, the coordinator task will wait for the external tasks to finish their work before refilling the buffer with new data. See the docstrings of these functions for more information. + +### Sniffing the beginning of the file + +Sometimes we want to skip over the first couple of lines of a file, e.g. when they contain comments or metadata, or we might want to set up our `AbstractParsingContext` with some information that is available at the beginning of the file (like the header names of a CSV). + +To do this, we can use fill our `ChunkingContext` with `read_and_lex!` which will read the first `buffersize` bytes from the input and lex them so that we can inspect the newlines and decide what to do with the file. We can use `skip_rows_init!` to skip over rows that we don't want to parse, and then use `parse_file_parallel` to parse the rest of the file, so our `populate_result_buffers!` method can focus on the "cleaner" part of the file. + +Instead of `read_and_lex!`, one could also call `initial_read!` and `initial_lex!` separately. This gives you the opportunity to detect which newline type is used in the file and set up your lexer accordingly. diff --git a/docs/diagrams/chunked_base.png b/docs/diagrams/chunked_base.png new file mode 100644 index 0000000000000000000000000000000000000000..aeae42a3e8ed1307ccf088b49862d8c8e68edaa5 GIT binary patch literal 182437 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�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%0A!F}f$Lw*w%)1RU0R$52x~g&zEyg0Iqd$%o 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 aLF!$y)nlo^pm_!Or|?`=w)EMnp#KNp{`CR? literal 0 HcmV?d00001 diff --git a/src/ChunkedBase.jl b/src/ChunkedBase.jl index e31b120..4a790b4 100644 --- a/src/ChunkedBase.jl +++ b/src/ChunkedBase.jl @@ -6,103 +6,39 @@ using CodecZlibNG using NewlineLexers using SentinelArrays.BufferedVectors -const MIN_TASK_SIZE_IN_BYTES = 16 * 1024 +# The means through which the user can provide their own parsing logic. +include("ParsingContexts.jl") -# populate_result_buffer!(result_buf::AbstractResultBuffer, newlines::AbstractVector{Int32}, parsing_ctx::AbstractParsingContext, comment::Union{Nothing,Vector{UInt8}}=nothing, ::Type{CT}=Tuple{}) where {CT} -function populate_result_buffer! end - -abstract type AbstractParsingContext end - -# Synchronization mechanism -- after we lexed all rows, we split them in N tasks and TaskCounter -# in ChunkingContext will block the io/lexer to overwrite the current chunk unless workers -# report back N times that they are done with their tasks. +# A counter-based synchronization primitive that is used to coordinate the parsing/consuming tasks. include("TaskCounters.jl") using .TaskCounters -_comment_to_bytes(x::AbstractString) = Vector{UInt8}(x) -_comment_to_bytes(x::Char) = _comment_to_bytes(ncodeunits(x) > 1 ? string(x) : UInt8(x)) -_comment_to_bytes(x::UInt8) = [x] -_comment_to_bytes(x::Vector{UInt8}) = x -_comment_to_bytes(::Nothing) = nothing -struct ChunkingContext - id::Int - counter::TaskCounter - newline_positions::BufferedVector{Int32} - bytes::Vector{UInt8} - nworkers::Int - limit::Int - comment::Union{Nothing,Vector{UInt8}} - # combination on `id` and `buffer_refills` can be used to detect if any pointers to `bytes` are still valid - buffer_refills::Base.RefValue{Int} -end -function ChunkingContext(buffersize::Integer, nworkers::Integer, limit::Integer, comment::Union{Nothing,UInt8,String,Char,Vector{UInt8}}) - (4 <= buffersize <= typemax(Int32)) || throw(ArgumentError("`buffersize` argument must be larger than 4 and smaller than 2_147_483_648 bytes.")) - (0 < nworkers < 256) || throw(ArgumentError("`nworkers` argument must be larger than 0 and smaller than 256.")) - (0 <= limit <= typemax(Int)) || throw(ArgumentError("`limit` argument must be positive and smaller than 9_223_372_036_854_775_808.")) - # TRACING # clear_traces!(nworkers) - return ChunkingContext( - 1, - TaskCounter(), - BufferedVector{Int32}(Int32[0], 1), - Vector{UInt8}(undef, buffersize), - nworkers, - limit, - _comment_to_bytes(comment), - Ref(0), - ) -end -function ChunkingContext(ctx::ChunkingContext) - out = ChunkingContext( - ctx.id + 1, - TaskCounter(), - BufferedVector{Int32}(Vector{Int32}(undef, max(1, length(ctx.newline_positions))), 1), - similar(ctx.bytes), - ctx.nworkers, - ctx.limit, - ctx.comment, - Ref(0), - ) - out.newline_positions.elements[1] = 0 - return out -end -tasks_per_chunk(ctx::ChunkingContext) = ctx.nworkers -total_result_buffers_count(ctx::ChunkingContext) = 2tasks_per_chunk(ctx) -last_newline_at(ctx::ChunkingContext) = Int(last(ctx.newline_positions)) -function should_use_parallel(ctx::ChunkingContext, _force) - return !( - _force === :serial || - ((_force !== :parallel) && (Threads.nthreads() == 1 || ctx.nworkers == 1 || last_newline_at(ctx) < MIN_TASK_SIZE_IN_BYTES)) - ) -end - -# We split the detected newlines equally among thr nworkers parsing tasks, but each -# unit of work should contain at least 16 KiB of raw bytes (MIN_TASK_SIZE_IN_BYTES). -function estimate_task_size(ctx::ChunkingContext) - eols = ctx.newline_positions - length(eols) == 1 && return 1 # empty file - bytes_to_parse = last(eols) - rows = length(eols) # actually rows + 1 - buffersize = length(ctx.bytes) - # There are 2*nworkers result buffers total, but there are nworkers tasks per chunk - prorated_maxtasks = ceil(Int, tasks_per_chunk(ctx) * (bytes_to_parse / buffersize)) - # Lower bound is 2 because length(eols) == 2 => 1 row - # bump min rows if average row is much smaller than MIN_TASK_SIZE_IN_BYTES - min_rows = max(2, cld(MIN_TASK_SIZE_IN_BYTES, cld(bytes_to_parse, rows))) - return min(max(min_rows, cld(rows, prorated_maxtasks)), rows) -end - -abstract type AbstractResultBuffer end +# The `ChunkingContext` is used to keep track of the current chunk of data being processed +# and to coordinate with the parsing/consuming tasks. Two `ChunkingContext` objects are used +# to double-buffer the input. +include("ChunkingContext.jl") +# The `ParsedPayload` is used to pass the results of parsing to the `consume!` method. All relevant +# information about the current chunk of data being processed is passed to `consume!` via `ParsedPayload`. +# In case the parsed results need to be consumed in order, the `PayloadOrderer` can be used to +# sort the payloads. include("payload.jl") +# Consuming is the means through which the parsed results are used by the end user. +include("ConsumeContexts.jl") +using .ConsumeContexts + +# By lexing the input in advance we can detect that we got to an inconsistent state +# (e.g. an unmatched quote at the end of the file) in which case we throw one of these exceptions. include("exceptions.jl") + +# Utilities for the coordinator task to handle the input and the newline positions. include("read_and_lex_utils.jl") include("read_and_lex.jl") -include("ConsumeContexts.jl") -using .ConsumeContexts -include("parser_serial.jl") +# The main entrypoints of the library. include("parser_parallel.jl") +include("parser_serial.jl") export ChunkingContext, tasks_per_chunk, total_result_buffers_count export AbstractParsingContext @@ -114,6 +50,14 @@ export SkipContext export Lexer export parse_file_serial, parse_file_parallel, populate_result_buffer! + +# By uncommenting all `# TRACING #` in the package, e.g. by turning them to `#= ... =#`, +# you'll enable low-overhead tracing capability. +# Before parsing, call `clear_traces!` to reset the traces, then call +# include("_tracing.jl") # once +# plot_traces() # to plot the traces +# TODO(#9): Port this over to be macro-based, with plotting being provided by a package extension + # TRACING # const PARSER_TASKS_TIMES = [UInt[]] # TRACING # const CONSUMER_TASKS_TIMES = [UInt[]] # TRACING # const IO_TASK_TIMES = UInt[] diff --git a/src/ChunkingContext.jl b/src/ChunkingContext.jl new file mode 100644 index 0000000..0c29ad8 --- /dev/null +++ b/src/ChunkingContext.jl @@ -0,0 +1,119 @@ +# When splitting the work among multiple tasks, we aim for each task to have at least this +# many bytes of input to work on (even if it means that some tasks will have nothing to process) +# This is to avoid overhead from too many task switches. +# TODO(#10): make this configurable and find a good default (the current 16 KiB is a guess) +const MIN_TASK_SIZE_IN_BYTES = 16 * 1024 + +_comment_to_bytes(x::AbstractString) = Vector{UInt8}(x) +_comment_to_bytes(x::Char) = _comment_to_bytes(ncodeunits(x) > 1 ? string(x) : UInt8(x)) +_comment_to_bytes(x::UInt8) = [x] +_comment_to_bytes(x::Vector{UInt8}) = x +_comment_to_bytes(::Nothing) = nothing + +""" + ChunkingContext( + buffersize::Integer, + nworkers::Integer, + limit::Integer, + comment::Union{Nothing,UInt8,String,Char,Vector{UInt8}} + ) -> ChunkingContext + +A context object used to coordinate parallel parsing of a single file, chunk by chunk. + +The user can use this object to specify the size of the byte buffer(s) to allocate, the +number of worker tasks to spawn and the maximum number of rows to parse in `parse_file_parallel`. + +# Arguments: +- `buffersize`: the size of the byte buffer to allocate . + If the input is bigger than `buffersize`, a secondary `ChunkingContext` object will be used to + double-buffer the input, which will allocate a new buffer of the same size as `buffersize`. +- `nworkers`: the number of worker tasks that should be spawned in `parse_file_parallel`. +- `limit`: the maximum number of rows to parse, see `limit_eols!`, by default no limit is set. +- `comment`: the comment prefix to skip, if any. By default no comment prefix is skipped. + +# Notes: +- One can use the `id` and `buffer_refills` fields to uniquely identify a chunk of input. +The `id` field is necessary because we internally create a secondary `ChunkingContext` object, with +`id` equal to the `id` of the original `ChunkingContext` + 1. +- The `counter` field is used to synchronize the parser/consumer tasks. +- The `newline_positions` field is used to store the newline positions in the input. +- The `bytes` field is used to store the raw bytes ingested from the input. +- `comment` can be used to skip the *initial* comment lines in the `skip_rows_init!`. This value is also passed to `populate_result_buffer!` for user to apply handle commented rows in the middle of the file during parsing (`_startswith` could be used to do the check). +- The `buffersize` should be large enough to fit the longest row in the input, otherwise the lexer will fail. +- The `buffersize` should be chosen such that each of the `nworkers` tasks has enough bytes to work on. Using 1MiB per task seems to work reasonably well in practice. + +# See also: +- [`parse_file_parallel`](@ref), [`parse_file_serial`](@ref) +""" +struct ChunkingContext + id::Int # id of the chunking context (1 or 2) + counter::TaskCounter # synchronization mechanism to coordinate parsing + newline_positions::BufferedVector{Int32} # positions of newlines in the bytes + bytes::Vector{UInt8} # raw bytes ingested from the input + nworkers::Int # number of worker tasks + limit::Int # maximum number of rows to parse, see `limit_eols!` + # byte prefix to skip, used in `skip_rows_init!` and handed to `populate_result_buffer!` + # for user to handle with consistently (`_startswith` could be used to do the check) + comment::Union{Nothing,Vector{UInt8}} + # number of times we refilled the buffer, can be combined with `id` to uniquely identify a chunk + buffer_refills::Base.RefValue{Int} +end +function ChunkingContext(buffersize::Integer, nworkers::Integer, limit::Integer=0, comment::Union{Nothing,UInt8,String,Char,Vector{UInt8}}=nothing) + (4 <= buffersize <= typemax(Int32)) || throw(ArgumentError("`buffersize` argument must be larger than 4 and smaller than 2_147_483_648 bytes.")) + (0 < nworkers < 256) || throw(ArgumentError("`nworkers` argument must be larger than 0 and smaller than 256.")) + (0 <= limit <= typemax(Int)) || throw(ArgumentError("`limit` argument must be positive and smaller than 9_223_372_036_854_775_808.")) + # TRACING # clear_traces!(nworkers) + return ChunkingContext( + 1, + TaskCounter(), + BufferedVector{Int32}(Int32[0], 1), + Vector{UInt8}(undef, buffersize), + nworkers, + limit, + _comment_to_bytes(comment), + Ref(0), + ) +end +# Convenience for double-buffering +function ChunkingContext(ctx::ChunkingContext) + out = ChunkingContext( + ctx.id + 1, + TaskCounter(), + BufferedVector{Int32}(Vector{Int32}(undef, max(1, length(ctx.newline_positions))), 1), + similar(ctx.bytes), + ctx.nworkers, + ctx.limit, + ctx.comment, + Ref(0), + ) + out.newline_positions.elements[1] = 0 + return out +end +tasks_per_chunk(ctx::ChunkingContext) = ctx.nworkers +total_result_buffers_count(ctx::ChunkingContext) = 2tasks_per_chunk(ctx) +last_newline_at(ctx::ChunkingContext) = Int(last(ctx.newline_positions)) +function should_use_parallel(ctx::ChunkingContext, _force) + return !( + _force === :serial || + ((_force !== :parallel) && (Threads.nthreads() == 1 || ctx.nworkers == 1 || last_newline_at(ctx) < MIN_TASK_SIZE_IN_BYTES)) + ) +end + +# Instead of splitting the newlines among `nworker` tasks equally, we try to ensure that each task +# has at least `MIN_TASK_SIZE_IN_BYTES` bytes of input to work on. For smaller inputs or for +# the last, trailing bytes of a bigger file, there won't be enough newlines to utilize each +# of the `nworkers` tasks properly, so we'll send out fewer chunks of work that are bigger to +# the parsing queue. +function estimate_task_size(ctx::ChunkingContext) + eols = ctx.newline_positions + length(eols) == 1 && return 1 # empty file + bytes_to_parse = last(eols) + rows = length(eols) # actually rows + 1 + buffersize = length(ctx.bytes) + # There are `2*nworkers` result buffers total, but there are `nworkers` tasks per chunk + prorated_maxtasks = ceil(Int, tasks_per_chunk(ctx) * (bytes_to_parse / buffersize)) + # Lower bound is 2 because length(eols) == 2 => 1 row + # bump min rows if average row is much smaller than MIN_TASK_SIZE_IN_BYTES + min_rows = max(2, cld(MIN_TASK_SIZE_IN_BYTES, cld(bytes_to_parse, rows))) + return min(max(min_rows, cld(rows, prorated_maxtasks)), rows) +end diff --git a/src/ConsumeContexts.jl b/src/ConsumeContexts.jl index 66e7d3b..977a3fc 100644 --- a/src/ConsumeContexts.jl +++ b/src/ConsumeContexts.jl @@ -7,6 +7,17 @@ using ..ChunkedBase: set!, dec! export AbstractConsumeContext, SkipContext export setup_tasks!, consume!, task_done!, sync_tasks, cleanup +""" + AbstractConsumeContext + +End users should subtype this to create custom consume contexts which are then +used in `parse_file_parallel` and `parse_file_serial`, to dispatch on their +`populate_result_buffer!` method. + +# See also: +- [`parse_file_parallel`](@ref), [`parse_file_serial`](@ref), [`populate_result_buffer!`](@ref) +- See also [`consume!`](@ref), [`setup_tasks!`](@ref), [`setup_tasks!`](@ref), [`cleanup`](@ref), [`AbstractResultBuffer`](@ref) +""" abstract type AbstractConsumeContext end """ @@ -14,7 +25,7 @@ abstract type AbstractConsumeContext end Override with your `AbstractConsumeContext` to provide a custom logic for processing the parsed results in `AbstractResultBuffer`. The method is called from multiple tasks in parallel, just after each corresponding `task_buf` has been populated. -`task_buf` is only filled once per chunk. +`task_buf` is only filled once per chunk and is only accessed by one task at a time. See also [`consume!`](@ref), [`setup_tasks!`](@ref), [`setup_tasks!`](@ref), [`cleanup`](@ref), [`AbstractResultBuffer`](@ref) """ @@ -34,11 +45,11 @@ is considered to be entirely processed. This function is called just after the we're done detecting newline positions in the current chunk of data and we are about to submit partitions of the detected newlines to the parse/consume tasks. -`ntasks` is between 1 and two times the `nworkers` agrument to `parse_file`, depeneding on -the size of the input. Most of the time, the value is `2*nworkers` is used, but for smaller -buffer sizes, smaller files or when handling the last bytes of the file, `ntasks` will be -smaller as we try to ensure the minimal average tasks size if terms of bytes of input is at least -$(Base.format_bytes(MIN_TASK_SIZE_IN_BYTES)). For `:serial` parsing mode, `ntasks` is always 1. +`ntasks` is between 1 and `nworkers` argument to `parse_file`, depending on the size of the input. +Most of the time, the value is `nworkers` is used, but for smaller buffer sizes, smaller files or +when handling the last bytes of the file, `ntasks` will be smaller as we try to ensure the minimal +average tasks size if terms of bytes of input is at least $(Base.format_bytes(MIN_TASK_SIZE_IN_BYTES)). +For `:serial` parsing mode, `ntasks` is always 1. You should override this method when you further subdivide the amount of concurrent work on the chunk, e.g. when you want to process each column separately in `@spawn` tasks, in which case you'd expect @@ -67,7 +78,7 @@ function task_done!(::AbstractConsumeContext, chunking_ctx::ChunkingContext) return nothing end -# TODO: If we want to support schema inference, this would be a good place to sync a `Vector{TaskResultBuffer}` belonging to current `parsing_ctx` +# TODO(#11): If we want to support schema inference, this would be a good place to sync a `Vector{TaskResultBuffer}` belonging to current `parsing_ctx` """ sync_tasks(consume_ctx::AbstractConsumeContext, chunking_ctx::ChunkingContext) diff --git a/src/ParsingContexts.jl b/src/ParsingContexts.jl new file mode 100644 index 0000000..ad7c95c --- /dev/null +++ b/src/ParsingContexts.jl @@ -0,0 +1,65 @@ +""" + populate_result_buffer!( + result_buf::AbstractResultBuffer, + newline_segment:AbstractVector{Int32}, + parsing_ctx::AbstractParsingContext, + bytes::Vector{UInt8}, + comment::Union{Nothing,Vector{UInt8}}=nothing, + ::Type{CT}=Tuple{} + ) where {CT} + +Override with your `AbstractParsingContext` to provide custom logic for parsing the input bytes +in `parsing_ctx.bytes` between the newline positions in `newline_segment` into `result_buf`. +The method is called from multiple tasks in parallel, each having a different `newline_segment`, +some sharing the same `parsing_ctx.bytes`. The `result_buf` is only accessed by one task at a time. + +# Arguments: +* `result_buf`: a user-provided object which is meant to store the parsing results from this function +* `newline_segment`: a vector of newline positions in `bytes` which delimit the rows of the input. +* `parsing_ctx`: a user-provided object that is used to dispatch to this method and carry parsing specific config +* `bytes`: the raw bytes ingested from the input +* `comment`: the comment prefix to skip, if any +* `CT`: an optional, compile-time known object which was passed to `parse_file_parallel` / `parse_file_serial` + +# Notes: +Each consecutive pair of `newline_segment` values defines an exclusive range of bytes in `bytes` which +constitutes a single row. + +The range needs to be treated as exclusive because we add a fictional newline at the beginning of the chunk +at position 0 and past the end of the file if it doesn't end on a newline. +A safe way of processing each row would be e.g.: + +``` +start_index = first(newline_segment) +for i in 2:length(newline_segment) + end_index = newline_segment[i] + row_bytes = view(bytes, start_index+1:end_index-1) # +/- 1 is needed! + + # ... actually populate the result_buf + + start_index = end_index +end +``` +""" +function populate_result_buffer! end +""" + AbstractParsingContext + +Users should subtype this to create custom parsing contexts variables which are +then used in `parse_file_parallel` / `parse_file_serial`, to dispatch on their +`populate_result_buffer!` method. + +# See also: +- [`parse_file_parallel`](@ref), [`parse_file_serial`](@ref), [`populate_result_buffer!`](@ref) +""" +abstract type AbstractParsingContext end +""" + AbstractResultBuffer + +Users should subtype this to create custom result buffer objects to store the +parsed results in `populate_result_buffer!`. + +# See also: +- [`parse_file_parallel`](@ref), [`parse_file_serial`](@ref), [`populate_result_buffer!`](@ref) +""" +abstract type AbstractResultBuffer end diff --git a/src/_traces.jl b/src/_traces.jl index 72a4a74..5d09403 100644 --- a/src/_traces.jl +++ b/src/_traces.jl @@ -1,15 +1,16 @@ using GLMakie, ChunkedBase function plot_traces() - t1 = copy(ChunkedBase.T1) - t2 = copy(ChunkedBase.T2) - io_task = copy(ChunkedBase.IO_TASK_TIMES) - lexer_task = copy(ChunkedBase.LEXER_TASK_TIMES) - parser_tasks = filter(x->length(x)>0, ChunkedBase.PARSER_TASKS_TIMES) - consume_tasks = filter(x->length(x)>0, ChunkedBase.CONSUMER_TASKS_TIMES) + t1 = copy(ChunkedBase.T1) # total parse/consume time for the first byte buffer by all workers + t2 = copy(ChunkedBase.T2) # total parse/consume time for the second byte buffer by all workers + io_task = copy(ChunkedBase.IO_TASK_TIMES) # time spent in IO + lexer_task = copy(ChunkedBase.LEXER_TASK_TIMES) # time spent in lexer + parser_tasks = filter(x->length(x)>0, ChunkedBase.PARSER_TASKS_TIMES) # individual parse/consume times for each worker + consume_tasks = filter(x->length(x)>0, ChunkedBase.CONSUMER_TASKS_TIMES) # optional extensions for consumes that spawn tasks start = Int(mapreduce(first, min, parser_tasks, init=min(io_task[1], lexer_task[1]))) + # convert to seconds, subtract start time lexer_timing = map(x->(x - start) / (1e9), lexer_task) io_timing = map(x->(x - start) / (1e9), io_task) pa_timings = map.(x->(x - start) / (1e9), parser_tasks) diff --git a/src/exceptions.jl b/src/exceptions.jl index e360032..9f51945 100644 --- a/src/exceptions.jl +++ b/src/exceptions.jl @@ -1,8 +1,8 @@ abstract type FatalLexingError <: Exception end Base.showerror(io::IO, e::FatalLexingError) = print(io, e.msg) -# TODO: Add some data to help debug the problematic file, like the first row with an escape character -# and/or the quote character. +# TODO(#12): Add some data to help debug the problematic file, like the first row with an escape character +# and/or the quote character. struct NoValidRowsInBufferError <: FatalLexingError msg::String buffersize::Int diff --git a/src/parser_parallel.jl b/src/parser_parallel.jl index 02f48ba..0e6b010 100644 --- a/src/parser_parallel.jl +++ b/src/parser_parallel.jl @@ -1,4 +1,9 @@ -# What the read_and_lex_task! task submits to the many parser tasks +# What the `read_and_lex_task!` task submits to the parser tasks via a Channel +# * task_start: first index in the newline_positions buffer the parser task should process +# * task_end: first index in the newline_positions buffer the parser task should process +# * row_num: the (global) row number of the first newline in the chunk +# * task_num: the index of the task (1-based) +# * use_current_context: whether to use the current or the next chunking context (double-buffering) const SubtaskMetadata = @NamedTuple{task_start::Int32, task_end::Int32, row_num::Int, task_num::Int, use_current_context::Bool} function submit_lexed_rows!(parsing_queue, consume_ctx, chunking_ctx, row_num) @@ -90,6 +95,47 @@ function process_and_consume_task( end end +""" + parse_file_parallel( + lexer::Lexer, + parsing_ctx::AbstractParsingContext, + consume_ctx::AbstractConsumeContext, + chunking_ctx::ChunkingContext, + result_buffers::Vector{<:AbstractResultBuffer}, + ::Type{CT}=Tuple{} + ) where {CT} -> Nothing + +Parse the file in `lexer.io` in parallel using `chunking_ctx.nworkers` tasks. User must provide +a `populate_result_buffer!` method which is used to parse ingested data in `chunking_ctx.bytes`, using the +newline positions in `chunking_ctx.newline_positions` as row boundaries into the `result_buffers`. +The `consume!` method is called after each `populate_result_buffer!` call, so the user can process +the parsed results in parallel. No `result_buffer` is accessed by more than one task at a time. + +# Arguments: +* `lexer`: a `NewlineLexers.Lexer` object which is used to find newline positions in the input. The +type of the lexer affects whether the search is quote-aware or not. +* `parsing_ctx`: a user-provided object which is passed to `populate_result_buffer!` +* `consume_ctx`: a user-provided object which is passed to `consume!` +* `chunking_ctx`: an internal object that is used to keep track of the current chunk of data being processed +* `result_buffers`: a vector of user-provided objects which are used to store the parsed results +* `CT`: an optional, compile-time known type which is passed to `populate_result_buffer!`. +This is bit of niche functionality required by ChunkedCSV, which needs to know about +"custom types" at compile time in order to unroll the parsing loop on them. + +# Exceptions: +* `UnmatchedQuoteError`: if the input ends with an unmatched quote +* `NoValidRowsInBufferError`: if not a single newline was found in the input buffer +* `CapturedException`: if an exception was thrown in one of the parser/consumer tasks + +# Notes: +* You can initialize the `chunking_ctx` yourself using `read_and_lex!` or with `initial_read!` + `initial_lex!` +which gives you the opportunity to sniff the first chunk of data before you call `parse_file_parallel`. +* If the input is bigger than `chunking_ctx.bytes`, a secondary `chunking_ctx` object will be used to +double-buffer the input, which will allocate a new buffer of the same size as `chunking_ctx.bytes`. +* This function spawns `chunking_ctx.nworkers` + 1 tasks. + +See also [`populate_result_buffer!`](@ref), [`consume!`](@ref), [`parse_file_serial`](@ref). +""" function parse_file_parallel( lexer::Lexer, parsing_ctx::AbstractParsingContext, @@ -100,6 +146,10 @@ function parse_file_parallel( ) where {CT} @assert chunking_ctx.id == 1 length(result_buffers) != total_result_buffers_count(chunking_ctx) && ArgumentError("Expected $(total_result_buffers_count(chunking_ctx)) result buffers, got $(length(result_buffers)).") + # In case we were given an uninitialized chunking_ctx, we need to fill it first + if chunking_ctx.buffer_refills[] == 0 && !lexer.done + read_and_lex!(lexer, chunking_ctx) + end parsing_queue = Channel{SubtaskMetadata}(Inf) if lexer.done diff --git a/src/parser_serial.jl b/src/parser_serial.jl index 0c8b421..677a3ff 100644 --- a/src/parser_serial.jl +++ b/src/parser_serial.jl @@ -1,3 +1,18 @@ +""" + parse_file_serial( + lexer::Lexer, + parsing_ctx::AbstractParsingContext, + consume_ctx::AbstractConsumeContext, + chunking_ctx::ChunkingContext, + result_buf::AbstractResultBuffer, + ::Type{CT}=Tuple{}, + ) where {CT} + +The serial analog of `parse_file_parallel` which doesn't spawn any tasks, +useful for debugging and processing very small files. + +See also [`populate_result_buffer!`](@ref), [`consume!`](@ref), [`parse_file_parallel`](@ref). +""" function parse_file_serial( lexer::Lexer, parsing_ctx::AbstractParsingContext, @@ -6,6 +21,10 @@ function parse_file_serial( result_buf::AbstractResultBuffer, ::Type{CT}=Tuple{}, ) where {CT} + # In case we were given an uninitialized chunking_ctx, we need to fill it first + if chunking_ctx.buffer_refills[] == 0 && !lexer.done + read_and_lex!(lexer, chunking_ctx) + end row_num = 1 _comment = chunking_ctx.comment try diff --git a/src/payload.jl b/src/payload.jl index e41003b..c62a52f 100644 --- a/src/payload.jl +++ b/src/payload.jl @@ -2,14 +2,29 @@ # ParsedPayload # -# What we send to the consume! method +""" + ParsedPayload{B, C<:AbstractParsingContext} + +A payload of parsed results, which is passed to `consume!` after each `populate_result_buffer!` call. + +# Fields: +- `row_num::Int`: row number of the first row in the payload +- `len::Int`: number of rows in the payload +- `results::B`: parsed result buffer which was populated by `populate_result_buffer!` +- `parsing_ctx::C`: library-provided data (to distinguish JSONL and CSV processing) +- `chunking_ctx::ChunkingContext`: contains the raw bytes, synchronization objects and newline positions +- `eols_buffer_index::Int32`: The start index of the newline positions in `chunking_ctx.newline_positions` that this payload corresponds to. + +# See also: +- [`consume!`](@ref), [`AbstractParsingContext`](@ref), [`ChunkingContext`](@ref), [`AbstractResultBuffer`](@ref), [`PayloadOrderer`](@ref) +""" struct ParsedPayload{B, C<:AbstractParsingContext} - row_num::Int - len::Int - results::B - parsing_ctx::C - chunking_ctx::ChunkingContext - eols_buffer_index::Int32 + row_num::Int # row number of the first row in the payload + len::Int # number of rows in the payload + results::B # parsed result buffer which was populated by `populate_result_buffer!` + parsing_ctx::C # library-provided data (to distinguish JSONL and CSV processing) + chunking_ctx::ChunkingContext # internal data to facilitate chunking and synchronization + eols_buffer_index::Int32 # The start index of the newline positions in `chunking_ctx.newline_positions` that this payload corresponds to. end Base.length(payload::ParsedPayload) = payload.len last_row(payload::ParsedPayload) = payload.row_num + length(payload) - 1 @@ -24,7 +39,52 @@ function insertsorted!(arr::Vector{T}, x::T, by=identity) where {T} return idx end -# Like a Channel, but when you take! a Payload from it, it will be the next one in order + +""" + PayloadOrderer{B, C<:AbstractParsingContext} <: AbstractChannel{ParsedPayload{B,C}} + +A channel-like object that ensures that the payloads are consumed in order. + +To use the `PayloadOrderer` you should create your own `AbstractConsumeContext` that contains it +and override the `consume!` to only `put!` payloads in the `PayloadOrderer` and `take!` payloads +from it using a separate task. For example: + +``` +struct MyConsumeContext <: AbstractConsumeContext + orderer::PayloadOrderer{MyResultBuffer, MyParsingContext} +end + +# Forward the payloads, which will arrive in random order, to the orderer +function ChunkedBase.consume!(consume_ctx::MyConsumeContext, payload::ParsedPayload) + put!(consume_ctx.orderer, payload) +end + +# Expect `ChunkedBase.task_done!` to be called twice per payload. +# By default, we'd do it once after every `consume!` +# But we'll add another one in the task that takes from the orderer. +# This will make sure that the current chunk won't ger recycled after our task is done with it. +function ChunkedBase.setup_tasks!(::MyConsumeContext, chunking_ctx::ChunkingContext, ntasks::Int) + set!(chunking_ctx.counter, 2*ntasks) +end + +consume_ctx = MyConsumeContext(PayloadOrderer{MyResultBuffer, MyParsingContext}()) + +# Our task that needs to process the payloads in order +@spawn begin + while true + payload = take!(consume_ctx.orderer) + do_something_that_requires_ordered_results(payload) + task_done!(consume_ctx, payload.chunking_ctx) + end +end + +parse_file_parallel(lexer, parsing_ctx, consume_ctx, chunking_ctx, result_buf) +``` +NOTE: It is not safe to call `take!` from multiple tasks on a `PayloadOrderer`. + +# See also: +- [`ParsedPayload`](@ref) +""" mutable struct PayloadOrderer{B, C<:AbstractParsingContext} <: AbstractChannel{ParsedPayload{B,C}} queue::Channel{ParsedPayload{B,C}} expected_row::Int @@ -41,6 +101,7 @@ function _reenqueue_ordered!(queue::Channel{T}, waiting_room::Vector{T}, payload payload = first(waiting_room) if payload.row_num == (nrows + row) put!(queue, popfirst!(waiting_room)) + row = payload.row_num else break end @@ -51,10 +112,10 @@ function _reorder!(queue::Channel{T}, waiting_room::Vector{T}, payload::T, expec row = payload.row_num if row == expected_row _reenqueue_ordered!(queue, waiting_room, payload) - return false + return false # we don't need to keep searching, we found the next payload in order end insertsorted!(waiting_room, payload, x->x.row_num) - return true + return true # we need to keep searching the next payload in order end Base.put!(o::PayloadOrderer{B,C}, x::ParsedPayload{B,C}) where {B,C} = put!(o.queue, x) diff --git a/src/read_and_lex.jl b/src/read_and_lex.jl index bee9caa..4c51067 100644 --- a/src/read_and_lex.jl +++ b/src/read_and_lex.jl @@ -12,7 +12,7 @@ function readbytesall!(io::IO, buf, n::Integer) end function prepare_buffer!(io::IO, buf::Vector{UInt8}, last_newline_at::Int) - ptr = pointer(buf) + ptr = pointer(buf) # `buf` is rooted in ChunkingContext, so we shouldn't need to GC.@preserve it buffersize = length(buf) @inbounds if last_newline_at == 0 # This is the first time we saw the buffer, we'll fill it up and skip leading BOM @@ -34,8 +34,10 @@ function prepare_buffer!(io::IO, buf::Vector{UInt8}, last_newline_at::Int) end function check_any_valid_rows(lexer, chunking_ctx) + # we always prepend a 0 to newline_positions as a fake newline from previous chunk + # thus there must be at least 2 elements in newline_positions to have a valid row eols = chunking_ctx.newline_positions - if (length(eols) == 0 || (length(eols) == 1 && first(eols) == 0)) && !eof(lexer.io) # TODO: check done instead of eof? + if (length(eols) == 0 || (length(eols) == 1 && first(eols) == 0)) && !eof(lexer.io) close(lexer.io) throw(NoValidRowsInBufferError(length(chunking_ctx.bytes))) end @@ -52,12 +54,14 @@ function handle_file_end!(lexer::Lexer, eols, end_pos) end end - +# Fill the chunking_ctx.bytes buffer with bytes from the input and find newlines in it +# The trailing bytes between the last newline and the end of the buffer are copied to the +# beginning of the buffer and the rest of the buffer is refilled. function read_and_lex!(lexer::Lexer, chunking_ctx::ChunkingContext, _last_newline_at=last_newline_at(chunking_ctx)) @assert !lexer.done empty!(chunking_ctx.newline_positions) - push!(chunking_ctx.newline_positions, Int32(0)) + push!(chunking_ctx.newline_positions, Int32(0)) # fake newline from previous chunk if eof(lexer.io) # Catches the empty input case lexer.done = true return nothing @@ -65,7 +69,6 @@ function read_and_lex!(lexer::Lexer, chunking_ctx::ChunkingContext, _last_newlin bytes_read_in = prepare_buffer!(lexer.io, chunking_ctx.bytes, _last_newline_at) chunking_ctx.buffer_refills[] += 1 - # _last_newline_at == 0 && bytes_read_in == 0 && return nothing # only BOM / whitespace in the buffer start_pos = _last_newline_at == 0 ? 1 : length(chunking_ctx.bytes) - _last_newline_at + 1 end_pos = start_pos + bytes_read_in - 1 @@ -78,6 +81,8 @@ function read_and_lex!(lexer::Lexer, chunking_ctx::ChunkingContext, _last_newlin return nothing end +# Separate initial read and lex function for package that sniff the file first (e.g. to detect newline character) +# This function should be paired with `initial_lex!` to properly initialize the chunking context function initial_read!(io, chunking_ctx, skip_leading_whitespace=false) # First ingestion of raw bytes from io buf = chunking_ctx.bytes @@ -87,7 +92,6 @@ function initial_read!(io, chunking_ctx, skip_leading_whitespace=false) bytes_read_in = readbytesall!(io, buf, buffersize) chunking_ctx.buffer_refills[] += 1 - # bytes_read_in = _skip_over_initial_whitespace_and_bom!(io, buf, bytes_read_in) starts_with_bom = bytes_read_in > 2 && _hasBOM(buf) if skip_leading_whitespace @@ -107,7 +111,7 @@ function initial_read!(io, chunking_ctx, skip_leading_whitespace=false) # We found a non-space byte -- we'll left-shift the spaces before it so that the buffer # begins with a valid value and we'll try to refill the rest of the buffer. - # If first_valid_byte was already at the beginnig of the buffer, we don't have to do + # If first_valid_byte was already at the beginning of the buffer, we don't have to do # anything. skip_over = first_valid_byte - 1 if skip_over > 0 diff --git a/src/read_and_lex_utils.jl b/src/read_and_lex_utils.jl index 515b3a0..12c4da0 100644 --- a/src/read_and_lex_utils.jl +++ b/src/read_and_lex_utils.jl @@ -1,3 +1,5 @@ +# If we don't find any `\n` but we do find a `\r`, we assume the file uses `\r` as a newline, +# '\n' otherwise. function _detect_newline(buf, pos, len) len == 0 && return UInt8('\n') # empty file @assert 1 <= pos <= len <= length(buf) @@ -18,6 +20,10 @@ function _hasBOM(bytes::Vector{UInt8}) return @inbounds bytes[1] == 0xef && bytes[2] == 0xbb && bytes[3] == 0xbf end +# Either we were looking for `\n` as a newline char and then an empty row has +# two newline positions next to each other or there is a single byte between them +# and it's `\r`. Or we were looking for `\r` in which case we only consider two +# neighboring `\r` as an empty row. function _isemptyrow(prev_nl, next_nl, bytes) return prev_nl + 1 == next_nl || (prev_nl + 2 == next_nl && @inbounds(bytes[prev_nl+1]) == UInt8('\r')) end @@ -32,10 +38,7 @@ _input_to_io(input::IO, use_mmap::Bool) = false, input function _input_to_io(input::String, use_mmap::Bool) ios = open(input, "r") if !eof(ios) && peek(ios, UInt16) == 0x8b1f - # TODO: GzipDecompressorStream doesn't respect MmapStream reaching EOF for some reason - # io = CodecZlibNG.GzipDecompressorStream(use_mmap ? MmapStream(ios) : ios) - use_mmap && @warn "`use_mmap=true` is currently unsupported when reading gzipped files, using file io." - io = CodecZlibNG.GzipDecompressorStream(ios) + io = CodecZlibNG.GzipDecompressorStream(use_mmap ? MmapStream(ios) : ios) elseif use_mmap io = MmapStream(ios) else @@ -48,6 +51,7 @@ end # limit_eols! # +# We can set a limit in our `chunking_ctx` to limit the number of rows we parse function limit_eols!(chunking_ctx::ChunkingContext, row_num::Int) _limit = chunking_ctx.limit _limit == 0 && return false @@ -71,9 +75,17 @@ function _startswith(s::AbstractVector{UInt8}, soff::Integer, prefix::AbstractVe return true end _startswith(s::AbstractVector{UInt8}, prefix::AbstractVector{UInt8}) = _startswith(s, 0, prefix) +# nothing for a comment / prefix means we are not skipping commented rows _startswith(s, soff, prefix::Nothing) = false _startswith(s, prefix::Nothing) = false +# Skip rows at the beginning of the file, optionally skipping empty rows as well. +# If the inputs has fewer lines than `rows_to_skip`, we skip the whole input. +# If we exhaust the buffer during skipping, we refill it and continue skipping. +# If we specify comment in in `chunking_ctx`, we skip commented rows as well. +# If we specify `ignoreemptyrows=true`, we skip empty rows as well. +# If we'are skipping empty rows and/or comments, we might skip more rows than `rows_to_skip`, +# we'll continue skipping until we find a non-empty, non-commented row. function skip_rows_init!(lexer, chunking_ctx, rows_to_skip, ignoreemptyrows=false) input_is_empty = length(chunking_ctx.newline_positions) == 1 input_is_empty && (return 0) @@ -141,6 +153,7 @@ MmapStream(ios::IO) = MmapStream(ios, Mmap.mmap(ios, grow=false, shared=false), Base.close(m::MmapStream) = close(m.ios) Base.eof(m::MmapStream) = m.pos > length(m.x) function readbytesall!(io::MmapStream, buf, n::Int) + # `io` and `buf` are rooted in ChunkingContext, so we don't need to preserve them bytes_to_read = min(bytesavailable(io), n) unsafe_copyto!(pointer(buf), pointer(io.x) + io.pos - 1, bytes_to_read) io.pos += bytes_to_read diff --git a/test/e2e_tests.jl b/test/e2e_tests.jl index dfc1832..4cb2a85 100644 --- a/test/e2e_tests.jl +++ b/test/e2e_tests.jl @@ -35,17 +35,17 @@ ChunkedBase.task_done!(::TestConsumeContext, ::ChunkingContext) = nothing ### TestThrowingContext #################################################################### struct TestThrowingContext <: AbstractConsumeContext - tasks::Vector{Task} - conds::Vector{TaskCounter} + tasks::Base.IdSet{Task} + conds::Base.IdSet{TaskCounter} throw_row::Int end -TestThrowingContext(throw_row) = TestThrowingContext(Task[], ChunkedBase.TaskCounter[], throw_row) +TestThrowingContext(throw_row) = TestThrowingContext(Base.IdSet{Task}(), Base.IdSet{TaskCounter}(), throw_row) function ChunkedBase.consume!(ctx::TestThrowingContext, payload::ParsedPayload) t = current_task() c = payload.chunking_ctx.counter - c in ctx.conds || push!(ctx.conds, c) - t in ctx.tasks || push!(ctx.tasks, t) + push!(ctx.conds, c) + push!(ctx.tasks, t) payload.row_num >= ctx.throw_row && error("These contexts are for throwing, and that's all what they do") sleep(0.01) # trying to get the task off a fast path to claim everything from the parsing queue return nothing @@ -328,8 +328,8 @@ end ) end @assert !isempty(throw_ctx.tasks) - @test throw_ctx.tasks[1] === current_task() - @test throw_ctx.conds[1].exception isa ErrorException + @test only(throw_ctx.tasks) === current_task() + @test only(throw_ctx.conds).exception isa ErrorException end @testset "parallel" begin @@ -348,8 +348,8 @@ end sleep(0.2) @test length(throw_ctx.tasks) == nworkers @test all(istaskdone, throw_ctx.tasks) - @test throw_ctx.conds[1].exception isa CapturedException - @test throw_ctx.conds[1].exception.ex.msg == "These contexts are for throwing, and that's all what they do" + @test first(throw_ctx.conds).exception isa CapturedException + @test first(throw_ctx.conds).exception.ex.msg == "These contexts are for throwing, and that's all what they do" end end @@ -366,10 +366,9 @@ end ) end @assert !isempty(throw_ctx.tasks) - @test throw_ctx.tasks[1] === current_task() - @test throw_ctx.conds[1].exception isa ErrorException + @test only(throw_ctx.tasks) === current_task() + @test only(throw_ctx.conds).exception isa ErrorException end - @testset "parallel" begin throw_ctx = TestThrowingContext(typemax(Int)) # Only capture tasks, let IO do the throwing nworkers = min(3, Threads.nthreads()) @@ -385,10 +384,13 @@ end sleep(0.2) @test length(throw_ctx.tasks) == min(3, Threads.nthreads()) @test all(istaskdone, throw_ctx.tasks) - @test throw_ctx.conds[1].exception isa CapturedException - @test throw_ctx.conds[1].exception.ex.task.result.msg == "That should be enough data for everyone" - @test throw_ctx.conds[2].exception isa CapturedException - @test throw_ctx.conds[2].exception.ex.task.result.msg == "That should be enough data for everyone" + conds = collect(throw_ctx.conds) + cond = pop!(conds) + @test cond.exception isa CapturedException + @test cond.exception.ex.task.result.msg == "That should be enough data for everyone" + cond = pop!(conds) + @test cond.exception isa CapturedException + @test cond.exception.ex.task.result.msg == "That should be enough data for everyone" end end end diff --git a/test/runtests.jl b/test/runtests.jl index dd743c2..b108b38 100644 --- a/test/runtests.jl +++ b/test/runtests.jl @@ -459,6 +459,7 @@ end @testset "initial_lex!" begin lexer = NewlineLexers.Lexer(IOBuffer("1"), nothing, UInt8('\n')) ctx = ChunkingContext(4, 1, 0, nothing) + ctx.bytes .= false @assert lexer.done == false @assert ctx.newline_positions == [0] ChunkedBase.initial_lex!(lexer, ctx, 0) @@ -466,6 +467,7 @@ end lexer = NewlineLexers.Lexer(IOBuffer("1"), nothing, UInt8('\n')) ctx = ChunkingContext(4, 1, 0, nothing) + ctx.bytes .= false @assert lexer.done == false @assert ctx.newline_positions == [0] seekend(lexer.io) @@ -489,6 +491,7 @@ end lexer = NewlineLexers.Lexer(IOBuffer("1"), nothing, UInt8('\n')) ctx = ChunkingContext(4, 1, 0, nothing) + ctx.bytes .= false ctx.newline_positions.elements[1] = 1 @test_throws AssertionError ChunkedBase.initial_lex!(lexer, ctx, 0) @test_throws AssertionError ChunkedBase.initial_lex!(lexer, ctx, 5) @@ -496,6 +499,7 @@ end lexer = NewlineLexers.Lexer(IOBuffer("1"), nothing, UInt8('\n')) lexer.done = true ctx = ChunkingContext(4, 1, 0, nothing) + ctx.bytes .= false @test_throws AssertionError ChunkedBase.initial_lex!(lexer, ctx, 0) @test_throws AssertionError ChunkedBase.initial_lex!(lexer, ctx, 5)