Ответы пользователя по тегу C#
  • Как ускорить поиск элементов из статичного string[] по подстроке?

    VoidVolker
    @VoidVolker Куратор тега C#
    Dark side eye. А у нас печеньки! А у вас?
    Раз нет ограничений по памяти и надо максимально быстро, то можно разложить весь массив в дерево таблиц переходов с шагом в один символ на таблицу. Самый быстрый и самый затратный по памяти. Таблица на каждый символ - 256 байт. Скорость поиска зависит только от размера строки и не зависит от объема данных: один символ - один переход в таблице к следующей таблице или конец поиска, если ноль. Я так уже делал: использовать имеет смысл на объемах примерно от 4 гигабайт данных (чем больше объем - тем меньше затраты на каждый символ). Но, если память позволяет и цель именно в скорости - то вполне нормальная плата памятью за скорость. Можно сократить расход памяти, если перекодировать строки в кодировку по числу используемых символов. Тогда таблица переходов будет в несколько раз меньше. Более экономный и более медленный вариант - дерево массивов/списков с шагом в 2/4/8 символов, при этом в поиске сравнение не по символам делать, а сразу по 2/4/8 байт: т.е., работаем со строкой как с массивом байтов и получаем оттуда uint16/uint32/uint64 и их и сравниваем, ибо процессору все равно какую инструкцию выполнять - один байт сравнить или 8. Возможно, конечно, оптимизатор в поиске по строке это все и оптимизирует. Я давно уже не смотрю на результаты его работы - так что тут только опытным путем. Ну и щас еще других вариантов накидают с деревьями тоже.

    UPD1:
    Можно все несколько упростить (или усложнить - смотря с какой стороны смотреть), если перекодировать строки из стандартной кодировки во что-то более компактное либо самостоятельно сделать кодировку под набор данных.

    Еще можно ускорить, если искать в несколько потоков, разбив весь набор данных на несколько групп.

    UPD2:
    Таки нашел немного времени и откопал исходники для шарпа и провел несколько тестов по расходу памяти.

    Число строк / общий размер данных / итоговый размер дерева

    5 символов:
    1000000 / 55.9MB / 13.2GB
    2000000 / 111.6MB / 25.2GB

    10 символов:
    100000 / 8.1MB / 4.1GB
    200000 / 16.1MB / 8GB
    300000 / 24.2MB / 11.9GB
    400000 / 32.2MB / 15.7GB
    500000 / 40.3MB / 19.5GB

    15 символов:
    100000 / 10.5MB / 6.6GB
    200000 / 21MB / 13.1GB
    300000 / 31.5MB / 19.5GB
    400000 / 42MB / 25.8GB

    20 символов:
    100000 / 13MB / 9.1GB
    200000 / 25.9MB / 18.1GB
    300000 / 38.9MB / 27GB


    Максимальный размер дерева для глубины в 5 символов на платформе х64:
    • Для диапазона 0-255 - до 8Тб и до 4 311 810 305 узлов
    • Для диапазона 0-70 - до 13.5Гб и до 24 357 971 узлов

    Максимальный размер дерева для глубины в 4 символа для диапазона 0-255: ~17Гб и ~33Гб для х86 и для х64 соответственно и лимит в 16 843 009 узлов. Ну и в коде есть функция для вычисления максимального числа узлов и размера дерева.

    Как видно по результатам - чем выше объем и короче строки, т.е., плотность, тем выше эффективность размещения на единицу памяти. Скорость поиска в таком дереве зависит лишь от числа символов в слове/строке и всегда константа независимо от объема. ТС имеет смысл оптимизировать алгоритм под свои данные, если там обычный текст - то вероятно имеет смысл сделать индекс слов, подобрать компактную кодировку, а далее уже список строк с этим словом. Т.е., сначала идет поиск в дереве по слову, а далее уже по списку строк. И можно будет хоть в гигабайтах искать мгновенно, но памяти там надо будет уже терабайты.

    И соответственно код: https://github.com/VoidVolker/search-tree/tree/master (предупреждаю сразу: код старый, по сути экспериментальный, не вылизанный и вероятно приведет кого-то в ужас). Но, главное, что работает.
    код

    Тестовый код:
    static Random rnd = new Random();
    static string[] GenStrings(int cnt, int strLen)
    {
        string[] arr = new string[cnt];
        var i = 0;
        while (i < cnt)
        {
            var sb = new StringBuilder();
            for (var j = 0; j < strLen; j++)
            {
                sb.Append(rnd.Next(0, 256));
                //sb.Append(TAbc[rnd.Next(0, TAbc.Length)]);
            }
            arr[i++] = sb.ToString();
        }
        return arr;
    }
    
    var arraySize = 300000;
    var stringSize = 20;
    
    var GCStartArr = GC.GetTotalMemory(true);
    
    var strings = GenStrings(arraySize, stringSize);
    
    var GCEndArr = GC.GetTotalMemory(true);
    var GCStart = GC.GetTotalMemory(true);
    
    var tree = new ArrayTree<string>();
    foreach (string s in strings)
    {
        tree.Add(Encoding.UTF8.GetBytes(s), s);
    }
    
    var GCEnd = GC.GetTotalMemory(true);
    
    Console.WriteLine("Array x string size / Array memory used / Tree memory used");
    Console.WriteLine($"{arraySize} х {stringSize} / {BytesToString(GCEndArr - GCStartArr)} / {BytesToString(GCEnd - GCStart)}");
    Ответ написан
  • Как лучше сохранять результаты логирования приложения NET?

    VoidVolker
    @VoidVolker Куратор тега C#
    Dark side eye. А у нас печеньки! А у вас?
    Добавлю, что есть еще такая замечательная штука, как "сборщик логов" - то, что надо, если хочется собирать логи с нескольких разных источников. Например FluentD, Graylog, Nagios Log Server, NXlog, Elastic Stack: Elasticsearch, Kibana, Beats & Logstash, LOGalyze.
    Ответ написан
    1 комментарий
  • Как практиковаться в программировании?

    VoidVolker
    @VoidVolker Куратор тега C#
    Dark side eye. А у нас печеньки! А у вас?
    Решать реальные задачи. Написание кода - это всего лишь небольшая часть в разработке ПО. Язык программирования - это инструмент. Рекомендую присмотреться к готовым схемам изучения ЯП. Например: https://roadmap.sh/ А так же пробовать не только решать разные задачи, но и разные ЯП и разными способами. Так же имеет смысл присмотреться к играм с мощными редакторами и системами модификации: создать свой квест/карту/игру очень даже неплохо мотивирует делать что-то большее. Ну и, конечно же, учиться, учиться и учиться. Причем еще и учиться учиться. И обязательно учить английский и математику. IT меняется и развивается очень быстро и без навыков и способностей к самостоятельному обучению тут очень быстро можно оказаться за бортом и уйти на дно как топор.
    Ответ написан
    Комментировать
  • Как передать данные в exe файл на C# при загрузке?

    VoidVolker
    @VoidVolker Куратор тега C#
    Dark side eye. А у нас печеньки! А у вас?
    Проще всего просто дописать строку в конец самого exe файла, а в последнем байте - её длину. И при запуске приложения прочитать последний байт exe и далее вычислив начало и конец строки прочитать конец файла как строку. Чуть более сложный вариант в случае если надо пересобирать дистрибутив или добавить в него параметры какие-то: NSIS отлично работает под линуксом - так что можно ему передавать любые свои аргументы и делать сборку дистрибутива на лету.
    Ответ написан
  • Как десериализовать массивы JSON в C#?

    VoidVolker
    @VoidVolker Куратор тега C#
    Dark side eye. А у нас печеньки! А у вас?
    Комментировать
  • Как собрать проект с WebView2 в 1 exe файл?

    VoidVolker
    @VoidVolker Куратор тега C#
    Dark side eye. А у нас печеньки! А у вас?
    Самый простой вариант: Enigma Virtual Box. Кроме того, если надо просто браузер, который показывает какой-то сайт, то есть еще такая замечательная штука, как NWJS.
    Ответ написан
    Комментировать
  • Как сделать маркированный список в wpf?

    VoidVolker
    @VoidVolker Куратор тега C#
    Dark side eye. А у нас печеньки! А у вас?
    Значит плохо гуглили - надо учиться. Ловите символ: . Либо добавляете в шаблон элемента списка в виде текстового элемента либо вообще в текст самих элементов списка.
    Ответ написан
  • Как создать фабрику картинок в windorms c#?

    VoidVolker
    @VoidVolker Куратор тега C#
    Dark side eye. А у нас печеньки! А у вас?
    Есть такая штука, называется "Декомпозиция задачи": вот это вам и надо сделать. Разбить свою задачу на несколько подзадач меньшего размера, а потом эти задачи разбить на подзадачи еще меньше и так далее, пока не станет все понятно. Затем следует объединить задачи в какие-то модули и логические блоки. И по шагам реализовывать нужный функционал. (И в очередной раз напоминаю, как вам уже неоднократно сказали: в вашем случае следует сделать карту игрового поля и основываясь на этой карте рисовать игровое поле - вы её сделали?)
    Ответ написан
    Комментировать
  • Как отформатировать текст для отправки по REST API WORDPRESS?

    VoidVolker
    @VoidVolker Куратор тега JavaScript
    Dark side eye. А у нас печеньки! А у вас?
    Ответ написан
    Комментировать
  • Можно ли просто передать exe или передать папку Release wiforms c#?

    VoidVolker
    @VoidVolker Куратор тега C#
    Dark side eye. А у нас печеньки! А у вас?
    Можно один исполняемый файл при условии отсутствия дополнительных зависимостей. Обычно студия зависимости кладет рядом в тот же каталог (release/debug), но в некоторых случаях не все зависимости копируются и тогда их надо ручками добавлять в конфиги. Для распространения приложения используется такая штука, как "дистрибутив" или установщик: все требуемые файлы упаковываются в один исполняемый и далее один этот файл распространяется. При запуске установщик распаковывает все файлы в указанный в его конфиге каталог и делает разные дополнительные действия типа создания ярлыков и прочее.
    Ответ написан
  • Почему выходит ошибка при передаче пользователю программу winforms?

    VoidVolker
    @VoidVolker Куратор тега C#
    Dark side eye. А у нас печеньки! А у вас?
    Конечно надо. Все используемые медиа файлы надо либо упаковывать в ресурсы либо вместе с приложением передавать в отдельном каталоге, например.
    Ответ написан
    Комментировать
  • Как сделать вызов функции при изменении значения переменной типа enum c# winform?

    VoidVolker
    @VoidVolker Куратор тега C#
    Dark side eye. А у нас печеньки! А у вас?
    Например использовать свойства:
    class Foo {
        private BarEnum _bar;
        public BarEnum bar {
            get { ... }
            set { ... }
        }
    }

    И, соответственно при изменении значения переменной во время записи выполнить нужный код. Можно даже использовать события.
    Ответ написан
    Комментировать
  • Как изменить интерфейс программы при нажатии на кнопку winforms c#?

    VoidVolker
    @VoidVolker Куратор тега C#
    Dark side eye. А у нас печеньки! А у вас?
    Да, для этого потребуются всего три функции: создать элемент управления, удалить элемент управления и добавить элемент управления.
    Ответ написан
    Комментировать
  • Как правильно десериализовать JSON в объект класса C#?

    VoidVolker
    @VoidVolker Куратор тега C#
    Dark side eye. А у нас печеньки! А у вас?
  • Передача функциям в виде объектов класса?

    VoidVolker
    @VoidVolker Куратор тега C#
    Dark side eye. А у нас печеньки! А у вас?
    Потому что эти функции делают разные вещи. Первая - меняет местами свойства разных объектов, в то время как вторая меняет местами значения локальных переменных.
    Ответ написан
    2 комментария
  • Норм ли использовать MSTest для создания юнит-тестов под .NET-проект (см. внутри)?

    VoidVolker
    @VoidVolker Куратор тега C#
    Dark side eye. А у нас печеньки! А у вас?
    Если функционал устраивает и все работает - то почему нет-то? Нравится - используй, не нравится - не используй. Все просто.
    Ответ написан
  • Как получить текст из автоматически сгенерированных TextBox-ов?

    VoidVolker
    @VoidVolker Куратор тега C#
    Dark side eye. А у нас печеньки! А у вас?
    Документация -> Learn / .NET / Обозреватель API / System.Windows.Controls / Grid -> Свойства -> Children: https://learn.microsoft.com/ru-ru/dotnet/api/syste...
    Ответ написан
    4 комментария
  • Как взаимодействовать с данными из другого проекта WPF?

    VoidVolker
    @VoidVolker Куратор тега C#
    Dark side eye. А у нас печеньки! А у вас?
    Выносите все общие части в отдельный проект и подключаете его как внешнюю зависимость в нужные проекты/решения.
    Ответ написан
    Комментировать
  • Как сделать ввод нескольких переменных ReadLine в одну строку?

    VoidVolker
    @VoidVolker Куратор тега C#
    Dark side eye. А у нас печеньки! А у вас?
    1. Получить строку
    2. Разбить строку либо по разделителю - если пробел используется, либо по знаку в строке
    3. Из полученного массива взять нужные значения
    4. Распарсить значения
    Ответ написан
    Комментировать
  • Как сделать из локального чата публичный?

    VoidVolker
    @VoidVolker Куратор тега C#
    Dark side eye. А у нас печеньки! А у вас?
    Вам следует описать конкретно, что именно у вас не получается. В целом ваша задача состоит из следующих подзадач:
    1. Арендовать сервер
    2. Арендовать домен
    3. Подключить сервер к домену
    4. Сделать дополнительные настройки на сервере в соответствии с требованиями вашего приложения
    5. Разместить приложение на сервере
    6. Запустить приложение
    Ответ написан
    8 комментариев