Voglio leggere singoli byte il più velocemente possibile da un file in un'applicazione D2. L'applicazione richiede byte per byte, quindi leggere più grandi blocchi di dati non è un'opzione per l'interfaccia al lettore.Il modo più veloce di leggere i byte in D2
Per questo ho creato alcune implementazioni banali in C++, Java, D2 a: https://github.com/gizmomogwai/performance.
Come si può vedere ho provato semplici letture, buffer nel codice dell'applicazione e file mappati in memoria. Per il mio caso la soluzione mappata in memoria ha funzionato meglio, ma la cosa strana è che D2 è più lento di java. Avrei sperato che D2 finisse tra C++ e Java (il codice C++ è compilato con -O3 -g, il codice D2 è compilato con -O -release).
Quindi, per favore dimmi cosa sto facendo male qui e come accelerare l'implementazione D2.
Per dare un'idea del caso d'uso qui è un'implementazione C++:
class StdioFileReader {
private:
FILE* fFile;
static const size_t BUFFER_SIZE = 1024;
unsigned char fBuffer[BUFFER_SIZE];
unsigned char* fBufferPtr;
unsigned char* fBufferEnd;
public:
StdioFileReader(std::string s) : fFile(fopen(s.c_str(), "rb")), fBufferPtr(fBuffer), fBufferEnd(fBuffer) {
assert(fFile);
}
~StdioFileReader() {
fclose(fFile);
}
int read() {
bool finished = fBufferPtr == fBufferEnd;
if (finished) {
finished = fillBuffer();
if (finished) {
return -1;
}
}
return *fBufferPtr++;
}
private:
bool fillBuffer() {
size_t l = fread(fBuffer, 1, BUFFER_SIZE, fFile);
fBufferPtr = fBuffer;
fBufferEnd = fBufferPtr+l;
return l == 0;
}
};
size_t readBytes() {
size_t res = 0;
for (int i=0; i<10; i++) {
StdioFileReader r("/tmp/shop_with_ids.pb");
int read = r.read();
while (read != -1) {
++res;
read = r.read();
}
}
return res;
}
che è molto più veloce rispetto alla soluzione "stesso" in D:
struct FileReader {
private FILE* fFile;
private static const BUFFER_SIZE = 8192;
private ubyte fBuffer[BUFFER_SIZE];
private ubyte* fBufferPtr;
private ubyte* fBufferEnd;
public this(string fn) {
fFile = std.c.stdio.fopen("/tmp/shop_with_ids.pb", "rb");
fBufferPtr = fBuffer.ptr;
fBufferEnd = fBuffer.ptr;
}
public int read(ubyte* targetBuffer) {
auto finished = fBufferPtr == fBufferEnd;
if (finished) {
finished = fillBuffer();
if (finished) {
return 0;
}
}
*targetBuffer = *fBufferPtr++;
return 1;
}
private bool fillBuffer() {
fBufferPtr = fBuffer.ptr;
auto l = std.c.stdio.fread(fBufferPtr, 1, BUFFER_SIZE, fFile);
fBufferEnd = fBufferPtr + l;
return l == 0;
}
}
size_t readBytes() {
size_t count = 0;
for (int i=0; i<10; i++) {
auto reader = FileReader("/tmp/shop_with_ids.pb");
ubyte buffer[1];
ubyte* p = buffer.ptr;
auto c = reader.read(p);
while (1 == c) {
++count;
c = reader.read(p);
}
}
return count;
}
Ho fatto qualche altra codifica non correlata in D e Java, (calcoli intensivi matematici), e risulta che Java è leggermente più veloce nei miei test. Suppongo che al momento non ci si debba aspettare che java sia molto più lento, il compilatore JIT è MOLTO bravo nell'ottimizzazione. –
Sì ... hai ragione ... Non mi aspetto che java sia molto più lento di cpp (che è ancora nel mio esempio dimostrativo usando il jit predefinito), ma il mio punto è che d è ancora più lento. Speravo di essere alla pari con cpp. – Gizmomogwai
Sì, l'ho fatto anche io, quando ho convertito un algoritmo Java in D alcuni mesi fa. Penso che abbiano alcune stranezze da risolvere nell'ottimizzazione del codice. o forse il GC è davvero pessimo, e lento, quindi prova a girarlo? –