Quiero leer bytes únicos lo más rápido posible desde un archivo a una aplicación D2. La aplicación necesita bytes por byte, por lo que leer bloques de datos más grandes no es una opción para la interfaz del lector.La forma más rápida de leer bytes en D2
Para esto he creado algunas implementaciones triviales en C++, Java, D2 en: https://github.com/gizmomogwai/performance.
Como puede ver, probé lecturas simples, almacenamientos intermedios en el código de la aplicación y en los archivos mapeados en la memoria. Para mi caso de uso, la solución mapeada de memoria funcionó mejor, pero lo extraño es que D2 es más lento que Java. Hubiera esperado que D2 aterrizara entre C++ y Java (el código C++ está compilado con -O3 -g, el código D2 está compilado con -O -release).
Así que por favor dígame qué estoy haciendo mal aquí y cómo acelerar la implementación de D2.
Para dar una idea del caso de uso que aquí hay una implementación en 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;
}
que es mucho más rápido en comparación con la "misma" solución de 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;
}
He hecho algunos otros códigos no relacionados en D y Java, (cálculos matemáticos intensivos), y resulta que Java es marginalmente más rápido en mis pruebas. Supongo que no deberías esperar que Java sea mucho más lento hoy en día, el compilador JIT es MUY bueno para la optimización. –
Sí ... tienes razón ... No espero que Java sea mucho más lento que cpp (que todavía está en mi ejemplo de demostración usando el jit predeterminado), pero mi punto es que d es aún más lento. Esperaba estar a la par con cpp. – Gizmomogwai
Sí, también lo hice, cuando convertí un algoritmo de Java a D hace unos meses. Creo que tienen algunas peculiaridades para corregir en la optimización del código. o tal vez el GC es realmente malo, y lento, así que intente cambiar eso? –