Re[44]: MS забило на дотнет. Питону - да, сишарпу - нет?
От: Serginio1 СССР https://habrahabr.ru/users/serginio1/topics/
Дата: 03.09.21 18:16
Оценка:
Здравствуйте, vdimas, Вы писали:


V>Не обязательно.

V>Можно просто описать разные типы структур, читать поле-дискриминатор и приводить к соотв. структуре.
V>Твоё описание хорошо, когда одно поле всего в union, но бывает union структур.
Ну просто имея [FieldOffset()] и fixed byte data[] можно мапить структуру на любой IntPtr или byte[]
https://docs.microsoft.com/ru-ru/dotnet/api/system.runtime.interopservices.memorymarshal.asref?view=net-5.0#System_Runtime_InteropServices_MemoryMarshal_AsRef__1_System_Span_System_Byte__

MemoryMarshal.AsRef Метод
AsRef<T>(Span<Byte>)
Повторно интерпретирует массив байтов как ссылку на структуру типа T.

Копировать
public static ref T AsRef<T> (Span<byte> span) where T : struct;

Параметры типа
T
Тип возвращаемой ссылки.
Параметры
span
Span<Byte>
Повторно интерпретируемая массив.
Возвращаемое значение
T
Ссылка на структуру типа T.
Комментарии
T не может содержать указатели или ссылки. Он проверяется во время выполнения, чтобы обеспечить безопасность типа.

и солнце б утром не вставало, когда бы не было меня
Re[50]: MS забило на дотнет. Питону - да, сишарпу - нет?
От: Ночной Смотрящий Россия  
Дата: 03.09.21 20:42
Оценка: +1
Здравствуйте, vdimas, Вы писали:

V>>>И в любом случае твой пример только для MSSQL, а для любых других баз на основе OLEDB или ODBC

НС>>И много таких баз данных в реальности?
V>А много используют MSSQL в вебе?

Много. В Ажуре, к примеру, это основная РСУБД. К чему вопрос?

V>>>Разве что написали дотнетный драйвер к MS SQL, изначально это была обычная обёртка над OLEDB,

НС>>Никогда не была. Изначално это была обертка над низкоуровневоцй библиотекой парсинга протокола (tdslib.dll или как то так).
V>Над MS SQL Native Client.

Вроде того. Это не ADO, это более низкоуровневая штука.

V>В котором доступны были 3 вида подключения — ODBC, OLEDB и еще не помню название вида подключения


Нет. Конкретно та либа — обычная плоская dll со специфичным контрактом, по сути просто парсер TDS. ODBC и OLEDB драйвера сами ее используют, а не являются ее частью.

НС>>Хинты, как показывает практика, нужны хорошо если в 1% запросов. Это почему DAL не стоит затачивать под конкретного провайдера.

V>Как показывает практика, 1% запросов используется в 99% случаев.

Это неважно. Потому что 1% запросов это 1% кода, и проще сделать для 1% специальное исключение, а не переписывать ради этого под каждый сервер оставшиеся 99%.
... << RSDN@Home 1.3.17 alpha 5 rev. 62>>
Re[50]: MS забило на дотнет. Питону - да, сишарпу - нет?
От: Ночной Смотрящий Россия  
Дата: 03.09.21 21:10
Оценка:
Здравствуйте, vdimas, Вы писали:

V>Куда я тебе показал в первый раз — это реализация ODBC драйвера.

V>Все базы имеют ODBC-дрова, но далеко не все имеют OLEDB.
V>Например, нет OLEDB драйвера к самой популярной в вебе базе MySQL.
V>Следующая по популярности идёт PostgreSQL, к ней тоже живые/актуальные только ODBC-дрова.

Опять за рыбу деньги. ADO.NET драйвера и к MySQL, и к Postgres — полностью managed, не используют ни ODBC, ни OLEDB, ни вообще какую либо внешнюю библиотеку. Я сейчас вообще затрудняюсь придумать хоть одну БД, где бы ODBC или OLEDB мост был бы единственным выбором в силу отсутствия pure драйвера.

V>Для MS Access! ))


О, точно. Есть такое.

V>То бишь, самим реализовать всё семейство с 0-ля: IDbConnection, IDbTransaction, IDbCommand и еще пару десятков (если не больше) сущностей из модели ADO.Net.


Не пару десятков, меньше. Да, так и делают на практике. Но есть еще драйвера для EF (их, правда, далеко не все делают).
... << RSDN@Home 1.3.17 alpha 5 rev. 62>>
Re[44]: MS забило на дотнет. Питону - да, сишарпу - нет?
От: Sinclair Россия https://github.com/evilguest/
Дата: 04.09.21 06:43
Оценка: 6 (2)
Здравствуйте, vdimas, Вы писали:

V>Хотя, подозреваю, что быстродействие вызова UnmanagedCallersOnly-метода должно быть примерно на уровне DllImport.

Ну, с практической точки зрения там почти всё — бессмысленно. Вот эти все "давайте получим анменеджед указатель на менеджед делегат, и вызовем его из менеджед кода" — нулевая практическая ценность.
Удивительно то, что вызов через делегат, ещё недавно чуть ли не на порядок проигрывавший вызову через интерфейс, теперь сравнялся — у меня делегат вышел даже быстрее.
В общем, предсказуемым образом, менеджед код быстрее всего вызывать через managed func pointer, а анменеджед — через PInvoke без переключения GC.

