const string со счетчиком ссылок
От: Коваленко Дмитрий Россия http://www.ibprovider.com
Дата: 28.02.20 05:53
Оценка:
В одной небольшой задачке потребовалось загрузить снаружи некий набор строк, а потом его мутузить разными способами.

VS2019.

Я сначала замутил её на базе std::wstring.

Программулина выжрала почти 4GB, что было на грани фола для 32-битного процесса.

Я на это дело посмотрел и вспомнил про свой велосипед — класс для константных строк с использованием счетчика ссылок.

Прикрутил этот класс к этой программе, реализовал создание новых экземпляров через словарь строк.

Программа стала жрать 600MB максимум.

---
В STL что-то подобное для константных строк есть?
-- Пользователи не приняли программу. Всех пришлось уничтожить. --
Отредактировано 28.02.2020 6:00 DDDX . Предыдущая версия .
Re: const string со счетчиком ссылок
От: Igore Россия  
Дата: 28.02.20 06:36
Оценка:
Здравствуйте, Коваленко Дмитрий, Вы писали:

КД>В одной небольшой задачке потребовалось загрузить снаружи некий набор строк, а потом его мутузить разными способами.


КД>Я на это дело посмотрел и вспомнил про свой велосипед — класс для константных строк с использованием счетчика ссылок.

КД>Прикрутил этот класс к этой программе, реализовал создание новых экземпляров через словарь строк.

КД>---

КД>В STL что-то подобное для константных строк есть?
string_view, может для твоего сценария и не подойдет
Re[2]: const string со счетчиком ссылок
От: Коваленко Дмитрий Россия http://www.ibprovider.com
Дата: 28.02.20 06:52
Оценка:
Здравствуйте, Igore, Вы писали:

I>Здравствуйте, Коваленко Дмитрий, Вы писали:


КД>>В одной небольшой задачке потребовалось загрузить снаружи некий набор строк, а потом его мутузить разными способами.


КД>>Я на это дело посмотрел и вспомнил про свой велосипед — класс для константных строк с использованием счетчика ссылок.

КД>>Прикрутил этот класс к этой программе, реализовал создание новых экземпляров через словарь строк.

КД>>---

КД>>В STL что-то подобное для константных строк есть?
I>string_view, может для твоего сценария и не подойдет

Не. Не то.

Тут строки создаются толпой, но потом они живут своей жизнью. Постепенно они изничтожаются.

Можно было, конечно, создать словарь std::wstring, потом его юзать указатели на его элементы. Но это не то.

Еще можно было в "shared_ptr" строки засунуть — но это два раза память выделяться будет (здесь я не уверен, не пробовал, только сейчас об этом подумал).

---
Хотелось нормальный read-only класс строки, которая при присваивании будет увеличивать счетчик ссылок у разделяемых данных.

Мой велосипед так и делает.

Но я уже устал от своих велосипедов
-- Пользователи не приняли программу. Всех пришлось уничтожить. --
Re[3]: const string со счетчиком ссылок
От: Chorkov Россия  
Дата: 28.02.20 07:33
Оценка:
Здравствуйте, Коваленко Дмитрий, Вы писали:

КД>Но я уже устал от своих велосипедов


А что за операции предполагается проволить со строками, кроме сравнения на равенство?
Re[3]: const string со счетчиком ссылок
От: XuMuK Россия  
Дата: 28.02.20 07:43
Оценка: +1
Здравствуйте, Коваленко Дмитрий, Вы писали:

КД>Еще можно было в "shared_ptr" строки засунуть — но это два раза память выделяться будет (здесь я не уверен, не пробовал, только сейчас об этом подумал).

КД>Хотелось нормальный read-only класс строки, которая при присваивании будет увеличивать счетчик ссылок у разделяемых данных.
shared_ptr<const std::string> как раз должен подойти, дополнительная память будет выделяться только под счетчики ссылок, а строки будут неизменяемые.
Re: const string со счетчиком ссылок
От: T4r4sB Россия  
Дата: 28.02.20 07:47
Оценка:
Здравствуйте, Коваленко Дмитрий, Вы писали:

КД>В одной небольшой задачке потребовалось загрузить снаружи некий набор строк, а потом его мутузить разными способами.


КД>VS2019.


КД>Я сначала замутил её на базе std::wstring.


КД>Программулина выжрала почти 4GB, что было на грани фола для 32-битного процесса.


А можно саму задачу? Мне кажется, у тебя ошибка в том, что ты для внутренних операций копировал строки, вместо перекидывания ссылок на них.

КД>Тут строки создаются толпой, но потом они живут своей жизнью. Постепенно они изничтожаются.


А это важно, что они уничтожаются постепенно, а не в конце все разом?
Re[4]: const string со счетчиком ссылок
От: Коваленко Дмитрий Россия http://www.ibprovider.com
Дата: 28.02.20 09:35
Оценка:
Здравствуйте, Chorkov, Вы писали:

