C ++ /在大文件中跳过快速随机访问
C++ / Fast random access skipping in a large file
我有大文件,其中包含少量大数据集。每个数据集都包含一个名称和以字节为单位的数据集大小,允许跳过它并转到下一个数据集。
我想快速建立数据集名称的索引。文件示例大约 21MB,包含 88 个数据集。通过使用 std::ifstream
和 seekg()
在数据集之间跳过来快速读取 88 个名称大约需要 1300 毫秒,我想减少它。
所以实际上,我正在读取一个 21MB 文件中给定位置的 88 个大约 30 字节的块,这需要 1300 毫秒。
有没有办法改善这个问题,还是 OS 和文件系统限制?我是运行测试Windows7 64bit.
我知道在文件开头有一个完整的索引会更好,但是文件格式没有这个,我们也改不了。
你可以使用内存映射文件接口(我推荐boost's implementation.)
这会将文件打开到您的应用程序的虚拟页面中,以缩短查找时间,而无需返回到磁盘。
您可以扫描文件并使用单独文件中的键和索引制作您自己的 header。根据您的用例,您可以在程序启动时和每次文件更改时执行一次。
在访问大数据之前,在较小的文件中查找会为您提供所需的索引。
您可以使用多线程执行缓冲区排队过程。您可以创建一个自定义结构来存储各种数据量。
你说:
Each dataset contains a name and the dataset size in bytes, allowing to skip it and go to the next dataset.
因此,由于一遍又一遍地打开和关闭文件很慢,您可以一次读取所有文件并将其存储到一个完整的缓冲区对象中,然后解析它或将其存储成批次。这也取决于您是以文本模式还是二进制模式阅读文件的解析难易程度。稍后我将通过填充多个批次来演示后者,同时从文件中读取缓冲大小的数据量。
伪代码
struct Batch {
std::string name; // Name of Dataset
unsigned size; // Size of Dataset
unsigned indexOffset; // Index to next read location
bool empty = true; // Flag to tell if this batch is full or empty
std::vector<DataType> dataset; // Container of Data
};
std::vector<Batch> finishedBatches;
// This doesn't matter on the size of the data set; this is just a buffer size on how much memory to digest in reading the file
const unsigned bufferSize = "Set to Your Preference" 1MB - 4MB etc.
void loadDataFromFile( const std::string& filename, unsigned bufferSize, std::vector<Batch>& batches ) {
// Set ifstream's buffer size
// OpenFile For Reading and read in and upto buffer size
// Spawn different thread to populate the Batches and while that batch is loading
// in data read in that much buffer data again. You will need to have a couple local
// stack batches to work with. So if a batch is complete and you reached the next index
// location from the file you can fill another batch.
// When a single batch is complete push it into the vector to store that batch.
// Change its flag and clear its vector and you can then use that empty batch again.
// Continue this until you reached end of file.
}
这将是一个 2 线程系统。用于打开和读取文件以及从文件中查找的主线程,工作线程填充批次并将批次推入容器并交换以使用下一个批次。
我有大文件,其中包含少量大数据集。每个数据集都包含一个名称和以字节为单位的数据集大小,允许跳过它并转到下一个数据集。
我想快速建立数据集名称的索引。文件示例大约 21MB,包含 88 个数据集。通过使用 std::ifstream
和 seekg()
在数据集之间跳过来快速读取 88 个名称大约需要 1300 毫秒,我想减少它。
所以实际上,我正在读取一个 21MB 文件中给定位置的 88 个大约 30 字节的块,这需要 1300 毫秒。
有没有办法改善这个问题,还是 OS 和文件系统限制?我是运行测试Windows7 64bit.
我知道在文件开头有一个完整的索引会更好,但是文件格式没有这个,我们也改不了。
你可以使用内存映射文件接口(我推荐boost's implementation.)
这会将文件打开到您的应用程序的虚拟页面中,以缩短查找时间,而无需返回到磁盘。
您可以扫描文件并使用单独文件中的键和索引制作您自己的 header。根据您的用例,您可以在程序启动时和每次文件更改时执行一次。 在访问大数据之前,在较小的文件中查找会为您提供所需的索引。
您可以使用多线程执行缓冲区排队过程。您可以创建一个自定义结构来存储各种数据量。
你说:
Each dataset contains a name and the dataset size in bytes, allowing to skip it and go to the next dataset.
因此,由于一遍又一遍地打开和关闭文件很慢,您可以一次读取所有文件并将其存储到一个完整的缓冲区对象中,然后解析它或将其存储成批次。这也取决于您是以文本模式还是二进制模式阅读文件的解析难易程度。稍后我将通过填充多个批次来演示后者,同时从文件中读取缓冲大小的数据量。
伪代码
struct Batch {
std::string name; // Name of Dataset
unsigned size; // Size of Dataset
unsigned indexOffset; // Index to next read location
bool empty = true; // Flag to tell if this batch is full or empty
std::vector<DataType> dataset; // Container of Data
};
std::vector<Batch> finishedBatches;
// This doesn't matter on the size of the data set; this is just a buffer size on how much memory to digest in reading the file
const unsigned bufferSize = "Set to Your Preference" 1MB - 4MB etc.
void loadDataFromFile( const std::string& filename, unsigned bufferSize, std::vector<Batch>& batches ) {
// Set ifstream's buffer size
// OpenFile For Reading and read in and upto buffer size
// Spawn different thread to populate the Batches and while that batch is loading
// in data read in that much buffer data again. You will need to have a couple local
// stack batches to work with. So if a batch is complete and you reached the next index
// location from the file you can fill another batch.
// When a single batch is complete push it into the vector to store that batch.
// Change its flag and clear its vector and you can then use that empty batch again.
// Continue this until you reached end of file.
}
这将是一个 2 线程系统。用于打开和读取文件以及从文件中查找的主线程,工作线程填充批次并将批次推入容器并交换以使用下一个批次。