Methodm MeanErrorStdDevMedianOverhead Ratio
CallTestBaseline 173.9 μs3.44 μs9.37 μs173.2 μs0%
CallTestManaged func ptr245.1 μs3.37 μs2.63 μs244.9 μs100%
CallTestDelegate from MI335.8 μs3.94 μs3.29 μs336.2 μs227%
CallTestDelegate339.1 μs6.72 μs13.57 μs337.5 μs232%
CallTestInterface371.3 μs7.32 μs14.10 μs368.6 μs277%
CallTestDllImportNGC399.2 μs7.98 μs18.50 μs392.3 μs316%
CallTestDllImport901.5 μs14.52 μs12.12 μs896.8 μs1022%
CallTestDllGetProcAddr950.6 μs18.98 μs39.61 μs935.4 μs1091%
CallTestPtr from delegate1,572.6 μs19.71 μs21.91 μs1,564.2 μs1964%
CallTestUnmanaged func ptr8,796.0 μs174.14 μs232.47 μs8,690.9 μs12110%
CallTestDelegate from ptr10,214.0 μs158.16 μs231.83 μs10,140.2 μs14101%
Самый дешёвый вызов — по менеджед указателю — на моём процессоре стоит 7ns. Вызов через делегат — 16ns, в 2.3 раза дороже. Примерно в том же классе вызов через интерфейс.
Вызов простого PInvoke, который сам быстро исполняется и не лезет в менеджед-данные, стоит 22.5ns — втрое дороже, чем менеджед вызов, но всё ещё в 2.5 раза дешевле, чем обычный PInvoke через DllImport или через GetProcAddress. (73 ns). Вызовы менеджед кода как анменеджед стоят космически дорого (1мкс), но они и не нужны. Более жизненным сценарием было бы замерить вызов менеджед кода через колбэк.
Но и там основное, для чего нужно такое измерение — это чтобы понимать, какими должны быть масштабы объёма нативной работы, чтобы взаимодействие с ней было оправданым.
То есть когда мы говорим "вот тебе десять мегов данных, позови меня, когда отправишь" — это норм. А когда мы говорим: "вот тебе массив из 100 менеджед указателей, давай ты его отсортируешь, вызывая вот этот колбек для сравнения каждого из них" — это не норм, не надо так делать.
Уйдемте отсюда, Румата! У вас слишком богатые погреба.
Отредактировано 04.09.2021 7:08 Sinclair . Предыдущая версия .
Re[7]: MS забило на дотнет. Питону - да, сишарпу - нет?
От: Sinclair Россия https://github.com/evilguest/
Дата: 04.09.21 07:06
Оценка: 3 (2) +1
Здравствуйте, vfedosov, Вы писали:

V>Ну вот к примеру +- типичная задача: нужно развернуть индекс: есть индекс по одному ключу, надо построить по другому. В пайтоне решается так:

V>names2data = {"name1": (1, 3, "str1"), "name2": (2, 4, "str2")}
V>data2names = {data[1]: name for name, data in names2data.items()}
Не очень понимаю синтаксис — что делает эта штука?
V>я не в курсе, может последние версии шарпа позволяют коротко эту задачу решить — уж лет 6-7 не работаю с шарпом, но пайтон и 10 лет назад это поддерживал. Насколько кратко можно проинициализировать сложную структуру данных и насколько легко с ней работать! Кстати работает мега быстро в отличии от довольно медленного Linq.

V>Или обработка массивов float — работает почти как на плюсах по скорости. Имеем двумерный numpy массив — картинку (яркости пикселей нормированы к 1.0), надо сделать ярче в 1.5 раза, но значения не должны быть больше 1.0:

V>array_2d = np.min(array_2d * 1.5, 1.0)
V>Может слегка с синтаксисом в примерах накосячил (влом проверять) — но суть такая.
V>Представь чего на шарпе придется нагородить для этого
Ну, вот я себе хорошо это представляю.
array_2d = (from a in array_2d select Math.Min(a*1.5, 1.0)).ToArray();

https://github.com/evilguest/linq2d
V>и сколько это работать будет по времени.
Ну, некоторые вещи работают быстрее, чем на плюсах. Может быть, numpy написан получше — можем помериться, если есть желание.
V>Работа с массивами в numpy вообще впечатляет — очень элегантно. Занимаясь имадж процессингом, я понял, что плюсы не нужны почти нигде — все можно сделать на пайтоне — и не будет тормозить!
V>На шарпе это невозможно.
Вы недооцениваете шарп.
Уйдемте отсюда, Румата! У вас слишком богатые погреба.
Re[42]: MS забило на дотнет. Питону - да, сишарпу - нет?
От: Sinclair Россия https://github.com/evilguest/
Дата: 04.09.21 09:46
Оценка: 4 (2)
Здравствуйте, vdimas, Вы писали:

V>Это следствие невозможности боксирования.

V>Следствие невозможности располагаться в полях не ref-struct типов.
Я в курсе — но, тем не менее, ограничение такое есть.

V>Не обязательно ограничена интеропом, просто хорошо подходит как доп. искуственно-вводимые разработчиком ограничения через систему типов.

V>Для пущей безопасности, кароч, чтобы временные ссылки никуда случайно не утекли.
Ну так в том-то и дело, что не так много случаев, когда в гражданском коде мы будем пользоваться вот такой вот структурой "ограниченного действия".

V>Случаев сразу несколько.