КД>>Но я уже устал от своих велосипедов


C>А что за операции предполагается проволить со строками, кроме сравнения на равенство?


В этой конкретной задаче:

1. Сравнение. По факту, используется только оператор <. В словаре строк.
2. Получение самой строки, для формирования текстов запросов к базе.
-- Пользователи не приняли программу. Всех пришлось уничтожить. --
Re[2]: const string со счетчиком ссылок
От: Коваленко Дмитрий Россия http://www.ibprovider.com
Дата: 28.02.20 09:40
Оценка:
Здравствуйте, T4r4sB, Вы писали:

КД>>В одной небольшой задачке потребовалось загрузить снаружи некий набор строк, а потом его мутузить разными способами.


КД>>VS2019.


КД>>Я сначала замутил её на базе std::wstring.


КД>>Программулина выжрала почти 4GB, что было на грани фола для 32-битного процесса.


TB>А можно саму задачу? Мне кажется, у тебя ошибка в том, что ты для внутренних операций копировал строки, вместо перекидывания ссылок на них.


Это часть тестовой системы.

Сначала формируются тестовые данные, которые потом рассовываются по (параллельно выполняемым) подзадачам.

КД>>Тут строки создаются толпой, но потом они живут своей жизнью. Постепенно они изничтожаются.


TB>А это важно, что они уничтожаются постепенно, а не в конце все разом?


По мере того как подзадачи отрабатывают, память освобождается.

Этих подзадач ~10тыщ.

А общая толпа, в рамках которой они работают — за 700 тысяч.

Удерживать словарь до завершения работы последней подзадачи не очень разумно. Особенно на 32х битах.
-- Пользователи не приняли программу. Всех пришлось уничтожить. --
Re[3]: const string со счетчиком ссылок
От: T4r4sB Россия  
Дата: 28.02.20 09:44
Оценка:
Здравствуйте, Коваленко Дмитрий, Вы писали:

КД>Сначала формируются тестовые данные, которые потом рассовываются по (параллельно выполняемым) подзадачам.


Всё равно не вижу причин рассылать копии строк, а не ссылки на них.

КД>Удерживать словарь до завершения работы последней подзадачи не очень разумно. Особенно на 32х битах.


Почему?
Re[4]: const string со счетчиком ссылок
От: Коваленко Дмитрий Россия http://www.ibprovider.com
Дата: 28.02.20 09:46
Оценка:
Здравствуйте, XuMuK, Вы писали:

КД>>Еще можно было в "shared_ptr" строки засунуть — но это два раза память выделяться будет (здесь я не уверен, не пробовал, только сейчас об этом подумал).

КД>>Хотелось нормальный read-only класс строки, которая при присваивании будет увеличивать счетчик ссылок у разделяемых данных.
XMK>shared_ptr<const std::string> как раз должен подойти, дополнительная память будет выделяться только под счетчики ссылок, а строки будут неизменяемые.

Да, я тоже про это подумал. Но — вот это вот дополнительное выделение памяти напрягает.

В моем случае счетчик хранится в блоке с самими данными.

Я этот shared_ptr поэтому и не люблю. Даже кушать не могу. То есть нигде не использую.

----
Вообще этот мой велосипед (const_string) относительно хорошо продуман, поскольку он может представлять как строки из динамической памяти, так и статические строки

----
А вместо string_view у меня юзается другой велосипед — const_str_box.

Кривоватые, конечно. Но .... делать
-- Пользователи не приняли программу. Всех пришлось уничтожить. --
Re[5]: const string со счетчиком ссылок
От: Chorkov Россия  
Дата: 28.02.20 09:58
Оценка:
Здравствуйте, Коваленко Дмитрий, Вы писали:

КД>Здравствуйте, Chorkov, Вы писали:


КД>>>Но я уже устал от своих велосипедов


C>>А что за операции предполагается проволить со строками, кроме сравнения на равенство?


КД>В этой конкретной задаче:


КД>1. Сравнение. По факту, используется только оператор <. В словаре строк.

КД>2. Получение самой строки, для формирования текстов запросов к базе.

Надеюсь запросы на поиск полного совпадения строк, а не подстроки в строке?
Тогда, стоит поменять структуру базы: дабавит таблицу уникальных идентификаторов, и далее пользоваться только их номерами (ссылками на эту таблицу).
На стороне C++ строк вообще не будет.
Re: const string со счетчиком ссылок
От: Stanislav V. Zudin Россия  
Дата: 28.02.20 10:03
Оценка:
Здравствуйте, Коваленко Дмитрий, Вы писали:

КД>В одной небольшой задачке потребовалось загрузить снаружи некий набор строк, а потом его мутузить разными способами.

