C-style structs on the JVM!

Related tags

Kotlin Strukt
Overview

Strukt

C-style structs on the JVM!

ZERO garbage, ZERO reflection, ZERO code generation.
EASY to use, and with INCREDIBLE performance.

Maven Central Build Status license


Declaring Strukts to manage your Strukt

First you need to create a Strukts which manages your Strukt (allocates, frees, etc.).

Fixed: uses a single memory allocation and addresses are given with an offset. This is the fastest option available.

object Points : FixedStrukts(Point::class, capacity)

Persisted fixed: same as above, except uses a memory-mapped file rather than system memory and persists to disk. This means you can allocate with as much space as disk space, rather than RAM. There is practically no performance penalty for using this over .fixed(capacity)!

object Points : FixedStrukts(Point::class, capacity, persistedTo: File|String)

Elastic: similar to .fixed(capacity) except will dynamically resize, and has a performance penalty of a few operations for that capability.

object Points : ElasticStrukts(Point::class, initialCapacity = 1024, growthFactor = 2.0)

Pointed: uses a laid-out pointer system, this option supports unlimited allocations without any "resizing" necessary. Note: Since a memory allocation and a memory copy is necessary, this has slow allocations.

object Points : PointedStrukts(Point::class)

Declaring fields of your Strukt

You need to declare your fields within your Struktss using delegates to the default value.

The value you delegate to determines the field's type, and the default value for each allocation -- in this case it's an Int of the default value 0 for both.

object Points : ElasticStrukts(Point::class) {
	val x by 0
	val y by 0
}

All primitive types are supported, and even enums:

enum class Type { DEFAULT, SPECIAL }

object Points : ElasticStrukts(Point::class) {
        val x by 0
        val y by 0
        val type by Type.DEFAULT  
}

Declaring your inline Strukt

inline class Point(override val address: Long = Points()) : Strukt {
	var x
		get() = Points.x(address)
		set(x) = Points.x(address, x)
	var y
		get() = Points.y(address)
		set(y) = Points.y(address, y)
}

Because of the way inlining works, you'll notice that we need to provide virtual fields using our previously defined fields.

You should also notice the use of Strukts.invoke as a default value for allocating our address.

Allocating a Strukt

The syntax for allocation is the same as a regular object!

For the above Point example, this might look like:

val example = Point()

Accessing fields

Accessing fields is exactly like normal objects!

example.y = 123
println("x: ${example.x}, y: ${example.y}") // 0, 123

Freeing a Strukt

To free any Strukt, you can use:

Points.free(example.address)

The reason this longer syntax is necessary is because we want to avoid "generic" type use of our inline class, to prevent creating boxed instances.

Thread Safety

It's easy to make your fields thread-safe! Just annotate them with @ThreadSafe and use a ThreadSafeType (NONE, VOLATILE, or SYNCHRONIZED).

import org.jire.strukt.ThreadSafeType.*

object Points : ElasticStrukts(Point::class) {
  @ThreadSafe(VOLATILE) val x by 0
  @ThreadSafe(SYNCHRONIZED) val y by 0
}

Using in Java

It's not too hard to define and use a Strukt in Java!

public interface Point extends Strukt {
	
	Strukts points = Strukts.elastic(Point.class);
	
	IntField x = points.intField(0);
	IntField y = points.intField(0, ThreadSafeType.VOLATILE);
	
	static long allocate() {
		return points.allocate();
	}

}

You can then use it like so:

long example = Point.allocate();

Point.y.set(example, 123);
System.out.println("x: " + Point.x.get(example) + ", y: " + Point.y.get(example)); // 0, 123

Performance

Benchmark sources: https://github.com/Jire/Strukt/tree/master/src/jmh/kotlin/org/jire/strukt/benchmarks

Test Bench

  • OS: Windows 10 Pro 64-bit (10.0, Build 19042)
  • CPU: Intel(R) Core(TM) i7-6700K CPU @ 4.60GHz (8 CPUs), ~4.6GHz
  • RAM: 2x 16GB DDR4-2100MHz
  • JMH version: 1.25
  • VM version: JDK 1.8.0_271, Java HotSpot(TM) 64-Bit Server VM, 25.271-b09
  • VM options: Tested on an Intel i7 6700K @ 4.6GHz with default Oracle JDK 8 VM parameters on Windows 10:
Benchmark                                  Mode  Cnt          Score   Error  Units

HeapRead.read                             thrpt       434769304.174          ops/s
PointedRead.read                          thrpt       372296437.498          ops/s
FixedRead.read                            thrpt       438208243.968          ops/s
ElasticRead.read                          thrpt       418701531.606          ops/s

HeapWrite.write                           thrpt       561591456.153          ops/s
PointedWrite.write                        thrpt       622915634.215          ops/s
FixedWrite.write                          thrpt       631370517.687          ops/s
ElasticWrite.write                        thrpt       600571289.654          ops/s

HeapAllocate.allocate                        ss              96.597          ms/op
PointedAllocate.allocate                     ss           20556.955          ms/op
FixedAllocate.allocate                       ss            2436.920          ms/op
ElasticAllocate.allocate                     ss            1882.812          ms/op

FixedFree.free                               ss            4836.308          ms/op
ElasticFree.free                             ss            4876.006          ms/op
You might also like...
Blog implemented via the Storyblok Kotlin Multiplatform SDK (Android, JVM)
Blog implemented via the Storyblok Kotlin Multiplatform SDK (Android, JVM)