V>Раньше был доступен stackalloc только под примитивные blit-типы.
V>Например, делаешь byte * b = stackallock byte[N], затем приводишь к указателю на структуру.
V>Потом стало можно привести к управляемой ref-ссылке на структуру через CompilerServices.Unsafe.
V>В последней версии C# можно делать stackalloc пользовательских структур, которые вдоль всей иерархии агрегации состоят или из простых типов или структур, состоящих из простых типов.
V>Т.е. структуры, попадающие под ограничение unmanaged.
V>В т.ч. в теле которых располагаются inplace-массивы примитивных типов или тоже unmanaged структур.
Ага, вы говорите про "массивы структур". Но ведь с ними и до этого особенных проблем не было — ну, разве что, кроме случаев, когда сама структура не нужна за пределами текущего фрейма стека, и не хочется нагружать GC.
Я-то имел в виду работу с flexible array member https://en.wikipedia.org/wiki/Flexible_array_member

V>>>Чтобы GC игнорировал стек нейтивных вызовов.

V>>>Т.е., возможна зебра вглубь всех вызовов:
V>>>- из управляемого кода в нейтив;
V>>>- оттуда приходит колбэк в управляемый код (многие перечисления в системных АПИ так работают);
V>>>- из этого фрейма опять вызывается что-то в нейтиве.
S>>Ну в вашем-то случае весь метод — это инкремент лонга по указателю. Никаких колбэков, никаких зебр.

V>У меня просто бенчмарк различных способов вызова ф-ий.

V>А ты спрашивал, зачем замыкается стек перед вызовом нейтивной функциональности.
V>А как GC должен знать, где в стеке управляемые данные, а где игнорить?
Программист ему подскажет, где можно безопасно игнорить, при помощи SuppressGCTransition.

V>Стек замыкается в любом случае, т.к. GC stop world никто не отменял.

Для конкретного метода с инкрементом отключение GC Transition ускоряет вызов в натив вдвое. Если вычитать baseline — то втрое.
Для часто вызываемых микро-методов типа "набъём команды в буфер" — самое то.

V>Средней руки приложение может компиляться под AOT iOS несколько минут, сколько-нибудь большое — десятки минут.

V>Поэтому, всё это херня собачья, гнаться за хотспотом.
Не уверен.

V>Над разрабывать либы так, чтобы они были готовы к нейтивной компиляции потом, а клиент при публикации своего приложения пусть запускает АОТ-оптимизатор.


V>Ну, у нас зато тоже в некоторых проектах тонны статического-справочного кода, вот на такх проектах разница видна хорошо.

V>И что характерно — если эти "справочные" данные бинарно сериализовать (не встроенной бинарной сериализацией, которой теперь тоже нет в .Net Core, а просто ручками), сохранить в ресурсах, а потом при старте прочесть — это занимает примерно 30 ms. А в исходном виде добавляло примерно 400 ms.
Непонятно, откуда тормоза.

S>>Это для десктопа. А для любимого мной бэкенда важен именно хотспот, т.к. никакой AOT не предскажет реальную нагрузку.

V>А толку, если нагрузка может меняться?
Ну так для того хотспот в джаве и умеет повторно джиттить уже отджиттенный код. Нагрузка поменялась => метод перекомпилировали.
V>В нейтиве для этого отродясь было PGO.
V>К АОТ его тоже надо прикручивать.
У PGO ровно та же самая проблема — устаревание данных.

V>Хотя, АОТ хорош тем, что не рассматривает типы как открытые, хотя бы по виртуальности/наследованию.

Это как это он так не рассматривает? А если я динамически код сгенерю? А если будет подгружена новая сборка?

V>Плюс, у него достаточно времени на всевозможные оптимизации.

Для "настольного" применения — согласен, АОТ нужен. А для серверсайда, когда приложение живёт неделями, выделить 1% времени на дооптимизацию даст столько времени, что никакому АОТ столько не дадут.
V>Т.е. и дефолтная оптимизация может много чего дать.
Да для начала надо бы, конечно, просто глупостей не делать. Например, всё таки оптимизировать порождаемый IL.
V>Просто непонятно — когда это всё будет в наличии! ))
Отож.

V>Просто это был бы не Рослин, а портированный на шарп плюсовый компилятор.

V>По моему опыту, портирование кода из С++ в дотнет тривиальное (это обратно нетривиально), у меня получалось портировать примерно 2 тыс строк в день.
V>Если хотя бы 4-5 человек навалятся, первый шарповый компилятор на шарпе можно было бы получить примерно за неделю.
Ну ХЗ. Почему-то они так делать не хотели.

V>Просто они вообще с 0-ля его писали.

V>Наглухо.
V>Похоже, еще и учились писать компилятор в процессе, бгг...
V>Заодно похерили ранее сделанные вложения в уже имеющийся компилятор.

V>Детсад, штаны на лямках.


V>Я же почитывал Липперта — он нифига не спец в компиляторостроении.

V>Это отдельная дисциплина, не бог весть какая сложная, но в ней надо шарить...
V>Желательно, до начала разработки...
V>А эти гаврики с шашкой на танк помчались.
V>Результат известен.
Уйдемте отсюда, Румата! У вас слишком богатые погреба.
Re[38]: MS забило на дотнет. Питону - да, сишарпу - нет?
От: Sinclair Россия https://github.com/evilguest/
Дата: 04.09.21 10:22
Оценка:
Здравствуйте, vdimas, Вы писали:

V>Здравствуйте, Sinclair, Вы писали:

V>>>Еще раз, медленно — интероп в C# медленный.
Как оказалось — нет, не медленный.
V>>>Требуется сокращать его до минимума.
S>>Эмм, а чего там медленного?
S>>И, главное, как нода-то ухитряется сделать интероп быстрее?

V>Ноде не надо заботиться о фреймах стека для GC, поэтому, вызывает нейтивные ф-ии напрямую.

