Skip to content

Commit 50570c3

Browse files
committed
update example, benchmark and readme
1 parent d7ee11a commit 50570c3

7 files changed

Lines changed: 54 additions & 69 deletions

File tree

README.md

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22

33
![Flecs](https://raw.githubusercontent.com/SanderMertens/flecs/master/docs/img/logo.png)
44

5-
Java bindings for [Flecs](https://github.com/SanderMertens/flecs) - A fast and flexible Entity Component System (ECS) using Java 25's Foreign Function & Memory API (FFM).
5+
Java bindings for [Flecs](https://github.com/SanderMertens/flecs) (v4.1.4) - A fast and flexible Entity Component System (ECS) using Java 25's Foreign Function & Memory API (FFM).
66

77
## What is Flecs?
88

@@ -30,8 +30,8 @@ Flecs is a powerful ECS framework written in C that provides high-performance da
3030

3131
```gradle
3232
dependencies {
33-
implementation 'io.github.elebras1:flecs-java:0.5.3'
34-
annotationProcessor 'io.github.elebras1:flecs-java:0.5.3'
33+
implementation 'io.github.elebras1:flecs-java:0.6.0'
34+
annotationProcessor 'io.github.elebras1:flecs-java:0.6.0'
3535
3636
}
3737
```
@@ -109,9 +109,8 @@ public class Example {
109109

110110
// Query entities
111111
try (Query query = world.query().with(Position.class).build()) {
112-
query.each(entityId -> {
112+
query.each(Position.class, (entityId, pos) -> {
113113
Entity e = world.obtainEntity(entityId);
114-
Position pos = e.get(Position.class);
115114
System.out.printf("%s: (%.2f, %.2f)%n", e.getName(), pos.x(), pos.y());
116115
});
117116
}

benchmark/results/benchmark-results.txt

Lines changed: 28 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -10,68 +10,68 @@ GCC : gcc (Ubuntu 13.3.0-6ubuntu2~24.04) 13.3.0
1010
============================================================
1111

1212
BENCHMARK RESULTS — flecs-java vs flecs C vs Artemis-odb
13-
Date : 2026-02-27 15:02:57
13+
Date : 2026-03-06 23:34:01
1414

1515
[ Java / JMH ]
1616
------------------------------------------------------------
1717
Benchmark Mode Cnt Score Error Units
1818
c.g.e.f.b.artemisodb.EntityCreationBenchmark.create avgt 3 0,012 ± 0,001 us/op
19-
c.g.e.f.b.artemisodb.EntityCreationBenchmark.create:·gc.alloc.rate avgt 3 5791,911 ± 57,546 MB/sec
19+
c.g.e.f.b.artemisodb.EntityCreationBenchmark.create:·gc.alloc.rate avgt 3 5814,955 ± 454,737 MB/sec
2020
c.g.e.f.b.artemisodb.EntityCreationBenchmark.create:·gc.alloc.rate.norm avgt 3 75,435 ± 0,001 B/op
21-
c.g.e.f.b.artemisodb.EntityCreationBenchmark.create:·gc.count avgt 3 50,000 counts
22-
c.g.e.f.b.artemisodb.EntityCreationBenchmark.create:·gc.time avgt 3 35,000 ms
23-
c.g.e.f.b.artemisodb.EntityCreationBenchmark.createWith2Components avgt 3 0,071 ± 0,001 us/op
24-
c.g.e.f.b.artemisodb.EntityCreationBenchmark.createWith2Components:·gc.alloc.rate avgt 3 2162,063 ± 35,120 MB/sec
21+
c.g.e.f.b.artemisodb.EntityCreationBenchmark.create:·gc.count avgt 3 26,000 counts
22+
c.g.e.f.b.artemisodb.EntityCreationBenchmark.create:·gc.time avgt 3 25,000 ms
23+
c.g.e.f.b.artemisodb.EntityCreationBenchmark.createWith2Components avgt 3 0,070 ± 0,002 us/op
24+
c.g.e.f.b.artemisodb.EntityCreationBenchmark.createWith2Components:·gc.alloc.rate avgt 3 2182,385 ± 70,828 MB/sec
2525
c.g.e.f.b.artemisodb.EntityCreationBenchmark.createWith2Components:·gc.alloc.rate.norm avgt 3 160,409 ± 0,001 B/op
26-
c.g.e.f.b.artemisodb.EntityCreationBenchmark.createWith2Components:·gc.count avgt 3 20,000 counts
27-
c.g.e.f.b.artemisodb.EntityCreationBenchmark.createWith2Components:·gc.time avgt 3 54,000 ms
28-
c.g.e.f.b.artemisodb.EntityCreationBenchmark.createWith2ComponentsFromPrefab avgt 3 0,037 ± 0,005 us/op
29-
c.g.e.f.b.artemisodb.EntityCreationBenchmark.createWith2ComponentsFromPrefab:·gc.alloc.rate avgt 3 2954,763 ± 359,537 MB/sec
26+
c.g.e.f.b.artemisodb.EntityCreationBenchmark.createWith2Components:·gc.count avgt 3 19,000 counts
27+
c.g.e.f.b.artemisodb.EntityCreationBenchmark.createWith2Components:·gc.time avgt 3 24,000 ms
28+
c.g.e.f.b.artemisodb.EntityCreationBenchmark.createWith2ComponentsFromPrefab avgt 3 0,037 ± 0,001 us/op
29+
c.g.e.f.b.artemisodb.EntityCreationBenchmark.createWith2ComponentsFromPrefab:·gc.alloc.rate avgt 3 2969,313 ± 6,766 MB/sec
3030
c.g.e.f.b.artemisodb.EntityCreationBenchmark.createWith2ComponentsFromPrefab:·gc.alloc.rate.norm avgt 3 115,435 ± 0,001 B/op
3131
c.g.e.f.b.artemisodb.EntityCreationBenchmark.createWith2ComponentsFromPrefab:·gc.count avgt 3 29,000 counts
32-
c.g.e.f.b.artemisodb.EntityCreationBenchmark.createWith2ComponentsFromPrefab:·gc.time avgt 3 30,000 ms
32+
c.g.e.f.b.artemisodb.EntityCreationBenchmark.createWith2ComponentsFromPrefab:·gc.time avgt 3 39,000 ms
3333
c.g.e.f.b.artemisodb.QueryBenchmark.query avgt 3 0,002 ± 0,001 us/op
3434
c.g.e.f.b.artemisodb.QueryBenchmark.query:·gc.alloc.rate avgt 3 ≈ 10⁻³ MB/sec
3535
c.g.e.f.b.artemisodb.QueryBenchmark.query:·gc.alloc.rate.norm avgt 3 ≈ 10⁻⁶ B/op
3636
c.g.e.f.b.artemisodb.QueryBenchmark.query:·gc.count avgt 3 ≈ 0 counts
3737
c.g.e.f.b.flecs.EntityCreationBenchmark.create avgt 3 0,014 ± 0,001 us/op
38-
c.g.e.f.b.flecs.EntityCreationBenchmark.create:·gc.alloc.rate avgt 3 0,497 ± 0,009 MB/sec
38+
c.g.e.f.b.flecs.EntityCreationBenchmark.create:·gc.alloc.rate avgt 3 0,511 ± 0,021 MB/sec
3939
c.g.e.f.b.flecs.EntityCreationBenchmark.create:·gc.alloc.rate.norm avgt 3 0,027 ± 0,001 B/op
4040
c.g.e.f.b.flecs.EntityCreationBenchmark.create:·gc.count avgt 3 ≈ 0 counts
41-
c.g.e.f.b.flecs.EntityCreationBenchmark.createWith2Components avgt 3 0,158 ± 0,039 us/op
42-
c.g.e.f.b.flecs.EntityCreationBenchmark.createWith2Components:·gc.alloc.rate avgt 3 303,679 ± 67,835 MB/sec
41+
c.g.e.f.b.flecs.EntityCreationBenchmark.createWith2Components avgt 3 0,166 ± 0,010 us/op
42+
c.g.e.f.b.flecs.EntityCreationBenchmark.createWith2Components:·gc.alloc.rate avgt 3 294,063 ± 24,549 MB/sec
4343
c.g.e.f.b.flecs.EntityCreationBenchmark.createWith2Components:·gc.alloc.rate.norm avgt 3 64,032 ± 0,001 B/op
44-
c.g.e.f.b.flecs.EntityCreationBenchmark.createWith2Components:·gc.count avgt 3 7,000 counts
45-
c.g.e.f.b.flecs.EntityCreationBenchmark.createWith2Components:·gc.time avgt 3 2,000 ms
46-
c.g.e.f.b.flecs.EntityCreationBenchmark.createWith2ComponentsFromPrefab avgt 3 0,198 ± 0,016 us/op
47-
c.g.e.f.b.flecs.EntityCreationBenchmark.createWith2ComponentsFromPrefab:·gc.alloc.rate avgt 3 0,131 ± 0,010 MB/sec
44+
c.g.e.f.b.flecs.EntityCreationBenchmark.createWith2Components:·gc.count avgt 3 6,000 counts
45+
c.g.e.f.b.flecs.EntityCreationBenchmark.createWith2Components:·gc.time avgt 3 3,000 ms
46+
c.g.e.f.b.flecs.EntityCreationBenchmark.createWith2ComponentsFromPrefab avgt 3 0,193 ± 0,015 us/op
47+
c.g.e.f.b.flecs.EntityCreationBenchmark.createWith2ComponentsFromPrefab:·gc.alloc.rate avgt 3 0,134 ± 0,027 MB/sec
4848
c.g.e.f.b.flecs.EntityCreationBenchmark.createWith2ComponentsFromPrefab:·gc.alloc.rate.norm avgt 3 0,033 ± 0,001 B/op
4949
c.g.e.f.b.flecs.EntityCreationBenchmark.createWith2ComponentsFromPrefab:·gc.count avgt 3 ≈ 0 counts
50-
c.g.e.f.b.flecs.EntityCreationBenchmark.createWith2ComponentsNoAlloc avgt 3 0,150 ± 0,016 us/op
51-
c.g.e.f.b.flecs.EntityCreationBenchmark.createWith2ComponentsNoAlloc:·gc.alloc.rate avgt 3 0,213 ± 0,022 MB/sec
50+
c.g.e.f.b.flecs.EntityCreationBenchmark.createWith2ComponentsNoAlloc avgt 3 0,148 ± 0,012 us/op
51+
c.g.e.f.b.flecs.EntityCreationBenchmark.createWith2ComponentsNoAlloc:·gc.alloc.rate avgt 3 0,218 ± 0,018 MB/sec
5252
c.g.e.f.b.flecs.EntityCreationBenchmark.createWith2ComponentsNoAlloc:·gc.alloc.rate.norm avgt 3 0,043 ± 0,001 B/op
5353
c.g.e.f.b.flecs.EntityCreationBenchmark.createWith2ComponentsNoAlloc:·gc.count avgt 3 ≈ 0 counts
54-
c.g.e.f.b.flecs.QueryBenchmark.query avgt 3 0,002 ± 0,001 us/op
55-
c.g.e.f.b.flecs.QueryBenchmark.query:·gc.alloc.rate avgt 3 1,633 ± 4,773 MB/sec
56-
c.g.e.f.b.flecs.QueryBenchmark.query:·gc.alloc.rate.norm avgt 3 0,003 ± 0,008 B/op
54+
c.g.e.f.b.flecs.QueryBenchmark.query avgt 3 0,001 ± 0,001 us/op
55+
c.g.e.f.b.flecs.QueryBenchmark.query:·gc.alloc.rate avgt 3 1,761 ± 4,447 MB/sec
56+
c.g.e.f.b.flecs.QueryBenchmark.query:·gc.alloc.rate.norm avgt 3 0,002 ± 0,005 B/op
5757
c.g.e.f.b.flecs.QueryBenchmark.query:·gc.count avgt 3 ≈ 0 counts
5858

5959
[ C / Native ]
6060
------------------------------------------------------------
61-
Runs : 0 | Warmup: -985056072 | Iterations: 0
61+
Runs : 0 | Warmup: 1864256696 | Iterations: 0
6262
Benchmark: create
6363
Mode: AverageTime, Time: us
64-
Score: 0.016612 ± 0.000586 us/op (batch avg: 1661.164 us, stddev: 125.821 us)
64+
Score: 0.017170 ± 0.000897 us/op (batch avg: 1716.961 us, stddev: 192.673 us)
6565
---------------------------------------------------
6666
Benchmark: createWith2Components
6767
Mode: AverageTime, Time: us
68-
Score: 0.115707 ± 0.001028 us/op (batch avg: 11570.671 us, stddev: 220.919 us)
68+
Score: 0.113909 ± 0.000906 us/op (batch avg: 11390.868 us, stddev: 194.649 us)
6969
---------------------------------------------------
7070
Benchmark: createWith2ComponentsFromPrefab
7171
Mode: AverageTime, Time: us
72-
Score: 0.106134 ± 0.000644 us/op (batch avg: 10613.443 us, stddev: 138.276 us)
72+
Score: 0.109141 ± 0.000259 us/op (batch avg: 10914.146 us, stddev: 55.735 us)
7373
---------------------------------------------------
7474
Benchmark: query
7575
Mode: AverageTime, Time: us
76-
Score: 0.000882 ± 0.000019 us/op (batch avg: 88.151 us, stddev: 4.190 us)
76+
Score: 0.000848 ± 0.000013 us/op (batch avg: 84.831 us, stddev: 2.877 us)
7777
---------------------------------------------------

benchmark/src/jmh/java/com/github/elebras1/flecs/benchmark/flecs/QueryBenchmark.java

Lines changed: 10 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -44,26 +44,19 @@ public void tearDown() {
4444
@Benchmark
4545
@OperationsPerInvocation(100_000)
4646
public void query(Blackhole bh) {
47-
this.query.iter(iter -> {
48-
Field<Health> healthField = iter.field(Health.class, 0);
49-
Field<Ideology> ideologyField = iter.field(Ideology.class, 1);
50-
for(int i = 0; i < iter.count(); i++) {
51-
HealthView healthView = healthField.getMutView(i);
52-
IdeologyView ideologyView = ideologyField.getMutView(i);
47+
this.query.eachView(Health.class, Ideology.class, (HealthView healthView, IdeologyView ideologyView) -> {
48+
int v1 = healthView.value() + 1;
49+
healthView.value(v1);
5350

54-
int v1 = healthView.value() + 1;
55-
healthView.value(v1);
51+
int v2 = ideologyView.color() + 1;
52+
ideologyView.color(v2);
5653

57-
int v2 = ideologyView.color() + 1;
58-
ideologyView.color(v2);
54+
int v3 = ideologyView.factionDriftingSpeed() + 1;
55+
ideologyView.factionDriftingSpeed(v3);
5956

60-
int v3 = ideologyView.factionDriftingSpeed() + 1;
61-
ideologyView.factionDriftingSpeed(v3);
62-
63-
bh.consume(v1);
64-
bh.consume(v2);
65-
bh.consume(v3);
66-
}
57+
bh.consume(v1);
58+
bh.consume(v2);
59+
bh.consume(v3);
6760
});
6861
}
6962
}

examples/src/main/java/com/github/elebras1/flecs/examples/ObserverExample.java

Lines changed: 2 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -21,13 +21,8 @@ public static void main(String[] args) {
2121
Entity e1 = world.obtainEntity(world.entity("Entity1"));
2222
e1.set(new Position(10.0f, 20.0f));
2323

24-
world.observer(Position.class).event(EcsOnSet).iter((it) -> {
25-
for (int i = 0; i < it.count(); i++) {
26-
long entityId = it.entityId(i);
27-
Position pos = world.obtainEntity(entityId).get(Position.class);
28-
System.out.println("Position set to (" + pos.x() + ", " + pos.y() + ")");
29-
}
30-
});
24+
world.observer(Position.class).event(EcsOnSet).each(Position.class, (entityId, pos) ->
25+
System.out.println("Position set to (" + pos.x() + ", " + pos.y() + ") " + "for entity " + entityId));
3126

3227
e1.set(new Position(30.0f, 40.0f));
3328

examples/src/main/java/com/github/elebras1/flecs/examples/QueryBasicsExample.java

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -25,9 +25,9 @@ public static void main(String[] args) {
2525
try (Query query = world.query().with(Position.class).with(Velocity.class).build()) {
2626
System.out.println("Entities with Position and Velocity: " + query.count());
2727

28-
query.each(entityId -> {
28+
query.each(Position.class, (entityId, pos) -> {
2929
Entity entity = world.obtainEntity(entityId);
30-
System.out.println(" - " + entity.getName());
30+
System.out.println(" - " + entity.getName() + " at position (" + pos.x() + ", " + pos.y() + ")");
3131
});
3232
}
3333

@@ -43,8 +43,7 @@ public static void main(String[] args) {
4343
Velocity vel = velocities.get(i);
4444
Entity entity = world.obtainEntity(it.entity(i));
4545

46-
System.out.printf("%s: pos=(%.1f, %.1f), vel=(%.1f, %.1f)%n",
47-
entity.getName(), pos.x(), pos.y(), vel.dx(), vel.dy());
46+
System.out.printf("%s: pos=(%.1f, %.1f), vel=(%.1f, %.1f)%n", entity.getName(), pos.x(), pos.y(), vel.dx(), vel.dy());
4847
}
4948
});
5049
}

examples/src/main/java/com/github/elebras1/flecs/examples/SystemExample.java

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -45,9 +45,8 @@ public static void main(String[] args) {
4545
FlecsSystem debugSystem = world.system("DebugSystem")
4646
.with(posId)
4747
.kind(FlecsConstants.EcsPostUpdate)
48-
.each(entityId -> {
48+
.each(Position.class, (entityId, pos) -> {
4949
Entity entity = world.obtainEntity(entityId);
50-
Position pos = entity.get(Position.class);
5150
System.out.printf("Debug: %s at (%.2f, %.2f)%n", entity.getName(), pos.x(), pos.y());
5251
});
5352

examples/src/main/java/com/github/elebras1/flecs/examples/ViewExample.java

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -28,12 +28,12 @@ public static void main(String[] args) {
2828
});
2929
}
3030

31-
world.system("MovementSystem").kind(FlecsConstants.EcsOnUpdate).with(Position.class).with(Velocity.class).multiThreaded().each(entityId -> {
32-
EntityView entityView = world.obtainEntityView(entityId);
33-
34-
PositionView posView = entityView.getMutView(Position.class);
35-
VelocityView velView = entityView.getMutView(Velocity.class);
36-
InventoryView invView = entityView.getMutView(Inventory.class);
31+
world.system("MovementSystem")
32+
.kind(FlecsConstants.EcsOnUpdate)
33+
.with(Position.class)
34+
.with(Velocity.class)
35+
.multiThreaded()
36+
.eachView(Position.class, Velocity.class, Inventory.class, (long entityId, PositionView posView, VelocityView velView, InventoryView invView)-> {
3737

3838
posView.x(posView.x() + velView.dx()).y(posView.y() + velView.dy());
3939

0 commit comments

Comments
 (0)