storyblok-mp-SDK-blog ... a showcase of using the Storyblok Kotlin Multiplatform Client to build a blog application (Android, JVM) What's included 🚀

Solves the audit needs for any JVM based application
Solves the audit needs for any JVM based application

Auditor-v1 Solves the audit needs for any JVM based application.

A property/method accessor library for the JVM, written in Kotlin

unlok - unlock your JVM a property/method accessor library for the JVM, written in Kotlin. how to import you can import unlok from maven central just

fusion4j - declarative rendering language for the JVM based on Neos.Fusion

fusion4j - declarative rendering language for the JVM based on Neos.Fusion Supports the Neos Fusion syntax/semantic as described in the official Neos

 A Kotlin library providing a simple, high-performance way to use off-heap native memory in JVM applications.
A Kotlin library providing a simple, high-performance way to use off-heap native memory in JVM applications.

native_memory_allocator A library which uses sun.misc.Unsafe to allocate off-heap native memory. Motivation The goal of this project is to provide a s

🎑 Up to date IANA timezone database library for Kotlin (JVM, JS, Native)

🎑 IANA Timezone Library for Kotlin Multiplatform Up to date IANA timezone database library for Kotlin (JVM, JS, Native) Usage import org.noelware.ian

A simplified interface for interacting with in-memory cache implementations on the JVM

This library provides a simplified interface for interacting with in-memory cache implementations on the JVM. Think: "SLF4J but for caching"

Kotlin/JVM compensated summation of Double sequences to calculate sum, mean, standard deviation

precise Implements compensated summation for sequences of Double. Reduces rounding errors associated with limited precision of floating-point numbers.

Lightweight compiler plugin intended for Kotlin/JVM library development and symbol visibility control.

Restrikt A Kotlin/JVM compiler plugin to restrict symbols access, from external project sources. This plugin offers two ways to hide symbols: An autom

Comments
  • Thread safe access from `use` block

    Thread safe access from `use` block

    Currently strukts dont provide thread safe access, changing the pointer on one thread will also change the pointer on another.

    I can think of two ways of doing this:

    1. Storing the current pointer in a thread local reference (may be unintuitive if you change the pointer on one thread and it doesnt update on another?)
    2. Adding a syncronised block to the use functionality. While this is slow, it will mean that as long as you always use the use block to access Strukts it will be thread safe.

    What's your opinion?

    opened by x4e 5
  • Document prerequisites

    Document prerequisites

    This looks really awesome, I'm really excited to give this a try sometime. What are the prerequisites for use of this library? Which JVM languages can this be used with? Kotlin? Java? Is it possible to get syntax examples for Java if it can be used with Java?

    opened by juckele 3
  • The pointer isn't threadsafe

    The pointer isn't threadsafe

    If one thread expects the pointer to remain set, while another thread sets it to a different value, undefined behavior may occur. The pointer needs to be thread-local.

    opened by Eladkay 2
Releases(3.2.0)
Owner
Jire
🍖 the coding caveman
Jire
Ivy FRP is a Functional Reactive Programming framework for declarative-style programming for Android

FRP (Functional Reactive Programming) framework for declarative-style programming for Andorid. :rocket: (compatible with Jetpack Compose)

null 8 Nov 24, 2022
🔴 A non-deterministic finite-state machine for Android & JVM that won't let you down

HAL is a non-deterministic finite-state machine for Android & JVM built with Coroutines StateFlow and LiveData. Why non-deterministic? Because in a no

Adriel Café 73 Nov 28, 2022
:blowfish: An Android & JVM key-value storage powered by Protobuf and Coroutines

PufferDB PufferDB is a ⚡ key-value storage powered by Protocol Buffers (aka Protobuf) and Coroutines. The purpose of this library is to provide an eff

Adriel Café 94 Dec 7, 2022
🚟 Lightweight, and simple scheduling library made for Kotlin (JVM)

Haru ?? Lightweight, and simple scheduling library made for Kotlin (JVM) Why did you build this? I built this library as a personal usage library to h

Noel 13 Dec 16, 2022
A injection minecraft cheat using jvm attach api

Luminous A injection minecraft cheat using jvm attach api Website: https://lumi.getfdp.today Build We used a thing called Wrapper to make development

null 24 Dec 21, 2022
Yet Another Native Loader for the JVM.

yanl - yet another native loader Yet another Native library extractor/loader for the JVM, written in Kotlin. why other libraries simply don't fit my n

Stardust Enterprises 5 Dec 23, 2022
A Template for a Github Actions Pipeline for building and publishing Gradle-JVM Applications

github-actions-cd-template-jvm A Template for a Github Actions Pipeline for building and publishing Gradle-JVM Applications It build a executable shad

Raphael Panic 0 Dec 5, 2021
Run Kotlin/JS libraries in Kotlin/JVM and Kotlin/Native programs

Zipline This library streamlines using Kotlin/JS libraries from Kotlin/JVM and Kotlin/Native programs. It makes it possible to do continuous deploymen

Cash App 1.5k Dec 30, 2022
Yaspeller-kt - Asynchronous Yandex.Speller API wrapper for Kotlin/JVM.

yaspeller-kt Asynchronous Yandex.Speller API wrapper for Kotlin/JVM. Installation repositories { maven { url 'https://jitpack.io' }

Mikhail Koshkin 6 Jun 27, 2022
Port immer for kotlin/jvm

1. kimmer Port https://github.com/immerjs/immer for kotlin/jvm (requires kotlin 1.5+). Immer is the winner of the "Breakthrough of the year" React ope

null 37 Dec 9, 2022