Хм. Почему же ноде не надо заботиться о фреймах стека? Она же тоже менеджед и с GC.
Уйдемте отсюда, Румата! У вас слишком богатые погреба.
Re[8]: MS забило на дотнет. Питону - да, сишарпу - нет?
От: Ночной Смотрящий Россия  
Дата: 04.09.21 11:35
Оценка:
Здравствуйте, Sinclair, Вы писали:

V>>На шарпе это невозможно.

S>Вы недооцениваете шарп.

Ну, с другой стороны это вполне валидная причина не использовать шарп. Он явно лучше знает python/numpy, нежели дотнет с современным шарпом.
... << RSDN@Home 1.3.17 alpha 5 rev. 62>>
Re[8]: MS забило на дотнет. Питону - да, сишарпу - нет?
От: vfedosov  
Дата: 04.09.21 20:51
Оценка:
Здравствуйте, Sinclair, Вы писали:

S>Здравствуйте, vfedosov, Вы писали:


V>>Ну вот к примеру +- типичная задача: нужно развернуть индекс: есть индекс по одному ключу, надо построить по другому. В пайтоне решается так:

V>>names2data = {"name1": (1, 3, "str1"), "name2": (2, 4, "str2")}
V>>data2names = {data[1]: name for name, data in names2data.items()}
S>Не очень понимаю синтаксис — что делает эта штука?

ну первая строка создает Dictionary<string, (int, int, string)> и заполняет его 2мя элементами. Это индекс — по аналогии с индексами БД — возможность быстро получить данные по имени. Быстро означает за O(ln(n)) или O(1) — полный перебор не канает.
Вторая строка создает новый Dictionary<int, string> — который содержит второй int и key из первого. Это индекс, который позволяет быстро перейти от int к name. Причем после второй строки он уже заполнен и готов к работе. Далее, если в коде тебе нужно получить быстро name для которого второй int = 3, ты пишешь:

name = data2names[3]

V>>я не в курсе, может последние версии шарпа позволяют коротко эту задачу решить — уж лет 6-7 не работаю с шарпом, но пайтон и 10 лет назад это поддерживал. Насколько кратко можно проинициализировать сложную структуру данных и насколько легко с ней работать! Кстати работает мега быстро в отличии от довольно медленного Linq.



V>>Или обработка массивов float — работает почти как на плюсах по скорости. Имеем двумерный numpy массив — картинку (яркости пикселей нормированы к 1.0), надо сделать ярче в 1.5 раза, но значения не должны быть больше 1.0:

V>>array_2d = np.min(array_2d * 1.5, 1.0)
V>>Может слегка с синтаксисом в примерах накосячил (влом проверять) — но суть такая.
V>>Представь чего на шарпе придется нагородить для этого
S>Ну, вот я себе хорошо это представляю.
S>
S>array_2d = (from a in array_2d select Math.Min(a*1.5, 1.0)).ToArray();
S>

Это ты написал для одномерного массива. Для двумерного это будет сложнее — как раз раза в 3, чем код на пайтоне. А представь, что нужно работать с двумерным массивом RGB пикселей — то есть каждый элемент массива — тоже массив из 3х элементов. Таким образом, массив 3х-мерный. Код на пайтоне будет тот-же, а на шарпе придется дальше разворачивать.
S>https://github.com/evilguest/linq2d
V>>и сколько это работать будет по времени.
S>Ну, некоторые вещи работают быстрее, чем на плюсах. Может быть, numpy написан получше — можем помериться, если есть желание.

Не может этот код быстро работать, так как там виртуальное вызовы IEnumerable идут — причем несколько вызовов на одну итерацию. Шарп не поддерживает inline для подобных вызовов и работает раз в 10-50 медленнее нативного кода в таких случаях — проверено не раз — я не преувеличиваю. При каждом виртуальном вызове идет копирование всех аргументов, создание точки возврата из функции, обращение к виртуальной таблице — куча ненужного дерьма, которое несопоставимо по объему с основной операцией — умножит на 1.5 и сравнить с единицей. Это если обойдется без аллокаций — а шарп иногда преподносит сюрпризы и выполняет аллокации там, где совсем не ожидаешь, начисто убивая производительность. А в пайтоне используется нативная имплементация без всякой виртуальности — все вызовы функций там заинлайнены и алгоритм выполняет только полезную работу — умножить, сравнить, записать результат, передвинуть указатель к следующему значению (если не последнее) — все! Думаю, они там еще и векторные инструкции процессора используют — уж слишком все быстро летает.

V>>Работа с массивами в numpy вообще впечатляет — очень элегантно. Занимаясь имадж процессингом, я понял, что плюсы не нужны почти нигде — все можно сделать на пайтоне — и не будет тормозить!

V>>На шарпе это невозможно.
S>Вы недооцениваете шарп.

Да я с ним немало поработал в свое время — знаю пределы возможностей. Но я не считаю, что Шарп must die. Как уже писал, Пайтон бесспорно хорош для простых проектов — желательно с одним разработчиком. В команде уже надо очень жестко следить за тем, кто чего пишет. Иначе код быстро станет несопровождабельным. И для проекта со сложной бизнес-логикой и/или сложным UI я бы все еще выбрал Шарп.
Отредактировано 04.09.2021 21:11 vfedosov . Предыдущая версия . Еще …
Отредактировано 04.09.2021 20:52 vfedosov . Предыдущая версия .
Re[7]: MS забило на дотнет. Питону - да, сишарпу - нет?
От: Nuzhny Россия https://github.com/Nuzhny007
Дата: 04.09.21 21:06
Оценка:
Здравствуйте, vfedosov, Вы писали:

