Speed up BResource loading

The code to parse the resource table reads one entry at a time because
the table size isn't known. This resulted in a lot of read syscalls,
each reading just 12 bytes. Use a BBufferIO to buffer these and reduce
the number of syscalls. This helps especially when there are lot of
resources, for example in libbe with all the country flags.

It also removes some spam from strace output for all these read calls.

Change-Id: Ib165a0eacc2bc5f3d319c22c2fac4f439efbdef2
Reviewed-on: https://review.haiku-os.org/c/haiku/+/2858
Reviewed-by: Rene Gollent <[email protected]>
This commit is contained in:
Adrien Destugues
2020-06-01 14:09:54 +00:00
committed by waddlesplash
parent 6178aeb315
commit 1ed08f5856
3 changed files with 21 additions and 18 deletions
+2 -1
View File
@@ -83,7 +83,8 @@ private:
const PEFContainerHeader& pefHeader); const PEFContainerHeader& pefHeader);
void _ReadHeader(resource_parse_info& parseInfo); void _ReadHeader(resource_parse_info& parseInfo);
void _ReadIndex(resource_parse_info& parseInfo); void _ReadIndex(resource_parse_info& parseInfo);
bool _ReadIndexEntry(resource_parse_info& parseInfo, bool _ReadIndexEntry(BPositionIO& buffer,
resource_parse_info& parseInfo,
int32 index, uint32 tableOffset, int32 index, uint32 tableOffset,
bool peekAhead); bool peekAhead);
void _ReadInfoTable(resource_parse_info& parseInfo); void _ReadInfoTable(resource_parse_info& parseInfo);
+1
View File
@@ -10,6 +10,7 @@ SEARCH_SOURCE += [ FDirName $(HAIKU_TOP) src kits support ] ;
BuildPlatformMergeObjectPIC <libbe_build>support_kit.o : BuildPlatformMergeObjectPIC <libbe_build>support_kit.o :
Archivable.cpp Archivable.cpp
BlockCache.cpp BlockCache.cpp
BufferIO.cpp
ByteOrder.cpp ByteOrder.cpp
CompressionAlgorithm.cpp CompressionAlgorithm.cpp
DataIO.cpp DataIO.cpp
+18 -17
View File
@@ -17,7 +17,7 @@
#include <stdio.h> #include <stdio.h>
#include <AutoDeleter.h> #include <AutoDeleter.h>
#include <BufferIO.h>
#include <Elf.h> #include <Elf.h>
#include <Exception.h> #include <Exception.h>
#include <Pef.h> #include <Pef.h>
@@ -781,9 +781,11 @@ ResourceFile::_ReadIndex(resource_parse_info& parseInfo)
{ {
int32& resourceCount = parseInfo.resource_count; int32& resourceCount = parseInfo.resource_count;
off_t& fileSize = parseInfo.file_size; off_t& fileSize = parseInfo.file_size;
BBufferIO buffer(&fFile, 2048, false);
// read the header // read the header
resource_index_section_header header; resource_index_section_header header;
read_exactly(fFile, kResourceIndexSectionOffset, &header, read_exactly(buffer, kResourceIndexSectionOffset, &header,
kResourceIndexSectionHeaderSize, kResourceIndexSectionHeaderSize,
"Failed to read the resource index section header."); "Failed to read the resource index section header.");
// check the header // check the header
@@ -820,6 +822,7 @@ ResourceFile::_ReadIndex(resource_parse_info& parseInfo)
"offset. Is: %lu, should be: %lu.", "offset. Is: %lu, should be: %lu.",
unknownSectionOffset, kUnknownResourceSectionSize); unknownSectionOffset, kUnknownResourceSectionSize);
} }
// info table offset and size // info table offset and size
uint32 infoTableOffset = _GetInt(header.rish_info_table_offset); uint32 infoTableOffset = _GetInt(header.rish_info_table_offset);
uint32 infoTableSize = _GetInt(header.rish_info_table_size); uint32 infoTableSize = _GetInt(header.rish_info_table_size);
@@ -827,6 +830,7 @@ ResourceFile::_ReadIndex(resource_parse_info& parseInfo)
throw Exception(B_IO_ERROR, "Invalid info table location."); throw Exception(B_IO_ERROR, "Invalid info table location.");
parseInfo.info_table_offset = infoTableOffset; parseInfo.info_table_offset = infoTableOffset;
parseInfo.info_table_size = infoTableSize; parseInfo.info_table_size = infoTableSize;
// read the index entries // read the index entries
uint32 indexTableOffset = indexSectionOffset uint32 indexTableOffset = indexSectionOffset
+ kResourceIndexSectionHeaderSize; + kResourceIndexSectionHeaderSize;
@@ -836,8 +840,8 @@ ResourceFile::_ReadIndex(resource_parse_info& parseInfo)
bool tableEndReached = false; bool tableEndReached = false;
for (int32 i = 0; !tableEndReached && i < maxResourceCount; i++) { for (int32 i = 0; !tableEndReached && i < maxResourceCount; i++) {
// read one entry // read one entry
tableEndReached = !_ReadIndexEntry(parseInfo, i, indexTableOffset, tableEndReached = !_ReadIndexEntry(buffer, parseInfo, i,
(i >= resourceCount)); indexTableOffset, (i >= resourceCount));
if (!tableEndReached) if (!tableEndReached)
actualResourceCount++; actualResourceCount++;
} }
@@ -855,41 +859,37 @@ ResourceFile::_ReadIndex(resource_parse_info& parseInfo)
bool bool
ResourceFile::_ReadIndexEntry(resource_parse_info& parseInfo, int32 index, ResourceFile::_ReadIndexEntry(BPositionIO& buffer,
uint32 tableOffset, bool peekAhead) resource_parse_info& parseInfo, int32 index, uint32 tableOffset,
bool peekAhead)
{ {
off_t& fileSize = parseInfo.file_size; off_t& fileSize = parseInfo.file_size;
//
bool result = true; bool result = true;
resource_index_entry entry; resource_index_entry entry;
// read one entry // read one entry
off_t entryOffset = tableOffset + index * kResourceIndexEntrySize; off_t entryOffset = tableOffset + index * kResourceIndexEntrySize;
read_exactly(fFile, entryOffset, &entry, kResourceIndexEntrySize, read_exactly(buffer, entryOffset, &entry, kResourceIndexEntrySize,
"Failed to read a resource index entry."); "Failed to read a resource index entry.");
// check, if the end is reached early // check, if the end is reached early
if (result && check_pattern(entryOffset, &entry, if (result && check_pattern(entryOffset, &entry,
kResourceIndexEntrySize / 4, fHostEndianess)) { kResourceIndexEntrySize / 4, fHostEndianess)) {
if (!peekAhead) {
// Warnings::AddCurrentWarning("Unexpected end of resource index "
// "table at index: %ld (/%ld).",
// index + 1, resourceCount);
}
result = false; result = false;
} }
uint32 offset = _GetInt(entry.rie_offset); uint32 offset = _GetInt(entry.rie_offset);
uint32 size = _GetInt(entry.rie_size); uint32 size = _GetInt(entry.rie_size);
// check the location // check the location
if (result && offset + size > fileSize) { if (result && offset + size > fileSize) {
if (peekAhead) { if (!peekAhead) {
// Warnings::AddCurrentWarning("Invalid data after resource index "
// "table.");
} else {
throw Exception(B_IO_ERROR, "Invalid resource index entry: index: " throw Exception(B_IO_ERROR, "Invalid resource index entry: index: "
"%ld, offset: %lu (%lx), size: %lu (%lx).", index + 1, offset, "%ld, offset: %lu (%lx), size: %lu (%lx).", index + 1, offset,
offset, size, size); offset, size, size);
} }
result = false; result = false;
} }
// add the entry // add the entry
if (result) { if (result) {
ResourceItem* item = new(std::nothrow) ResourceItem; ResourceItem* item = new(std::nothrow) ResourceItem;
@@ -901,6 +901,7 @@ ResourceFile::_ReadIndexEntry(resource_parse_info& parseInfo, int32 index,
throw Exception(B_NO_MEMORY); throw Exception(B_NO_MEMORY);
} }
} }
return result; return result;
} }