Здравствуйте.
Я пытаюсь реализовать дессериализацию в объекты из большого json файла. Хочется сделать это как можно быстрее, поэтому я решил считывать файл по частям, закидывая эти части в вектор, а в другом потоке я использую считанные данные для дессериализации, тем самым уменьшая время простоя в ожидании завершения считывания из файла.
Более коротко: есть два потока, в одном потоке в цикле считывается файл кусками и кладется в вектор, в другом потоке этот вектор читается (.len(), обращение по индексу, ничего криминального) .
Проблема в том, что на больших файлах у меня выпадает ошибка STATUS_ACCESS_VIOLATION. Я понял, что выпадает она на моменте append'а одного вектора к другому. Моя гипотеза заключается в том, что, видимо, существует какой то race condition, хотя на первый взгляд, не должно.
main:
mod file_reader;
mod json_consumer;
mod specification;
mod frame;
mod pixel;
use file_reader::read_on_the_fly;
use std::thread;
use std::alloc::handle_alloc_error;
use std::time::{Duration, Instant};
use crate::json_consumer::{deserialize_on_the_fly};
use crate::frame::Frame;
fn main() {
static mut CHAR_BUFFER: Vec<u8> = Vec::new();
static mut FRAME_BUFFER: Vec<frame::Frame> = Vec::new();
static mut IS_FILE_READ: bool = false;
static mut SPECS: specification::Specification = specification::Specification { height: 0, width: 0, frames: 0 };
let reader_handle = thread::spawn(|| unsafe {
let start = Instant::now();
let res = read_on_the_fly("file5_1160_786.json".to_string(), &mut CHAR_BUFFER, &mut IS_FILE_READ);
if res.is_ok() {
println!("\nFILE READ: done, elapsed time is {:?}", start.elapsed().as_secs_f64());
} else {
println!("\nFILE READ: fail");
}
});
let json_handle = thread::spawn(|| unsafe {
let start = Instant::now();
let res = deserialize_on_the_fly(&CHAR_BUFFER, &mut SPECS, &mut FRAME_BUFFER, &mut IS_FILE_READ);
if res.is_ok() {
println!("\nDESERIALIZE: done, elapsed time is {:?}", start.elapsed().as_secs_f64());
} else {
println!("\nDESERIALIZE: fail");
}
});
json_handle.join();
reader_handle.join();
}
Вот тут я считываю:
use std::io;
use std::io::{Read, BufReader};
use std::fs::File;
use std::str;
use std::thread::sleep;
use std::time::Duration;
pub fn read_on_the_fly(path: String, buffer: &mut Vec<u8>, is_file_read: &mut bool) -> Result<(), io::Error> {
static BUFF_SIZE: usize = 8192;
let mut file = File::open(path)?;
let mut br = BufReader::with_capacity(BUFF_SIZE, file);
let mut tmp_buff = vec![0; BUFF_SIZE];
while br.read(&mut tmp_buff)? != 0 {
buffer.append(&mut tmp_buff.clone());
}
*is_file_read = true;
Ok(())
}
Функция из второго потока довольно большая, но все, что происходит с общим вектором - это конструкции типа for i in 0..buff.len(), обращение по индексу и
push(buff[i] as char) в другой вектор, может быть дело в этом?
Спасибо.