V>Занимаясь имадж процессингом, я понял, что плюсы не нужны почти нигде — все можно сделать на пайтоне — и не будет тормозить! На шарпе это невозможно.


Именно поэтому всё для скорости переписывают с Питона или на плюсы для картинок, или вообще на Java/Scala. Если же есть готовая библиотека типа OpenCV, то код на плюсах может быть ещё и компактней, чем на Питоне. И при этом оптимизироваться проще. Так что это всё эфемерность, что Питона достаточно. Узкие места переписывают на плюсы сплошь и рядом, а то и все проекты целиком.
Re[9]: MS забило на дотнет. Питону - да, сишарпу - нет?
От: vfedosov  
Дата: 04.09.21 21:23
Оценка:
Здравствуйте, Ночной Смотрящий, Вы писали:

НС>Здравствуйте, Sinclair, Вы писали:


V>>>На шарпе это невозможно.

S>>Вы недооцениваете шарп.

НС>Ну, с другой стороны это вполне валидная причина не использовать шарп. Он явно лучше знает python/numpy, нежели дотнет с современным шарпом.


С Пайтоном опыта намного меньше чем с Шарпом. С последними версиями действительно не работал, но общий опыт работы с шарпом — лет 6-7. Работал в качестве программиста, архитектора и тим-лида в коммандах на C#. А на Пайтоне иногда простенькие скрипты пишу — день в месяц в среднем. Плюс иногда с нейросетями экспериментирую. Только в последний месяц занялся чем-то посерьезнее — пишу генератор Unit Tests для проекта, ибо отраслевое требование — 100% кода покрывать тестами, а времени на нормальные тесты у нас нет. Вот и выбрал Пайтон, как язык, на котором эту задачу можно решить наиболее эффективно. Код работает быстрее (а это важно — проект колоссальный по объему кода), чем аналогичный на шарпе и синтаксис лаконичнее. Пайтон не разочаровал — тесты генерятся достаточно быстро и код пока вполне сопровождабелен.
Отредактировано 04.09.2021 21:28 vfedosov . Предыдущая версия .
Re[9]: MS забило на дотнет. Питону - да, сишарпу - нет?
От: Sinclair Россия https://github.com/evilguest/
Дата: 05.09.21 03:40
Оценка:
Здравствуйте, Ночной Смотрящий, Вы писали:

НС>Ну, с другой стороны это вполне валидная причина не использовать шарп. Он явно лучше знает python/numpy, нежели дотнет с современным шарпом.

Отож — я и сам большой фанат ignorance-based decision making
Уйдемте отсюда, Румата! У вас слишком богатые погреба.
Re[9]: MS забило на дотнет. Питону - да, сишарпу - нет?
От: Sinclair Россия https://github.com/evilguest/
Дата: 05.09.21 03:46
Оценка:
Здравствуйте, vfedosov, Вы писали:

V>Здравствуйте, Sinclair, Вы писали:


S>>Здравствуйте, vfedosov, Вы писали:


V>>>Ну вот к примеру +- типичная задача: нужно развернуть индекс: есть индекс по одному ключу, надо построить по другому. В пайтоне решается так:

V>>>names2data = {"name1": (1, 3, "str1"), "name2": (2, 4, "str2")}
V>>>data2names = {data[1]: name for name, data in names2data.items()}
S>>Не очень понимаю синтаксис — что делает эта штука?

V>ну первая строка создает Dictionary<string, (int, int, string)> и заполняет его 2мя элементами. Это индекс — по аналогии с индексами БД — возможность быстро получить данные по имени. Быстро означает за O(ln(n)) или O(1) — полный перебор не канает.

V>Вторая строка создает новый Dictionary<int, string> — который содержит второй int и key из первого. Это индекс, который позволяет быстро перейти от int к name. Причем после второй строки он уже заполнен и готов к работе.
А, понятно. data[1]:name — это то, что мы получаем; name, data — переменные итерирования.
Тогда на шарпе это будет так:
var names2data = new Dictionary<string, (int, int, string)>() {["name1"]= (1, 3, "str1"), ["name2"] = (2, 4, "str2")};
var data2names = (from d in names2data select (d.Value.Item2, d.Key)).ToDictionary((t)=>t.Item1, (t)=>t.Key);

Если такого добра будет много, дописываем один раз вот такой однострочник:
public static class TupleEnumerable
{
    public static Dictionary<K, V> ToDictionary<K,V>(this IEnumerable<(K,V)> enumerable)
        => enumerable.ToDictionary((t)=>t.Item1, (t)=>t.Item2);
}

И вторая строка превращается в:
var data2names = (from d in names2data select (d.Value.Item2, d.Key)).ToDictionary();

V>Далее, если в коде тебе нужно получить быстро name для которого второй int = 3, ты пишешь:

V>name = data2names[3]

Да, тут всё точно так же. Ну, только читается получше, и компилятор проверяет типы. Ценой, понятное дело, дописывания к инициализациям деклараций вроде Dictionary<string, (int, int, string)>.

V>>>я не в курсе, может последние версии шарпа позволяют коротко эту задачу решить — уж лет 6-7 не работаю с шарпом, но пайтон и 10 лет назад это поддерживал. Насколько кратко можно проинициализировать сложную структуру данных и насколько легко с ней работать! Кстати работает мега быстро в отличии от довольно медленного Linq.

Ну, linq медленный не весь.

V>Это ты написал для одномерного массива. Для двумерного это будет сложнее — как раз раза в 3, чем код на пайтоне.

