Pull to refresh
1
0

Data Engineer который убежал от Java на Kotlin

Send message

Используйте application плагин, он куда удобнее, не нужно добавлять зависимость на еще один плагин и он не является хаком как вся концепция shadow jar


А еще можно сделать руками кеширование базового слоя со всеми зависимостями используя только application plugin


TestNG при Junit 5 тоже выглядит странным, я бы не рекомендовал его сегодня как решение "по умолчанию"


Ну и нативный mockk куда лучше mockito-kotlin, конечно только если у вас уже не готовое приложение и вы мигрируете на Kotlin новые/старые тесты

На котлине переходят не любители нового, а любители лучшего ;)

Переходите на Java 15, оно того стоит.

Переходите в клуб любителей БДСМ)

Конечно, но оригинальный БП так и так стоит денег. А еще NUC это вообще не про экономию, я выбирал между Ghost Canyon и собери сам в корпусе в три раза большем объеме и выбрал второе. Потому что дешевле и при этом для игр и компиляции куда лучше получилась конфигурация за те же деньги

Это как минимум придумать крепление, кабель менеджмент организовать (длина от блока до юнита не 10-30см, а добрый метр куда-то нужно упрятать. Хотя вот же оно очевидное решение


image

У меня удлинитель под столом прикручен к столешнице, блок питания деть некуда. Поэтому такая вот непонятная конструкия >---[CHARGER]---[NUC] стояла на столе и мешала моему OCD.


Почему?!

image


Для сравнения есть куда более элегантная >---[mac mini] или даже PC на miniITX смотрится куда лучше (я себе собрал в корпусе на 13 литров, полноценный 3900x и 2080s – совсем другой класс производительности) потому что проводов минимум и каких-то дополнительных блоков нет.


Неплохой же unit сделали, VESA крепление — конфетка. Только вот блок питания встроить, и тогда вообще прекрасно было бы подвесив за VESA (по факту нужен "VESA двойник/удлинитель" для многих мониторов)

Даже блок питания снаружи, из-за этого продал canyon, не про минимализм.

У вас хорошо получилось объяснить, даже новичек должен понять, пишите еще!

Я просто никак не могу быть согласным что стримы быстрее пусть и на 100мс.


Вот я накидал кейс когда они будут намного медленнее:


Server.kt


Undertow.builder()
    .setWorkerThreads(1000)
    .addHttpListener(8080, "127.0.0.1", BlockingHandler { exchange ->
        Thread.sleep(10000)
        exchange.responseSender.send("Hello")
    }).build().start()

Client1.kt


val syncClient = HttpClients.custom().setMaxConnTotal(500).setMaxConnPerRoute(500).build()
val time = measureTimeMillis {
    (1..1000).toList()
        .parallelStream()
        .map { syncClient.execute(HttpGet("http://localhost:8080")).close() }
        .toList()
}
println(time)
syncClient.close()

Client2.kt


val asyncClient = HttpAsyncClients.custom().setMaxConnTotal(500).setMaxConnPerRoute(500).build().also {
    it.start()
}
val time = measureTimeMillis {
    coroutineScope {
        (1..1000).map { async { asyncClient.execute(HttpGet("http://localhost:8080")) } }
    }.awaitAll()
}
println(time)
asyncClient.close()

Корутины (client2) выполнятся за ожидаемые 20секунд(10секунд, 1000запросов, 500 одновременных запросов ограничение клиента, у меня получилось 20730мс если точно), они упираются только в сервер и колличество сокетов.


Java вариант будет выполняться вечность (1000 запросов / 8 тредов * 10с = 20 минут, я даже подожду чтобы получить реальную цифру, подождал – 20 минут), он упрется в CommonPool (параллелизм в моем случае 8, по числу тредов), потому что не нужно использовать Stream для задач с IO, ну не нужно и все. Даже в вашем тесте попробуйте увеличить размер дата-сета который обрабатываете, и Dispatchers.IO в разы лучше справится чем стримы. Стримы в джаве это фреймворк для математических задач, но из-за отсутсвия нормальных коллекций стал использоваться как замена адекватным коллекциям.

val javaParallelTime = measureTimeMillis { 
    val res = (1..10).toList()
        .parallelStream()
        .map { getDataAsync("$URL/$it") }
    res.forEach { println(it) }
}
println("Java parallelSrtream время $javaParallelTime мс")

А как это может работать без блокирования треда?) Ну кроме loom, но тут речи про него вообще не было

