figura-profiler banner

figura-profiler

3 devlogs
11h 7m 42s

Performance and instruction usage analyzer for Figura (a Minecraft mod).

Loading README...

penguinencounter

did you know there’s a 2000 character limit on devlogs? I sure didn’t until after I had written a really big one with code examples and then it rejected me.


tldr: rewrote database wrapper. added SQLite WAL support. tried to fix concurrency. found out the hard way that you really need retries on SQL operations.


the whole thing, for all the storytelling score:
https://gist.github.com/penguinencounter/1ec89dc025b8b400c61517d37467728b


also, the reason why the attachment is weird: https://github.com/hackclub/flavortown/issues/1086
(I have to upload a new copy of that image every time I edit the text :P)

Attachment
0
penguinencounter

Did some database design:

  • profile_meta table; single row, contains schema versioning information

  • sources: source attachments

  • channels: groups that users may want to track, like TICK, or RENDER. could be continuous or not

  • events: collections of steps, like a single tick or frame. instruction count and timing are totaled under a single event to measure overall performance / permission level impact

    • can have a parent event (ex. ITEM_RENDER has RENDER as a parent)
  • steps: individual actions within a script. instructions, function calls, detailed timings

  • Added method to automatically set up a blank database with the current schema version.

  • Added method to apply database migrations in the future.

  • Added method to copy a on-disk database into a temporary database

    • this is done with a RESTORE FROM command, which is not real SQLite and gets intercepted by the JDBC connector. As a result, you can’t do this with a prepared statement, so manual sanitization goes brrrr
newConn.createStatement().use {
    val syntax = when {
        url.contains("\"") && url.contains("\'") -> throw SQLException("Cannot unmount database: no safe quote type for $url")
        url.contains("\'") -> "RESTORE FROM \"$url\""
        else -> "RESTORE FROM '$url'"
    }
    @Suppress("SqlSourceToSinkFlow")
    it.executeUpdate(syntax)
}
Attachment
0
penguinencounter

Project Setup

Created a new project based on https://github.com/FallingColors/hexdummy.
This is a Hex Casting addon template, but it has the best Architectury+Kotlin build system I’ve seen so far, so we’re going to use it for something completely unrelated.

  • tore out all the Hex Casting stuff
    • kept PKPCPBP for the JSON5 preprocessor
  • added Figura dependencies
    • figura itself - figura-common & figura-fabric & figura-forge
    • its transitive dependencies, figura-luaj-core, figura-luaj-jse, nvwebsocketclient, oggus, concentus, and fabricPermissionsApi
  • updated MixinExtras
  • upgraded Loom to 1.13
    • build JDK must be at least 21
    • upgraded kotlin to 2.2.21
  • added SQLite JDBC library (plan is to make profiler files SQLite databases)

Actual Mod Code

  • added hooks for the start and end of function calls, as well as every instruction executed in Lua bytecode
  • found out that LuaJ’s LuaClosure::execute method has bad control flow and causes @Expression from MixinExtras to get stuck in an infinite loop for some reason??
Attachment
Attachment
1

Comments

developergirishgiri

nice plz give me vote also and follow me