только не для того чтобы называть скорости скоростями, мне нравится идея что я могу думать о данных как о множествах и словарях без сильной связности датаклассов.
Щас попробовал у себя собрать на коленке бенчмарк по мотивам. стянул свежий бинарь JDK+valhalla и добавил туда JMH
package test;
import org.openjdk.jmh.annotations.*;
import org.openjdk.jmh.runner.Runner;
import org.openjdk.jmh.runner.options.OptionsBuilder;
import java.util.Random;
import java.util.concurrent.TimeUnit;
@BenchmarkMode(Mode.AverageTime)
@OutputTimeUnit(TimeUnit.MICROSECONDS)
@State(Scope.Benchmark)
@Fork(value = 1)
@Warmup(iterations = 5, timeUnit = TimeUnit.MILLISECONDS, time = 5000)
@Measurement(iterations = 5, timeUnit = TimeUnit.MILLISECONDS, time = 5000)
public class BenchValhalla {
private Point[] mutablePoint;
private ValuePoint[] valhallaPoint;
@Setup
public void setup() {
var r = new Random(69);
var samples = 5000;
this.valhallaPoint = new ValuePoint[samples];
this.mutablePoint = new Point[samples];
for (int i = 0; i < valhallaPoint.length; i++) {
valhallaPoint[i] = new ValuePoint(r.nextDouble(), r.nextDouble(), r.nextDouble(), r.nextDouble());
}
for (int i = 0; i < mutablePoint.length; i++) {
var valh = valhallaPoint[i];
mutablePoint[i] = new Point(valh.x, valh.y, valh.z, valh.w);
}
}
@Benchmark
public ValuePoint valhallaPoint() {
var arr = valhallaPoint;
var sum = new ValuePoint(0, 0, 0, 0);
for (int i = 0; i < arr.length; ++i) {
for (int j = 0; j < arr.length; ++j) {
sum = sum.add(arr[j].sub(arr[i]));
}
}
return sum;
}
@Benchmark
public Point plainOldMutablePoint() {
var arr = mutablePoint;
var sum = new Point(0, 0, 0, 0);
for (int i = 0; i < arr.length; ++i) {
for (int j = 0; j < arr.length; ++j) {
sum.mutableAdd(arr[j]);
sum.mutableSub(arr[i]);
}
}
return sum;
}
@Benchmark
public Point plainOldImmutablePoint() {
var arr = mutablePoint;
var sum = new Point(0, 0, 0, 0);
for (int i = 0; i < arr.length; ++i) {
for (int j = 0; j < arr.length; ++j) {
sum = sum.addImmutable(arr[j].subImmutable(arr[i]));
}
}
return sum;
}
public static void main(String[] args) throws Exception {
var options = new OptionsBuilder()
.include(BenchValhalla.class.getSimpleName())
.build();
new Runner(options).run();
}
static value class ValuePoint {
public final double x;
public final double y;
public final double z;
public final double w;
public ValuePoint(double x, double y, double z, double w) {
this.x = x;
this.y = y;
this.z = z;
this.w = w;
}
public ValuePoint add(ValuePoint p) {
return new ValuePoint(x + p.x, y + p.y, z + p.z, w + p.w);
}
public ValuePoint sub(ValuePoint p) {
return new ValuePoint(x - p.x, y - p.y, z - p.z, w - p.w);
}
}
static class Point {
public double x;
public double y;
public double z;
public double w;
public Point(double x, double y, double z, double w) {
this.x = x;
this.y = y;
this.z = z;
this.w = w;
}
public Point mutableAdd(Point p) {
x += p.x; y += p.y; z += p.z; w += p.w;
return this;
}
public Point mutableSub(Point p) {
x -= p.x; y -= p.y; z -= p.z; w -= p.w;
return this;
}
public Point addImmutable(Point p) {
return new Point(x + p.x, y + p.y, z + p.z, w + p.w);
}
public Point subImmutable(Point p) {
return new Point(x - p.x, y - p.y, z - p.z, w - p.w);
}
}
}
А ещё стейт корутин можно сериализовать и таким макаром сделать сохранения игры.
Да, тож много думал про то как было бы прикольно их использовать. Например, что можно описать какой-нить игровой квест на await условий понятным линейным кодом.
По поводу перфа, можно инлайнить композицию, правда это не динамическая история вообще, нужно будет каждую комбинацию описывать. У меня на проекте я специально делал кодген чтобы заинлайнить массив в класс, типа делал абстрактный MyCoolArray и реализации MyCoolArray0, MyCoolArray1 и тп. Но была цель оптимизироваться по памяти в первую очередь. После 16ти элементов уже была реализация MyCoolArrayN с массивом честным.
Потом это через виртуализацию разруливается на калсайте. Да, сдеградируешь на вызовах функций, но зато выигрываешь по плотности укладки в памяти.
Если совсем с ума сойти, можно ваще сделать «value types у нас дома» через VarHandle + byte[]. Производительность должна быть на уровне, тк JIT потом это всё вклеивает нормально.
конечно, это крайне костыльно, потому что JVM:(
Комментарий отредактирован:
29 ноября 2024, 14:46
(5 раз)
Если человек называет себя сеньором но при этом не может атомарно работать с конкурентной мапой, а прод «не упал» только потому что ревьюер уже в сотый раз смог это заметить…
А по поводу второго, это зависит от задач. Я тут задушнил не спорю, потому что в 99% случаев тебе будет достаточно простого решения. но в случае где его недостаточно… из недавних примеров, замена EnumMap на ConcurrentHashMap просто чтобы «па-быстраму» сделать класс тред-сейф положила кластер. А вот это на ревью пролетело к сожалению.
По поводу третьего это прямо моя личная жопоболь, когда ты встречаешь в коде воздушный замок который какой-то челик построил сто лет назад. А тебе нужно там что-то поменять. По итогу проблема добавить одно поле в POJO превращается в путешествие туда и обратно только потому что кто-то до тебя решил что тут нужно байткодогенерацию зафигачить.
Сорри за оффтоп уже конкретный от сабжа.
Комментарий отредактирован:
27 ноября 2024, 19:23
(3 раза)
я вот скоко работаю (байесд, не спорю), от чего реально горела жопа и из-за чего людей увольняли:
1) неправильный канкаренси код
2) неэффективные структуры данных
3) решение выдуманных проблем
> начинаются извращения с венгерской нотацией типа long timeMs; double speedKmh
А минусы будут?
в джаве тем более это экономия аллокаций.
ну типа да, ты можешь случайно смешать красное с липким, но от ошибок тебя не застрахуют полностью даже проверки на адекватность комбинаций.
Опять же, имхо, настоящая проблема в ЯП это читаемость кода, а ещё важнее читаемость многопоточного и асинхронного кода. А вот эти все вещи типа «а какой иерархией типов и перегрузками мне выразить мою идеальную модель», за решением таких паззлов это к хаскеллу и прочим функциональщикам. Т.е. кодить не за деньги.
В реальной жизни ты:
1) чтобы не ошибиться в вычислениях тестируешь код
2) если тебе надо вычислить физ величину ты просто её вычисляешь. ты не думаешь.
поэтому мультипарадигменные языки типа джавы и шарпа лучше.
только не для того чтобы называть скорости скоростями, мне нравится идея что я могу думать о данных как о множествах и словарях без сильной связности датаклассов.
терпите, джавики.
вот тебе, блять, 10 лет люди работали. жаль джава не умерла.
Результат по итогу вот такой:
чёто это не вяжется с тем что они на презентациях показывали))
Да, тож много думал про то как было бы прикольно их использовать. Например, что можно описать какой-нить игровой квест на await условий понятным линейным кодом.
там норм валью тайпы есть
а вот с apple music айфремы не работают
Потом это через виртуализацию разруливается на калсайте. Да, сдеградируешь на вызовах функций, но зато выигрываешь по плотности укладки в памяти.
Если совсем с ума сойти, можно ваще сделать «value types у нас дома» через VarHandle + byte[]. Производительность должна быть на уровне, тк JIT потом это всё вклеивает нормально.
конечно, это крайне костыльно, потому что JVM:(
Angelscript + C++ очень похож на groovy + java
типа, пара компилируемый и скриптовый языки, которые очень друг на друга похожи. что очень удобно.
мы же прикладные кодеры народ простой — нам джейсончик переложить и изредка литкод порешать.
а академической работой пусть занимаются учёные на грантах. а от изобретения до индустриального применения проходит какое-то время.
ну к примеру тот же paxos. очень сложный капец, поэтому придумали raft для решения задачек попроще.
ну а чё он блицы свои сидит дёргает на дворе уже 2024век все норм ребята уже кодят на расте
Если человек называет себя сеньором но при этом не может атомарно работать с конкурентной мапой, а прод «не упал» только потому что ревьюер уже в сотый раз смог это заметить…
А по поводу второго, это зависит от задач. Я тут задушнил не спорю, потому что в 99% случаев тебе будет достаточно простого решения. но в случае где его недостаточно… из недавних примеров, замена EnumMap на ConcurrentHashMap просто чтобы «па-быстраму» сделать класс тред-сейф положила кластер. А вот это на ревью пролетело к сожалению.
По поводу третьего это прямо моя личная жопоболь, когда ты встречаешь в коде воздушный замок который какой-то челик построил сто лет назад. А тебе нужно там что-то поменять. По итогу проблема добавить одно поле в POJO превращается в путешествие туда и обратно только потому что кто-то до тебя решил что тут нужно байткодогенерацию зафигачить.
Сорри за оффтоп уже конкретный от сабжа.
1) неправильный канкаренси код
2) неэффективные структуры данных
3) решение выдуманных проблем
А минусы будут?
в джаве тем более это экономия аллокаций.
ну типа да, ты можешь случайно смешать красное с липким, но от ошибок тебя не застрахуют полностью даже проверки на адекватность комбинаций.
Опять же, имхо, настоящая проблема в ЯП это читаемость кода, а ещё важнее читаемость многопоточного и асинхронного кода. А вот эти все вещи типа «а какой иерархией типов и перегрузками мне выразить мою идеальную модель», за решением таких паззлов это к хаскеллу и прочим функциональщикам. Т.е. кодить не за деньги.
В реальной жизни ты:
1) чтобы не ошибиться в вычислениях тестируешь код
2) если тебе надо вычислить физ величину ты просто её вычисляешь. ты не думаешь.