КД>Программа стала жрать 600MB максимум.

КД>В STL что-то подобное для константных строк есть?


Гм, а сколько всего строк и какой их размер?
Может не стоит связываться с СТЛ?
Для таких сценариев хорошо работает переход от отдельных строк к объекту "коллекция строк". Все строки лежат в одном блоке памяти.
Доступ к строке — по индексу.
Хочешь — возвращай указатель на 0-terminated строку, хочешь — самописный аналог string_view (обертка над парой указателей или указатель+длина).
Еще в ДОСовские времена использовали такую штуку.

Удаление из коллекции в этом случае не очень эффективно, но может оно и не нужно? На выходе разом всю память освободишь.
_____________________
С уважением,
Stanislav V. Zudin
Re: const string со счетчиком ссылок
От: EreTIk EreTIk's Box
Дата: 28.02.20 10:17
Оценка:
Здравствуйте, Коваленко Дмитрий, Вы писали:

КД>VS2019.


КД>Прикрутил этот класс к этой программе, реализовал создание новых экземпляров через словарь строк.


КД>В STL что-то подобное для константных строк есть?


Может из ATL подойдет?

#include <atlstr.h>

int main()
{
    ATL::CStringW str1{ L"abcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabc" };
    ATL::CStringW str2{ str1 };
}


Внутри конструктора str2:
0:000:x86> k4
 # ChildEBP RetAddr  
00 010ffab4 004a1fac Playground!ATL::CSimpleStringT<wchar_t,0>::CloneData+0x62 [C:\Program Files (x86)\Microsoft Visual Studio\2019\Community\VC\Tools\MSVC\14.24.28314\atlmfc\include\atlsimpstr.h @ 886] 
01 010ffacc 004a20d4 Playground!ATL::CSimpleStringT<wchar_t,0>::CSimpleStringT<wchar_t,0>+0x3c [C:\Program Files (x86)\Microsoft Visual Studio\2019\Community\VC\Tools\MSVC\14.24.28314\atlmfc\include\atlsimpstr.h @ 213] 
02 010ffadc 004a1843 Playground!ATL::CStringT<wchar_t,ATL::StrTraitATL<wchar_t,ATL::ChTraitsCRT<wchar_t> > >::CStringT<wchar_t,ATL::StrTraitATL<wchar_t,ATL::ChTraitsCRT<wchar_t> > >+0x24 [C:\Program Files (x86)\Microsoft Visual Studio\2019\Community\VC\Tools\MSVC\14.24.28314\atlmfc\include\cstringt.h @ 1029] 
03 010ffb14 004a7623 Playground!main+0x93 [d:\Projects\Playground\Playground.cpp @ 13]