Окей, запрос асинхронно но в итоге тред из CommonPool из ForkJoinPool блочится тогда. Добавляем еще запросов и оп, магический parallel stream перестал скейлиться.


Так что тесты так себе, как и идея сравнивать производительность относительно 3rd-party сервиса в интрнете.


Лучше локально поднять сервис и ввести исскуственную latency

Именно, суффикс асинк подразумевает что метод вернул какую-нибудь CompletableFuture, но нету вообще намека на то что это так. Код стал бы куда сложнее для чтения и понимания.


А если там синхронный клиент, то очень легко сделать так чтобы полностью асинхронная версия с корутинами на большем колличестве запросов вырвалась вперед (опять же зависит как клиент настроить, может там в клиенте 1 req/host установлен и тогда хоть 1000 тредов создай, 0 пользы)

val javaParallelTime = measureTimeMillis { 
    val res = (1..10).toList()
        .parallelStream()
        .map { getDataAsync("URL/$it") }
    res.forEach { println(it) }
}

Если async, то как же дождаться результата?

Перешел сюда с self-hosted tiny tiny rss. Кстати автору сего замечательного проекта можно задонатить -> https://tt-rss.org/

Зато люди которым постоянно кто-то пишет по собственным проблемам будут в восторге, а у вас не будет выбора

Спасибо за статью!


Пользуемся .airflowignore

Спасибо, как-то в документации не встречал


Используйте KubernetesPodOperator для запуска зависимостей и утилит, написанных не на Python.

И на Python тоже. Лучшей практикой будет обернуть все кастомные операторы в контейнер и запускать как KubernetesPodOperator, так вы избавитесь от множества проблем с версиями пакетов. И пайплайны будут простые и воспроизводимые (даже локально запустить будет проще).


Поэтому время от времени Composer предлагает апдейтнуть окружение: появляется кнопка, автоматически создается новый image, контейнеры и ваш инвайронмент переводится в новую версию Airflow.

Как у вас опыт с этим? Особенно интересно как апдейт окружение (изменение версии) подружить с Terraform

Спасибо за статью со Spring и Coroutines!


GlobalScope.async


Вот так не надо, используйте structured concurrency и код станет короче (не нужно будет писать GlobalScope), контекст не нужно будет явно передавать.

Ну допустим, это экскурс в историю, взгляд на общую картину мира. Почему тогда переход с PowerPC на Intel заслужил так мало внимания? Это же прямая параллель – там был переход на новую более эффективную архитектуру, которая позволила эволюционировать продукции Apple дальше. А все потому что PowerPC стагнировал, и не успевал выпускать новые, лучшие процессоры с меньшим потреблением энергии на единицу вычислений – прям как Intel сейчас.


однако уже сейчас понятно, что новым процессорам M1 ближайший год-два придется вывозить на себе все тягости и лишения переходного периода пока App store не обзаведется достойным набором приложений под новую архитектуру

Кому понятно, почему понятно? Подавляющее большинство приложений работает из коробки через rosetta 2, куча приложений уже адаптированна. Да еще и можно запускать приложения доступные для ipad/iphone. Потому что архитектура не такая новая, iphoneOs/ipadOs приложения запускаются нативно. А их магазин приложений значительно больше чем магазин приложений под macOs


Гладко было на бумаге, да забыли про овраги

Интересная подпись, которая ничем дальше не подкреплена (а так хотелось увидеть эти овраги)


Вода и голословность, писал маркетолог ради последнего абзаца

Читал и думал вот-вот вода закончится и начнется сравнение по существу, с тестами, замерами т.д. Но статья закончилась первой

gradle — это вообще яркий пример как электронным микроскопом коят орехи.

В идеальном мире – возможно, в реальной жизни хороший инструмент в котором можно и микробов рассматривать, и орехи поколоть :) Главное что при разработке он быстр, особенно в continuous режиме. И будет становится еще быстрее, компиляция самого Gradle Kotlin DSL ускорится в ветке 7

Information

Rating
Does not participate
Registered
Activity