Нет, я написал для двумерного.
V>А представь, что нужно работать с двумерным массивом RGB пикселей — то есть каждый элемент массива — тоже массив из 3х элементов. Таким образом, массив 3х-мерный. Код на пайтоне будет тот-же, а на шарпе придется дальше разворачивать.
Не массив, а структура. Да, там эффективность C# будет не такой впечатляющей — надо допиливать библиотеку.
S>>https://github.com/evilguest/linq2d
V>Не может этот код быстро работать, так как там виртуальное вызовы IEnumerable идут — причем несколько вызовов на одну итерацию.
Там нет никаких виртуальных вызовов. Генерируется нативный код с векторными инструкциями. Он работает чуть быстрее идиоматического плюсового кода. Сходите по ссылке, почитайте текст, посмотрите видео.
V>Да я с ним немало поработал в свое время — знаю пределы возможностей. Но я не считаю, что Шарп must die. Как уже писал, Пайтон бесспорно хорош для простых проектов — желательно с одним разработчиком. В команде уже надо очень жестко следить за тем, кто чего пишет. Иначе код быстро станет несопровождабельным. И для проекта со сложной бизнес-логикой и/или сложным UI я бы все еще выбрал Шарп.
Пределов возможностей шарп не знает никто .
У него очень большой потенциал. И довольно много из него уже реализовано. Именно за это я его и люблю — в отличие от пайтона, мне не нужно переключаться на другой язык для того, чтобы что-то улучшить.
Тот же Linq для IEnumerable написан на том же шарпе, что и использующий его код.
Уйдемте отсюда, Румата! У вас слишком богатые погреба.
Отредактировано 05.09.2021 4:04 Sinclair . Предыдущая версия .
Re[10]: MS забило на дотнет. Питону - да, сишарпу - нет?
От: vfedosov  
Дата: 05.09.21 07:08
Оценка:
S>var names2data = new Dictionary<string, (int, int, string)>() {["name1"]= (1, 3, "str1"), ["name2"] = (2, 4, "str2")};
S>var data2names = (from d in names2data select (d.Value.Item2, d.Key)).ToDictionary((t)=>t.Item1, (t)=>t.Key);

ну ToDictionary() и tuple реально хорошие нововведения — когда я работал на шарпе подобные вещи куда сложнее писать было. Но формально Пайтон всеравно лаконичнее — даже после класса-однострочника. Причем, это старый синтаксис Пайтона — для версий 2.x работает. В простых проектах в одно рыло, типизация не нужна совсем — по крайней мере мне она ничем не помогает. Читабельность подобных пайтоновских конструкций не уступает шарповским — при наличии привычки. Но для сложных и коммандных проектов шарп явно способен что-то предложить.



V>>Это ты написал для одномерного массива. Для двумерного это будет сложнее — как раз раза в 3, чем код на пайтоне.

S>Нет, я написал для двумерного.

Ну я попытался на своей VS2013 (более новые версии не доступны в нашей конторе) скомпилять следующий код:
        static void test()
        {
            var array2d = new double[1000, 1000];
            array2d = (from a in array2d select Math.Min(a * 1.5, 1.0)).ToArray();
        }

ошибка: Error 1 Could not find an implementation of the query pattern for source type 'double[*,*]'. 'Select' not found. Are you missing a reference or a using directive for 'System.Linq'? c:\users\vfedosov\documents\visual studio 2013\Projects\ConsoleApplication2\ConsoleApplication2\Program.cs 30 34 ConsoleApplication2

для одномерного массива вполне компиляется:
       static void test()
        {
            var array2d = new double[1000000];
            array2d = (from a in array2d select Math.Min(a * 1.5, 1.0)).ToArray();
        }

Чего я и ожидал собственно. Или в новых версия .Net есть "implementation of the query pattern for source type 'double[*,*]'" ? И если есть, то что будет на выходе ToArray() в этом случае? Одномерный массив?

Далее я сделал тест производительности — для одномерного массива. Код на шарпе:

