From 77aded7a050304b87b9d8a75cba87ed1032f2398 Mon Sep 17 00:00:00 2001 From: IonutParau Date: Sun, 5 Apr 2026 03:33:26 +0200 Subject: [PATCH] rip the drive cache had huge oversight and was just a bad idea --- TODO.md | 21 ++++++++++++++++++++- src/main.c | 14 +++++++------- src/neonucleus.c | 41 ++++------------------------------------- src/neonucleus.h | 3 --- 4 files changed, 31 insertions(+), 48 deletions(-) diff --git a/TODO.md b/TODO.md index cd55485..4f70d82 100644 --- a/TODO.md +++ b/TODO.md @@ -1,6 +1,7 @@ # For MVP functionality -- implement the RAID merger algorithm (merges multiple drives or filesystems together into a bigger config) +- move SSDs to ossm_flash +- remove HDD cachelines (they're pointless) - write a tester OS, basically a menu with tests to run - tmpfs (rework the whole thing) - device info @@ -67,6 +68,24 @@ NOTE: we're mostly bottlenecked by the architecture (typically a Lua VM) and the - make signals use a circular buffer instead of a simple array - use more arenas if possible +# Component extensions + +## filesystem + +- `getMaxRead(): integer`, returns the maximum size of a read; effectively the ideal buffer size + +## drive + +- `readUByte(byte: integer): integer`, reads an unsigned byte + +## ossm_flash + +- `getLabel(): string?`, to get the label +- `setLabel(label: string?): string?`, to set the label +- `isReadonly(): boolean`, check if the SSD is read-only +- `readUByte(byte: integer): integer`, reads an unsigned byte +- `getWearLevel(): number`, returns a number from 0 to 100, where 0 means full life and 100 means dead + # Unique components Subject to change, still being discussed with the other NeoFlock members. diff --git a/src/main.c b/src/main.c index 331fe2b..c0c8bda 100644 --- a/src/main.c +++ b/src/main.c @@ -389,28 +389,28 @@ int main(int argc, char **argv) { "component.invoke(g, 'bind', s, true)\n" "component.invoke(g, 'set', 1, 1, 'starting sequential bench...')\n" "local start = computer.uptime()\n" - "local cap = component.invoke(d, 'getCapacity')\n" "local ss = component.invoke(d, 'getSectorSize')\n" + "local cap = component.invoke(d, 'getCapacity')\n" "local bc = cap / ss\n" - "for i=1,bc do component.invoke(d, 'readSector', i) end\n" + "local tc = 256\n" + "for i=1,tc do component.invoke(d, 'readSector', i) end\n" "local now = computer.uptime()\n" "component.invoke(g, 'set', 1, 2, 'took ' .. (now - start) .. 's')\n" - "component.invoke(g, 'set', 1, 3, 'sequential read speed: ' .. (cap / (now - start)) .. 'B/s')\n" + "component.invoke(g, 'set', 1, 3, 'sequential read speed: ' .. (tc * ss / (now - start)) .. 'B/s')\n" "while computer.uptime() < now + 3 do computer.pullSignal(0.05) end\n" "component.invoke(g, 'bind', s, true)\n" "component.invoke(g, 'set', 1, 1, 'starting random bench...')\n" "start = computer.uptime()\n" - "local rand = 256\n" - "for i=1,rand do local i = math.random(1, bc) component.invoke(d, 'readSector', i) end\n" + "for i=1,tc do local i = math.random(1, bc) component.invoke(d, 'readSector', i) end\n" "now = computer.uptime()\n" "component.invoke(g, 'set', 1, 2, 'took ' .. (now - start) .. 's')\n" - "component.invoke(g, 'set', 1, 3, 'random read speed: ' .. (rand * ss / (now - start)) .. 'B/s')\n" + "component.invoke(g, 'set', 1, 3, 'random read speed: ' .. (tc * ss / (now - start)) .. 'B/s')\n" "while computer.uptime() < now + 3 do computer.pullSignal(0.05) end\n" "computer.shutdown(true)\n" ; nn_Drive driveconf; nn_Drive driveparts[] = { - nn_floppySSD, + nn_defaultSSDs[3], }; nn_mergeDrives(&driveconf, driveparts, sizeof(driveparts) / sizeof(driveparts[0])); nn_Component *testDrive = ncl_createDrive(u, NULL, &driveconf, testDriveData, strlen(testDriveData), false); diff --git a/src/neonucleus.c b/src/neonucleus.c index 2e756df..21ca59e 100644 --- a/src/neonucleus.c +++ b/src/neonucleus.c @@ -2488,7 +2488,6 @@ const nn_Drive nn_defaultDrives[4] = { .capacity = 1 * NN_MiB, .sectorSize = 512, .platterCount = 2, - .cacheLineSize = 2, .readsPerTick = 20, .writesPerTick = 10, .rpm = 3600, @@ -2499,7 +2498,6 @@ const nn_Drive nn_defaultDrives[4] = { .capacity = 2 * NN_MiB, .sectorSize = 512, .platterCount = 4, - .cacheLineSize = 4, .readsPerTick = 30, .writesPerTick = 15, .rpm = 5400, @@ -2510,7 +2508,6 @@ const nn_Drive nn_defaultDrives[4] = { .capacity = 4 * NN_MiB, .sectorSize = 512, .platterCount = 8, - .cacheLineSize = 8, .readsPerTick = 40, .writesPerTick = 20, .rpm = 7200, @@ -2521,7 +2518,6 @@ const nn_Drive nn_defaultDrives[4] = { .capacity = 8 * NN_MiB, .sectorSize = 512, .platterCount = 16, - .cacheLineSize = 16, .readsPerTick = 60, .writesPerTick = 30, .rpm = 7200, @@ -2534,7 +2530,6 @@ const nn_Drive nn_floppyDrive = { .capacity = 512 * NN_KiB, .sectorSize = 512, .platterCount = 1, - .cacheLineSize = 2, .readsPerTick = 10, .writesPerTick = 5, .rpm = 1800, @@ -2547,7 +2542,6 @@ const nn_Drive nn_defaultSSDs[4] = { .capacity = 512 * NN_KiB, .sectorSize = 512, .platterCount = 2, - .cacheLineSize = 2, .readsPerTick = 10, .writesPerTick = 5, .rpm = 0, @@ -2558,7 +2552,6 @@ const nn_Drive nn_defaultSSDs[4] = { .capacity = 1 * NN_MiB, .sectorSize = 512, .platterCount = 4, - .cacheLineSize = 4, .readsPerTick = 15, .writesPerTick = 7, .rpm = 0, @@ -2569,7 +2562,6 @@ const nn_Drive nn_defaultSSDs[4] = { .capacity = 2 * NN_MiB, .sectorSize = 512, .platterCount = 8, - .cacheLineSize = 8, .readsPerTick = 20, .writesPerTick = 10, .rpm = 0, @@ -2580,7 +2572,6 @@ const nn_Drive nn_defaultSSDs[4] = { .capacity = 4 * NN_MiB, .sectorSize = 512, .platterCount = 16, - .cacheLineSize = 16, .readsPerTick = 30, .writesPerTick = 15, .rpm = 0, @@ -2593,7 +2584,6 @@ const nn_Drive nn_floppySSD = { .capacity = 256 * NN_KiB, .sectorSize = 512, .platterCount = 1, - .cacheLineSize = 2, .readsPerTick = 5, .writesPerTick = 2, .rpm = 0, @@ -4067,30 +4057,16 @@ static void nn_drive_seekPenalty(nn_Computer *C, size_t lastSector, size_t newSe } else { sectorDelta = lastSector - newSector; } - if(sectorDelta < drive->cacheLineSize) { - sectorDelta = 0; // within cache - } else { - // align to cache line - if(sectorDelta % drive->cacheLineSize != 0) { - sectorDelta += drive->cacheLineSize - sectorDelta % drive->cacheLineSize; - } - } // RPM over the number of sectors, over 60 seconds. double latency = (double)sectorDelta * 60 / ((double)drive->rpm * maxSectors); nn_addIdleTime(C, latency); } -// 1-indexed -static size_t nn_drive_cachelineOf(size_t sector, size_t perCache) { - return (sector - 1) / perCache; -} - typedef enum nn_DrvNum { NN_DRVNUM_GETCAPACITY, NN_DRVNUM_GETSECTORSIZE, NN_DRVNUM_GETPLATTERCOUNT, - NN_DRVNUM_GETCACHESIZE, NN_DRVNUM_ISRO, NN_DRVNUM_GETLABEL, NN_DRVNUM_SETLABEL, @@ -4131,9 +4107,8 @@ static nn_Exit nn_drvHandler(nn_ComponentRequest *request) { return NN_OK; } size_t ss = state->drive.sectorSize; - size_t cacheline = state->drive.cacheLineSize; - size_t cacheByteSize = cacheline * ss; size_t sectorCount = state->drive.capacity / ss; + size_t perPlatter = sectorCount / state->drive.platterCount; unsigned int method = request->methodIdx; if(method == NN_DRVNUM_GETCAPACITY) { request->returnCount = 1; @@ -4143,10 +4118,6 @@ static nn_Exit nn_drvHandler(nn_ComponentRequest *request) { request->returnCount = 1; return nn_pushinteger(C, ss); } - if(method == NN_DRVNUM_GETCACHESIZE) { - request->returnCount = 1; - return nn_pushinteger(C, cacheline); - } if(method == NN_DRVNUM_ISRO) { dreq.action = NN_DRIVE_ISRO; e = state->handler(&dreq); @@ -4188,11 +4159,9 @@ static nn_Exit nn_drvHandler(nn_ComponentRequest *request) { if(e) return e; curPos = dreq.curpos; - if(nn_drive_cachelineOf(curPos, cacheline) != nn_drive_cachelineOf(sec, cacheline)) { - nn_drive_seekPenalty(C, curPos, sec, &state->drive); - nn_costComponent(C, request->compAddress, state->drive.readsPerTick); - nn_removeEnergy(C, state->drive.dataEnergyCost * cacheline * ss); - } + nn_drive_seekPenalty(C, curPos, sec, &state->drive); + nn_costComponent(C, request->compAddress, state->drive.readsPerTick); + nn_removeEnergy(C, state->drive.dataEnergyCost * ss); char *sector = nn_alloc(ctx, ss); if(sector == NULL) return NN_ENOMEM; @@ -4222,7 +4191,6 @@ nn_Component *nn_createDrive(nn_Universe *universe, const char *address, const n [NN_DRVNUM_GETCAPACITY] = {"getCapacity", "function(): integer - Get drive capacity", NN_DIRECT}, [NN_DRVNUM_GETSECTORSIZE] = {"getSectorSize", "function(): integer - Get sector size", NN_DIRECT}, [NN_DRVNUM_GETPLATTERCOUNT] = {"getPlatterCount", "function(): integer - Get number of platters on this drive", NN_DIRECT}, - [NN_DRVNUM_GETCACHESIZE] = {"getCacheSize", "function(): integer - Get number of sectors cached in a single read", NN_DIRECT}, [NN_DRVNUM_ISRO] = {"isReadOnly", "function(): boolean - Get whether the drive is read-only", NN_DIRECT}, [NN_DRVNUM_GETLABEL] = {"getLabel", "function(): string? - Get drive label", NN_DIRECT}, [NN_DRVNUM_SETLABEL] = {"setLabel", "function(label: string?): string - Set drive label", NN_INDIRECT}, @@ -4272,7 +4240,6 @@ bool nn_mergeDrives(nn_Drive *merged, const nn_Drive *drives, size_t len) { merged->dataEnergyCost += d.dataEnergyCost; merged->rpm += d.rpm; merged->capacity += d.capacity; - merged->cacheLineSize += d.cacheLineSize; merged->platterCount += d.platterCount; } merged->readsPerTick /= len; diff --git a/src/neonucleus.h b/src/neonucleus.h index ad166cb..1253308 100644 --- a/src/neonucleus.h +++ b/src/neonucleus.h @@ -1094,9 +1094,6 @@ typedef struct nn_Drive { // However, if it has 2 platters, it'd be seen as 1 to 4 being at the same angle as 5 to 8, which // would mean only 3 rotations. size_t platterCount; - // how many sectors are cached together. - // Each platter has "its own cache." - size_t cacheLineSize; // how many reads can be issued per tick. // Anything that kicks out the current cacheline counts as a read. size_t readsPerTick;