0:000:x86> lsa @eip
   882:         IAtlStringMgr* pNewStringMgr = pData->pStringMgr->Clone();
   883:         if( !pData->IsLocked() && (pNewStringMgr == pData->pStringMgr) )
   884:         {
   885:             pNewData = pData;
>  886:             pNewData->AddRef();
   887:         }
   888:         else
   889:         {
   890:             pNewData = pNewStringMgr->Allocate( pData->nDataLength, sizeof( XCHAR ) );
   891:             if( pNewData == NULL )
Re[2]: const string со счетчиком ссылок
От: Коваленко Дмитрий Россия http://www.ibprovider.com
Дата: 28.02.20 10:19
Оценка:
Здравствуйте, Stanislav V. Zudin, Вы писали:

SVZ>Гм, а сколько всего строк и какой их размер?


Я их не считал — много наверное.

SVZ>Может не стоит связываться с СТЛ?

SVZ>Для таких сценариев хорошо работает переход от отдельных строк к объекту "коллекция строк". Все строки лежат в одном блоке памяти.
SVZ>Доступ к строке — по индексу.
SVZ>Хочешь — возвращай указатель на 0-terminated строку, хочешь — самописный аналог string_view (обертка над парой указателей или указатель+длина).
SVZ>Еще в ДОСовские времена использовали такую штуку.

SVZ>Удаление из коллекции в этом случае не очень эффективно, но может оно и не нужно? На выходе разом всю память освободишь.


Словарь строк формируется в процессе формирования подзадач. И эти подзадачи сразу уезжают на выполнение.

Когда все подзадачи сформированы, словарь грохается.

Но строки остаются — в тех подзадачах которые выполняются или еще не были выполнены.

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

Подзадачи про словарь вообще ничего не знают. Им дали наборы строк, они с ними и работают.

-----------------
В Борландовская STL была std::string со счетчиком ссылок.

А в студии — каждая std::string хранит копию данных.

В этом и печаль.

Мне так кажется, что в STL нужна (константная) строка со счетчиком ссылок. Хотя, с другой стороны, вроде как std::shared_ptr<const string> проблему решает.
-- Пользователи не приняли программу. Всех пришлось уничтожить. --
Re[2]: const string со счетчиком ссылок
От: Коваленко Дмитрий Россия http://www.ibprovider.com
Дата: 28.02.20 10:26
Оценка:
Здравствуйте, EreTIk, Вы писали:

КД>>Прикрутил этот класс к этой программе, реализовал создание новых экземпляров через словарь строк.


КД>>В STL что-то подобное для константных строк есть?


ETI>Может из ATL подойдет?


То есть в STL такого нет

Стороннее мне не надо.
-- Пользователи не приняли программу. Всех пришлось уничтожить. --
Re[3]: const string со счетчиком ссылок
От: Stanislav V. Zudin Россия  
Дата: 28.02.20 10:27
Оценка:
Здравствуйте, Коваленко Дмитрий, Вы писали:


КД>Словарь строк формируется в процессе формирования подзадач. И эти подзадачи сразу уезжают на выполнение.

КД>Когда все подзадачи сформированы, словарь грохается.
КД>Но строки остаются — в тех подзадачах которые выполняются или еще не были выполнены.

Между подзадачами много дубликатов?
Если так, то шаред поинтер нормальное решение.


КД>В Борландовская STL была std::string со счетчиком ссылок.

КД>А в студии — каждая std::string хранит копию данных.

Стандарт-с, однако.

КД>Мне так кажется, что в STL нужна (константная) строка со счетчиком ссылок.


Красиво, как в Яве, всё равно не получится. Для этого GC нужен.
_____________________
С уважением,
Stanislav V. Zudin
Re[4]: const string со счетчиком ссылок
От: T4r4sB Россия  
Дата: 28.02.20 10:33
Оценка:
Здравствуйте, Stanislav V. Zudin, Вы писали:

SVZ>Красиво, как в Яве, всё равно не получится. Для этого GC нужен.


Чтоб было "как в GC", надо просто все строки хранить в одном месте а потом грохать разом на выходе.
Re[4]: const string со счетчиком ссылок
От: Коваленко Дмитрий Россия http://www.ibprovider.com
Дата: 28.02.20 10:43
Оценка:
Здравствуйте, Stanislav V. Zudin, Вы писали:

КД>>Словарь строк формируется в процессе формирования подзадач. И эти подзадачи сразу уезжают на выполнение.

КД>>Когда все подзадачи сформированы, словарь грохается.
КД>>Но строки остаются — в тех подзадачах которые выполняются или еще не были выполнены.

SVZ>Между подзадачами много дубликатов?


Как минимум есть x3. Тестируются строки в прямом порядке, в обратном порядку и random

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

SVZ>Если так, то шаред поинтер нормальное решение.


+1 один блок под счетчик...

SVZ>Красиво, как в Яве, всё равно не получится. Для этого GC нужен.


С явой не работал. Но, в свете всей это ..., понял почему в C# строки константные
-- Пользователи не приняли программу. Всех пришлось уничтожить. --
Re[5]: const string со счетчиком ссылок
От: Stanislav V. Zudin Россия  
Дата: 28.02.20 10:44
Оценка:
Здравствуйте, T4r4sB, Вы писали:

SVZ>>Красиво, как в Яве, всё равно не получится. Для этого GC нужен.


TB>Чтоб было "как в GC", надо просто все строки хранить в одном месте а потом грохать разом на выходе.


Не, я немного про другое.
Атомарность присваивания ссылок в Яве позволяет очень здорово работать с иммутабельными объектами (теми же строками).
На многопоточных задачах можно не заморачиваться синхронизацией — если потребовалось модифицировать объекто, то тупо заменяем старый объект новым. GC потом приберет освободившихся.

Чтобы такое замутить на плюсах приходится городить шаред поинтер, подсчет ссылок.

А "грохать разом на выходе" я предложил, но Дмитрий не хочет
_____________________
С уважением,
Stanislav V. Zudin
Re[3]: const string со счетчиком ссылок
От: Igore Россия  
Дата: 28.02.20 10:47
Оценка:
Здравствуйте, Коваленко Дмитрий, Вы писали:

КД>Тут строки создаются толпой, но потом они живут своей жизнью. Постепенно они изничтожаются.


КД>Можно было, конечно, создать словарь std::wstring, потом его юзать указатели на его элементы. Но это не то.


КД>Еще можно было в "shared_ptr" строки засунуть — но это два раза память выделяться будет (здесь я не уверен, не пробовал, только сейчас об этом подумал).


КД>---

КД>Хотелось нормальный read-only класс строки, которая при присваивании будет увеличивать счетчик ссылок у разделяемых данных.

КД>Мой велосипед так и делает.


КД>Но я уже устал от своих велосипедов

Ну, можно еще старый gcc взять до С++11, где строки с cow реализованы
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.