class Program
    {   
        public virtual double[] multiply(double[] array2d)
        {
            array2d = (from a in array2d select Math.Min(a * 1.5, 1.0)).ToArray();
            return array2d;
        }

        static void Main(string[] args)
        {
            Program p = new Program();
            var array2d = new double[1000000];
            
            for (int i = 0; i < 1000; ++i)
                array2d = p.multiply(array2d);
        }


вирульный метод введен, чтобы компилятор не попытался оптимизировать ненужный рассчет. Данный код в релизе выполняется более 20 секунд на моем ноуте.
Аналогичный код на Пайтон:


def multiply(arr):
    arr = np.minimum(arr*1.5, 1.0)
    return arr


array1D = np.ones([1000000], dtype=float)

for i in range(1000):
    array1D = multiply(array1D)

выполняется вдвое быстрее даже без компиляции в exe. А нативный код — С++, который делает ту-же работу, выполняется в 5 раз быстрее. В принципе результат шарпа все равно лучше, чем я ожидал — Linq действительно работает более оптимально, чем я ожидал и умудряется избежать какой-то части лишних действий. Но Пайтон быстрее.

S>Пределов возможностей шарп не знает никто .

Это, похоже, правда
Отредактировано 05.09.2021 8:04 vfedosov . Предыдущая версия . Еще …
Отредактировано 05.09.2021 7:55 vfedosov . Предыдущая версия .
Отредактировано 05.09.2021 7:54 vfedosov . Предыдущая версия .
Отредактировано 05.09.2021 7:50 vfedosov . Предыдущая версия .
Отредактировано 05.09.2021 7:13 vfedosov . Предыдущая версия .
Отредактировано 05.09.2021 7:09 vfedosov . Предыдущая версия .
Отредактировано 05.09.2021 7:08 vfedosov . Предыдущая версия .
Re[8]: MS забило на дотнет. Питону - да, сишарпу - нет?
От: vfedosov  
Дата: 05.09.21 07:32
Оценка:
Здравствуйте, Nuzhny, Вы писали:

N>Здравствуйте, vfedosov, Вы писали:


V>>Занимаясь имадж процессингом, я понял, что плюсы не нужны почти нигде — все можно сделать на пайтоне — и не будет тормозить! На шарпе это невозможно.


N>Именно поэтому всё для скорости переписывают с Питона или на плюсы для картинок, или вообще на Java/Scala. Если же есть готовая библиотека типа OpenCV, то код на плюсах может быть ещё и компактней, чем на Питоне. И при этом оптимизироваться проще. Так что это всё эфемерность, что Питона достаточно. Узкие места переписывают на плюсы сплошь и рядом, а то и все проекты целиком.


Ну OpenCV доступна на Python — собственно я с ней и работаю в основном. И я бы не сказал, что прям все переписывается на плюсы — иногда приходится — ИМХО где-то треть тасок с имаджпроцессингом приходится писать на плюсах. Иногда и ассемблер нужен — таких тасок процентов 5. Но не Java!. С какой стати на Java код будет работать быстрее?
Насчет компактности OpenCV кода на плюсах тоже неправда. Пайтоновский как минимум не хуже — а ИМХО намного более компактен.
Отредактировано 05.09.2021 7:37 vfedosov . Предыдущая версия . Еще …
Отредактировано 05.09.2021 7:36 vfedosov . Предыдущая версия .
Re[11]: MS забило на дотнет. Питону - да, сишарпу - нет?
От: Serginio1 СССР https://habrahabr.ru/users/serginio1/topics/
Дата: 05.09.21 08:37
Оценка:
Здравствуйте, vfedosov, Вы писали:


V>Чего я и ожидал собственно. Или в новых версия .Net есть "implementation of the query pattern for source type 'double[*,*]'" ?


Ты всегда можешь написать расширение
 public static class TwoDimensionalArrayEnumerable
    {
        public static IEnumerable<T> ToEnumerable<T>(this T[,] array)
        {
            for (int i = array.GetLowerBound(0); i <= array.GetUpperBound(0); i++)
            {
                for (int j = array.GetLowerBound(1); j <= array.GetUpperBound(1); j++)
                {

                    yield return array[i, j];
                }
            }
        }

        public static T[,] ToArray<T>(this IEnumerable<T> en, T[,] array)
        {
            var result = array;//(T[,]) Array.CreateInstance(typeof(T), fub, sub);
            var elemCount = array.GetUpperBound(1) - array.GetLowerBound(1) + 1;
            int ind = 0;
            foreach(T elem in en)
            {
                result[ind / elemCount, ind % elemCount] = elem;
                ind++;
            }

            return result;
        }
}


static void TestLinq()
        {
            var array2d = new double[1000, 1000];
            array2d = (from a in array2d.ToEnumerable()  select Math.Min(a * 1.5, 1.0)).ToArray(array2d);

        }


Есть прекраснейшая конструкция yield на основании которой ты можешь строить любые итераторы.
Для использования как в питоне, нужно просто сконструировать класс который будет держать данные о массиве.
Лениво
и солнце б утром не вставало, когда бы не было меня
Re[12]: MS забило на дотнет. Питону - да, сишарпу - нет?
От: vfedosov  
Дата: 05.09.21 08:55
Оценка:
Здравствуйте, Serginio1, Вы писали:

S>Здравствуйте, vfedosov, Вы писали:



V>>Чего я и ожидал собственно. Или в новых версия .Net есть "implementation of the query pattern for source type 'double[*,*]'" ?


S>Ты всегда можешь написать расширение

S>
S> public static class TwoDimensionalArrayEnumerable
S>    {
S>        public static IEnumerable<T> ToEnumerable<T>(this T[,] array)
S>        {
S>            for (int i = array.GetLowerBound(0); i <= array.GetUpperBound(0); i++)
S>            {
S>                for (int j = array.GetLowerBound(1); j <= array.GetUpperBound(1); j++)
S>                {

S>                    yield return array[i, j];
S>                }
S>            }
S>        }

S>        public static T[,] ToArray<T>(this IEnumerable<T> en, T[,] array)
S>        {
S>            var result = array;//(T[,]) Array.CreateInstance(typeof(T), fub, sub);
S>            var elemCount = array.GetUpperBound(1) - array.GetLowerBound(1) + 1;
S>            int ind = 0;
S>            foreach(T elem in en)
S>            {
S>                result[ind / elemCount, ind % elemCount] = elem;
S>                ind++;
S>            }

S>            return result;
S>        }
S>}
S>


S>
S>static void TestLinq()
S>        {
S>            var array2d = new double[1000, 1000];
S>            array2d = (from a in array2d.ToEnumerable()  select Math.Min(a * 1.5, 1.0)).ToArray(array2d);

S>        }
S>


S> Есть прекраснейшая конструкция yield на основании которой ты можешь строить любые итераторы.

S>Для использования как в питоне, нужно просто сконструировать класс который будет держать данные о массиве.
S>Лениво

Вот и мне лениво — поэтому предпочитаю на Пайтоне простые задачи решать. Одна из основных концепций Пайтона — простые вещи должны делаться просто.
Про yield я в курсе. Он и на Пайтоне есть — с точно такой-же функциональностью. Думаю с Пайтона его и собрали в .Net — хотя не уверен.
Re[13]: MS забило на дотнет. Питону - да, сишарпу - нет?
От: Serginio1 СССР https://habrahabr.ru/users/serginio1/topics/
Дата: 05.09.21 10:35
Оценка:
Здравствуйте, vfedosov, Вы писали:


S>> Есть прекраснейшая конструкция yield на основании которой ты можешь строить любые итераторы.

S>>Для использования как в питоне, нужно просто сконструировать класс который будет держать данные о массиве.
S>>Лениво

V>Вот и мне лениво — поэтому предпочитаю на Пайтоне простые задачи решать. Одна из основных концепций Пайтона — простые вещи должны делаться просто.

V>Про yield я в курсе. Он и на Пайтоне есть — с точно такой-же функциональностью. Думаю с Пайтона его и собрали в .Net — хотя не уверен.
На самом деле на шарпе можно решать любые задачи с той же эффективностью. Учитываю, что большинство использует нетипизированный питон, то на шарпе используя
интеллисенс и прочие удобства IDE можно писать даже быстрее.
Это уже дело привычки
и солнце б утром не вставало, когда бы не было меня
Re[14]: MS забило на дотнет. Питону - да, сишарпу - нет?
От: vfedosov  
Дата: 05.09.21 11:30
Оценка:
Здравствуйте, Serginio1, Вы писали:

S>Здравствуйте, vfedosov, Вы писали:



S>>> Есть прекраснейшая конструкция yield на основании которой ты можешь строить любые итераторы.

S>>>Для использования как в питоне, нужно просто сконструировать класс который будет держать данные о массиве.
S>>>Лениво

V>>Вот и мне лениво — поэтому предпочитаю на Пайтоне простые задачи решать. Одна из основных концепций Пайтона — простые вещи должны делаться просто.

V>>Про yield я в курсе. Он и на Пайтоне есть — с точно такой-же функциональностью. Думаю с Пайтона его и собрали в .Net — хотя не уверен.
S>На самом деле на шарпе можно решать любые задачи с той же эффективностью. Учитываю, что большинство использует нетипизированный питон, то на шарпе используя
S>интеллисенс и прочие удобства IDE можно писать даже быстрее.
S> Это уже дело привычки

Ну давай рассмотрим простую задачу — задание пишу вообще от балды — не подстраивая под Пайтон: открыть файл с именами сотрудников и зарплатами, распарсить все строки и выдать имя наиболее высокооплачиваемого работника. Никакие сторонние библиотеки не используем, как и парсеры CSV — иначе это сравнение библиотек, а не языков. Пример файла:
Иванов, 1000
Петров, 2000
Сидоров, 3000

Для простоты считаем, что все строки содержат корректные записи — ошибки обрабатывать не надо.

На Пайтоне я решу задачу не задумываясь так (наверняка есть решения и еще более лаконичные):
employees = []

for line in open("D:\\test.txt", encoding="utf-8").readlines():
    items = line.split(",")
    employees.append((items[0], int(items[1])))

employees.sort(key=lambda i: i[1])
print("Employee with the biggest salary is: ", employees[-1][0])


Это полное решение — не нужны никакие import, не нужен проектный файл — это уже готовый к исполнению файл
На C# я буду вынужден нахреначить минимум втрое больше кода и еще и проект создать для этого:

using System;
using System.IO;    
using System.Collections.Generic;
using System.Text;

public class Program
{
    public static void Main()
    {
        var employes = new List<(string n, int s)>();

        foreach(var line in File.ReadAllLines("D:\test.txt", Encoding.UTF8))
        {
            var items = line.Split(',');
            employes.Add((items[0], Int32.Parse(items[1])));
        }
        
        employes.Sort((i, j) => i.s.CompareTo(j.s));
        Console.WriteLine("Employee with the biggest isalary is: " + employes[employes.Count - 1].n);
    }
}


Кроме кучи лишнего кода, связанного с уровнями доступами, декларациями классов, библиотеками, который мне для простого решения вообще не нужен, еще и сам основной код, получился несколько менее компактным и читабельным. В этом коде можно заметить 2 вещи, в которых Пайтон лучше шарпа. Это парсинг строки к int — в Пайтоне делается так: (int) str. Так же сортировки в Пайтоне поудобнее — не нужен компарер — можно задать ключ. Но это мелочи по сравнению с мусорным для простого проекта декларативным кодом.
Отредактировано 05.09.2021 11:52 vfedosov . Предыдущая версия . Еще …
Отредактировано 05.09.2021 11:42 vfedosov . Предыдущая версия .
Отредактировано 05.09.2021 11:31 vfedosov . Предыдущая версия .
Re[11]: MS забило на дотнет. Питону - да, сишарпу - нет?
От: rameel https://github.com/rsdn/CodeJam
Дата: 05.09.21 11:51
Оценка:
Здравствуйте, vfedosov, Вы писали:

V>Ну я попытался на своей VS2013 (более новые версии не доступны в нашей конторе) скомпилять следующий код:

V>ошибка: Error 1 Could not find an implementation of the query pattern for source type 'double[*,*]'. 'Select' not found. Are you missing a reference or a using directive for 'System.Linq'? c:\users\vfedosov\documents\visual studio 2013\Projects\ConsoleApplication2\ConsoleApplication2\Program.cs 30 34 ConsoleApplication2

Там ссылку указали: https://github.com/evilguest/linq2d

Почитай, а лучше видео глянь. Все там достойно и на уровне, генерируется нативный код с векторными инструкциями.
... << RSDN@Home 1.0.0 alpha 5 rev. 0>>
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.