Я у цьом році використовував WeakReference у розробці прозорої зміни креденшелсів у рантаймі для MongoDB драйверу. Тобто якщо у вас зараз нема таких задач, це не говорить, що вони не з’являться у майбутньому.
Потрібна стаття. Але дуже мало про роботу стеку. Зараз багато джунів з профільною освітою не розуміють, як працює стек, яким чином передаються аргументи як хіпових об’єктів, так і простих типів. А Value Types вже не за горами, принаймні я на це сподіваюсь (вони вже 10 років це розроблюють, коли воно вже вийде у реліз?).
Все відносно, зараз є різні українці, хтось витрачає гроші на унітаз, а хтось на донати, а ...
Якщо ви можете швидко розробити сайт, який не має вразливостей безпеки, код може бути легко розширений новими бізнес-функціями і сайт може тримати велике навантаження (уключно ще більш великими піками), то вам залюбки будуть платити $3000 чистими.
Але якщо написаний вами сайт — це щось не зрозуміло (для більшості початківців це нормально), то компанія може понести збитки у
Тому розробка сайта від початківця може нічого не коштувати, скільки б ви не витратили на це часу. Так що $300, це нормально — на вас будуть витрачати час інші розробники, а ваш business value буде прагнути до 0. Тобто компанія бере вас на перспективу і вже від вас залежить, що буде далі з вашою кар’єрою і З/П у цій компанії.
Если вы инженер, то выбираете язык на основе его характеристик, если вы статист, то на основе индекса языков, ну а если вы побольше деньюжек хотите, то на основе медианы З/П :).
В Scala поддерживается множественное наследование и с ним все класс и обалдеть. С С++ с множественным наследованием то же было бы все хоршо, если бы по дефолту оно было виртуальным.
Окрім того, навіть на такому об’ємі можна спростувати деякі міфи, які я чув навіть від досвідчених розробників: «GIN індекс в PostgreSQL набагато швидший за звичайні індекси», «MongoDB завжди більш ефективна для роботи з документами, ніж JSONB в PostgreSQL», «MongoDB швидше виконує агрегації» і т.д.
Ви робите узагальнені висновки на дуже простій колекції/таблиці. Чому ви не розглядаєте роботу/пошук з вкладеними документами, масивами документів і т.п.? Якщо використовувати плоскі документи, то навіщо вам JSON?
Вже відповідав раніше. Як можна бачити з тестів — в багатьох випадках швидкість вже погана навіть на такому об’ємі. З ростом об’єму вона не покращиться. Чи має сенс порівняти швидкість фільтрації за індексом на терабайті даних між двома базами — звісно так, але це матеріал для майбутніх тестів.
Чому ви вирішили, що пошук/сортування ведеться на основі індексів? Ви дивились плани ваших запитів? Для розуміння було б корисно привести їх у аналізу результатів. Більш того, має значення розподіл індексованих даних. Наприклад, є поле, яке має тільки 2 значення, у колекції/таблиці дані поля розподілені 50/50, у такому випадку індексування цього поля не додасть якогось перфоменсу. Я розумію, якщо є бажання погратися з індексами, але навіщо для цього робити бенчмарк? Достатньо буде зручний вам клієнт до БД (mongodb або postgresql) і плани ваших запитів.
P.S. у мене є досвід роботи з колекцією mongodb, розмір якої більше 2 млрд документів, в залежності від результату, пошук виконувався мілісекунди/десятки мілісекунд. Авжеж, були і проблемні пошуки, але це більш стосувалося обробки на стороні клієнта, а не mongodb. Тому і виникає багато запитань до 11 млн документів і результатів вашого бенчмарку.
P.P.S. з моєї точки зору для 11 млн простих документів/рядків не має значення, яку БД використовувати (mongodb, postgresql, mysql ..., JSON/regular tables), вибір буде залежати від кошторису використання і експертизи команди підтримки. Але для більш великих даних, я б вибрав щось надійне і перевірене — mongodb shard cluster, а не postgres citus.
Стаття гарна, але є наступні питання до тестів:
* Не зрозуміло, яка була структура даних з індексами, наприклад, SalesTable.json для mongodb можно було б замінити або описати повноцінну схему валідації з індексами. Теж саме можно було б зробити/описати для SQL DBs.
* По індексам не розглянути різні цікаві кейси:
* індекс по полям з масиву
* індекс з NULL значеннями
* індекс з відсутніми полями (для mongodb можна використовувати sparse індекс)
* Не зрозуміло, які використовувалися вибірки. Наприклад, для префоменсу mongodb не має сенсу використовувати декілька роздільних індексів у одному запиті. Тобто не зрозуміло (або зрозуміло), чому така різниця у запитах MongoDB Composite Idx і MongoDB Separate Idxs.
Дивно, але окремі індекси в PostgreSQL працюють набагато гірше, ніж окремі індекси в MongoDB, незважаючи на згадану раніше оптимізацію сканування індексу (bitmap scan). MongoDB використовує індекс TimePeriod для сканування всіх відповідних записів, які вже розміщені в правильному порядку, а потім фільтрує кожен відсканований рядок за країною, доки не буде знайдено достатньо результатів для сторінки.
Результат mongodb може бути значно гірше, все залежить від об’єму даних індексу.
* Як я зрозумів, у деяких запитів використовується сортування. У mongodb я б не використовував фільтрацію і сортування окремими індексами. А якщо у вас невеликий результат вибірки, я б зовсім відмовився від сортування на стороні mongodb.
* Із статті не зрозуміло, як вибираються данні на клієнтської стороні. Наприклад, mongodb використовує курсор з fetch параметром. Якщо у вас велика вибірка, то вам потрібно вичитати усі данні (буде декілька запитів до mongodb).
* У даному аналізі були приведені результати запитів з сторони dotnet клієнта. Це цікаво, але хотілось б зрозуміти, а що там на стороні DB — CPU, Memory, IOPS, час виконання запитів на стороні DB. Тобто, якщо вибирати DB, то хотілось би більше результатів з DB, а не клієнта (скільки там часу займає серіалізація/десеріалізаця, використовується серіалізація/десеріалізаця драйвера/провайдера або щось своє, скільки часу пішло на GC т.п.).
* 11 мільйонів рядків — це не зрозумілий об’єм даних, хотілось б розмір на диску. Більш того, я не бачу сенсу використовувати mongodb для такого об’єму даних. Хотілось б подивитись, як будуть працювати mongodb vs postgresql хоча б для 500 млн рядків.
* Не зовсім зрозуміло, чи враховують JIT компіляцію результати бенчмарку (я не знаю, які є оптимізації зараз у дотнеті, але для джави це має значення). Не зрозуміло, чому було вибрано 1000 запитів на 1 поток, а не, наприклад 10000 і як це вплине не результати.
Мій висновок — для вибору DB немає сенсу використовувати загальні тести з мікробенчмарку, тому що багато чого залежить від структури даних, об’єму, сценаріїв використання, інструментів експлуатації, подальшого розвитку системи. Тому кожна команда/компанія повинна проводити свій аналіз, свої внутрішні тести, включно з довгостроковим навантаженням (наприклад, для шард кластеру mongodb операція «move chunk» може бути болячою у час пік навантаження).
Деякі називають шардування та вбудований повнотекстовий пошук перевагами MongoDB порівняно з традиційними реляційними базами даних...
... шардування може бути реалізовано за допомогою розширення Citus
Питання до автора — скількома терабайт даними ви оперували у вашому тестовому шард кластері? У вас були довгострокові навантажувальні тести шард кластера?
Це означає, що після котліна перейдеш до джави :) Повір на слово ;)
Если честно, то перечисленные проблемы ThreadLocal не такие уж и проблемы:
Mutability.
Вот простой код неизменяемого ThreadLocal (за искоючением remove):
final class ImmutableThreadLocal<T> {
private final ThreadLocal<T> threadLocal;
public ImmutableThreadLocal(Supplier<T> initValue) {
if (initValue == null) {
throw new IllegalArgumentException("initValue is null");
}
threadLocal = ThreadLocal.withInitial(initValue);
}
public T get() {
return threadLocal.get();
}
public Optional<T> getOpn() {
return Optional.ofNullable(get());
}
public void remove() {
threadLocal.remove();
}
}
Недоступність для дочірніх потоків.
Вообще не проблема, используйте InheritableThreadLocal (Since: 1.2) и ваши дочерние потоки получат доступ к вашим переменным из родительского потока. Вот только эта фича за очень редким исключением кем-либо используется. У вас оочень плохой пример использования одной транзации в дочерних потоках — это может приветси к оочень серьезным проблемам.
Необхідність явного очищення встановлених даних.
Все зависит от сценария использования. Вот вы ориентируетесь на спринг, как на эталон качества, а их реализация совсем далека от качества — использование транзакций в виде аннотаций оочень плохой подход. Ну и вот вам простой пример очистки реусрсов:
class ImmutableThreadLocalResource<T> implements AutoCloseable {
private final ThreadLocal<T> threadLocal;
private final Thread initThread;
private volatile boolean closed;
public ImmutableThreadLocalResource(T value) {
if (value == null) {
throw new IllegalArgumentException("value is null");
}
threadLocal = new ThreadLocal<>();
threadLocal.set(value);
initThread = Thread.currentThread();
}
public boolean isPresent() {
return !closed && initThread == Thread.currentThread();
}
public boolean isClosed() {
return closed;
}
public T get() {
final var value = threadLocal.get();
if (closed) {
throw new IllegalStateException(String.format("%s is closed", ImmutableThreadLocalResource.class.getSimpleName()));
}
if (!isPresent()) {
throw new IllegalStateException("attempt to get from non-initial thread");
}
return value;
}
public Optional<T> getOpn() {
return Optional.ofNullable(get());
}
@Override
public void close() throws Exception {
if (!closed) {
synchronized (this) {
if (!closed) {
if (!isPresent()) {
throw new IllegalStateException("attempt to close from non-initial thread");
}
try {
final var value = get();
if (value instanceof AutoCloseable) {
((AutoCloseable) value).close();
}
} finally {
threadLocal.remove();
closed = true;
}
}
}
}
}
}
...
try (final var threadLocalTx = new ImmutableThreadLocalResource<MyTx>(new MyTx(...))) {
...
}
Основная прблема ThreadLocal в том, что вы не можете использовать одно значение в нескольких потоках по определению. Например, вы используете неблокирующий HTTP сервер (например, Undertow), котрый выделяет небольшое кол. потоков на обработку HTTP запроса, при этом обработка одного запроса может выполняться в нескольки потоках, если вы обращаетесь к внешним ресурсам — файлы, сеть (БД, внешний сервис ...). В этом случаи использование ThreadLocal приведет к серьезным проблемам, вот поэтому многие программисты не любят ThreadLocal, вот поэтому спринг со своими транзакциями и другими подходами, использующие ThreadLocal, обнулились и им пришлось реализовать WebFlux.
Так вот, из статьи не понятно, как же ScopedValue поможет нам решить основную проблему ThreadLocal — использование одного значения в нескольких потоках? Из JEP 428: Structured Concurrency (Incubator)
Simplify multithreaded programming by introducing an API for structured concurrency. Structured concurrency treats multiple tasks running in different threads as a single unit of work, thereby streamlining error handling and cancellation, improving reliability, and enhancing observability. This is an incubating API.
Т.е. API позволяет выполнять одну «работу» (UnitOfWork) в нескольких потоках. Например, обработка одного HTTP запроса в нескольких потоках, которые используют одну транзакцию, а по завершению обработки («работы»), транзакция закрывается (атоматом? возможность добавить специализированный код по закрытию? и т.д.).
Во первых, смысл код-ревью джуниора заключается в том, что бы джуниор поднял свой уровень, поэтому как-то удивляет, что джуниор делает подобное ревью. Во вторых, любые замечания по стилю кода должны приниматься только после добавления в проект документа «Code Style», если нет документа или замечание по стилю (включая имена) ни как не связано с документом, то можно (а по мне, так НУЖНО) мягко послать ревьювера на создание/расширение документа. Ну и по всем замечаниям надо задавать вопросы — как это улучшит читабельность, производительность и т.п. Вполне возможно, что он не джуниор и замечания имеют место быть, но без подробных пояснений вы не поймете, зачем все эти изменения.
Та нема за що дякувати. Бажаю вам у майбутньому ще більш потужний аналіз і синтез вашого мозку, щоб ваші відповіді були більш коротші і у той же час всеосяжні у познані всесвіту.
Почему редко получается? Вы судите об этом на основе 0.001% удачных стартапов, которые решили поделиться «формулой» своего успеха?
Все относительно. Рассмотрим вот такой кейс. Вы, стартап, выкатываете на рынок полурабочий продукт. В течении полугода вы постоянно выкатываете новые полурабочие фичи, с задержками исправляя старые баги. Вроде как клиенты растут — ваш продукт на текущем рынке не имеет конкурентов. Но вот тут, откуда не возьмись, через те же пол года появляется первый конкурент — имеет более удобный сервис и на порядок меньше багов. И новые фичи у него более чем рабочие. Через еще пол года конкурент вас полностью выкидывает с рынка (вам же как бы надо больше фичей, что бы конкурента задавить). К чему этот кейс? К тому, что срать на баги надо с умом, особенно если у вас есть или может появиться конкурент :). Так что надо искать баланс между рынком и качеством.
Роман, ваша глубока відповідь мене вразила. По цієї відповіді я можу сказати, що у вас глибоке мислення і неймовірна освіченість.
З моєю точки зору посил правильний, але висновки дуже суперечливі.
1. Назва «Юзер платить не за красивий код, а за вирішення його проблеми» не дуже бізнес-орієнтована :). Користувач платить за зрозумілий, зручний та якісний сервіс. Йому начхати на код і він не повинен думати про якісь проблеми, користуючись вашим сервісом (це стосується не тільки цифрової частини вашого сервісу).
2. Якщо ваша продуктова компанія надає тільки цифровий сервіс (технологічна продуктова компанія), то основні затрати компанії будуть на розробку (у сервісу може бути багато систем на бакенді, наприклад, мікросервісна архітектура, багато інтерфейсів, таких як мобільні, веб і т.д.), підтримку сервісу (баг фікс, зміна вже існуючих фічів, розробка нових та вбудування їх у ваш сервіс), підтримку інфраструктури та на саму інфраструктуру. Якщо дивитися з точки зору розробників, то вони повинні намагатися знайти оптимальну рівновагу між продуктивністю розроблених систем, витратами на інфраструктуру та часом розробки. Успішність цій рівноваги залежить, як мінімум, від двох факторів — процесс розробки і архітектура вашого сервісу (який може включати багато розроблювальних систем). Тобто, якщо ви (ваша компанія) забиває на архітектуру, то бог вам у поміч, тому що компанії буде нема на кого сподіватися коли почнеться... А воно може початися зі зростом користувачів та компанії :). Тобто я б не радив користуватися вашими порадами про нехтуванням архітектури чи DDD (якщо у вас складний домен). І зовсім не радив нехтувати принципами SOLID у будь якій ситуації при використанні об’єктно-орієнтованої платформи. SOLID ні як не гальмує розробку. Якщо ви не користуєтесь чи не вмієте користуватися SOLID принципами, наприклад, у джаві, то це тільки каже про ваш рівень розробника.
3. Питання до доцільності і час розробки. Є таки сервіси, у яких розроблена фіча доцільна на обмежений час, наприклад, у геймінгу новий модуль (нове проходження) доцільний на свята (жорстка дата делівері) і цим будуть користуватися не більше тижня, місяця... Або вам потрібно зрозуміти доцільність нової фічі, наприклад, у масмакреті. Подібна розробка і впровадження займе не багато часу, якщо у вас продумана та якісна архітектура вашого сервісу (який може включати багато систем, на кшталт мікросервісної архітектури), налагоджений процесс розробки і підтримки, у вас є нормальні розробники (і не тільки розробники), які розуміють, що таке прототипування і що з цим робити у майбутньому. Але щоб усе це було так легко та просто, треба вкластися у багато що, як мінімум у процесс розробки, архітектуру і найм співробітників :).
4. Якщо ваша розробка, а не тестування, орієнтована на data-driven, тобто, розробка більш менш тупого редактора БД чи перенесення даних з точки А у точку Б, то вам зовсім не потрібно перейматися бізнес-орієнтованістю. Вам потрібно перейматися тільки тим, щоб усі ваші дані були вчасно на місці :).
5. З порад автора для бізнес-орієнтованої розробки, як мінімум, я б виключив прокачування навичок стратегічного мислення :). Для розробки це зовсім не потрібно. Більшість компаній не має спеціалістів зі стратегічним мисленням. Більш того, більшість держав не має спеціалістів зі стратегічним мисленням, наприклад, держава України (я не про всіх громадян). Якщо ж вам цікаве стратегічне мислення, то почніть, наприклад, з банди чотирьох — Сергій Дацюк, Юрій Чудновський, Володимир Нікітін і Тарас Бебешко. Можливо вам це зайде :).
> Що не подобалося? Звичайно, низька зарплата — кілька тисяч гривень.
Жаль, что у нас не ценят искусство в школе и не только в ней.
Щось мені не дуже подобається логічне запитання про літак — як звати пілота літака? Авжеж це полковник ФСБ Іванов Іван Іванович. Чому так? Тому що не літають літаки з Києва до Стамбулу з такими пасажирами — це ІПСО.