johnfound
Създадено на 24.10.2020, видяно: 1762 пъти. #16754
Идеята е – имаме манипулатор на отворен файл. Функцията чете от текущото място във файла, до края на реда и връща прочетения ред. Файла остава позициониран на началото на следващия ред.
Четене байт-по-байт, разбира се не е решение. Трябва да се чете на по-големи парчета. Но това пък гарантира, че ще се прочете повече от нужното и после трябва да се връща файла назад...
Аз това и правя в момента, но по неизвестни причини това връщане назад в някои случаи е много по-бавно от четенето напред. Тоест, когато файла е голям, четенето на целият файл става много бавно.
Библиотечни варианти на "readln" не е алтернатива - желателно да се използват само функции от ниско ниво. (независимо от операционната система). Тях ги знам как работят – с допълнителен буфер, в който държат каквото са прочели, а файла не го местят назад. Но буфера трябва да се предава при всяко следващо викане.
Някаква идея как всичко това може да се забърза?
|
Създадено на 24.10.2020, видяно: 1754 пъти. #16757
Какво е това "връщане назад"? lseek? Каква е скоростта ако използваш pread, например?
slow_user
Създадено на 24.10.2020, видяно: 1750 пъти. #16758
Можеш да мапнеш файла в паметта, и да четеш докато стигнеш до \n символ - стринга ще ти е началото на указателя, до броя символи които си прочел, после местиш указателя след \n символа и повтаряш горната операция. Но вероятно определянето на code-page ако са ANSI файловете ще е мъка.
|
Създадено на 24.10.2020, видяно: 1742 пъти. #16759
Това при всички случаи влиза в дефиницията "използване на допълнителен буфер".
johnfound
Създадено на 24.10.2020, видяно: 1736 пъти. #16762
Примерно да, lseek със SEEK_CUR и отрицателен офсет.
Скоростта е в пъти по-бавна, отколкото ако банално чета целият файл при същият размер на буфера.
|
Създадено на 24.10.2020, видяно: 1734 пъти. #16763
Можеш да мапнеш файла в паметта, и да четеш докато стигнеш до \n символ - стринга ще ти е началото на указателя, до броя символи които си прочел, после местиш указателя след \n символа и повтаряш горната операция. Но вероятно определянето на code-page ако са ANSI файловете ще е мъка.
Това при всички случаи влиза в дефиницията "използване на допълнителен буфер".
Не и самото четене, ако трябва да правиш някакви конвертирания може. Но примерно ако файла е UTF-16 LE четенето е без буфер.
HANDLE hMapFile;
HANDLE hFile;
hFile = CreateFile(L"d:\\test.txt",
GENERIC_READ | GENERIC_WRITE,
0,
NULL,
OPEN_EXISTING,
FILE_ATTRIBUTE_NORMAL,
NULL);
if (hFile == INVALID_HANDLE_VALUE)
{
return 0;
}
// Get the system allocation granularity.
SYSTEM_INFO siInfo;
GetSystemInfo(&siInfo);
auto nGranularity = siInfo.dwAllocationGranularity;
LARGE_INTEGER dwFileSize;
if (!GetFileSizeEx(hFile, &dwFileSize))
{
CloseHandle(hFile);
return 0;
}
hMapFile = CreateFileMapping(hFile,
NULL,
PAGE_READWRITE,
dwFileSize.HighPart,
dwFileSize.LowPart,
NULL);
if (hMapFile == NULL)
{
return 0;
}
// Map the view and test the results.
wchar_t* lpMapAddress = (wchar_t*)MapViewOfFile(hMapFile,
FILE_MAP_ALL_ACCESS,
0,
0,
dwFileSize.LowPart);
if (lpMapAddress == NULL)
{
return 0;
}
std::vector<std::wstring> oaItems;
wchar_t* lpEndLinePtr = lpMapAddress;
wchar_t* lpEndPtr = &lpMapAddress[dwFileSize.LowPart];
while(lpEndLinePtr!=lpEndPtr)
{
if (*lpEndLinePtr++ == L'\n')
{
oaItems.push_back(std::wstring(lpMapAddress, lpEndLinePtr - lpMapAddress));
lpMapAddress = lpEndLinePtr;
}
}
oaItems.push_back(std::wstring(lpMapAddress, lpEndLinePtr - lpMapAddress));
UnmapViewOfFile(lpMapAddress);
CloseHandle(hMapFile);
CloseHandle(hFile); `
Абе, как да форматирам първия ред на кода, като го преместя на долния ред форматиран и тага за код не излиза
|
Създадено на 24.10.2020, видяно: 1727 пъти. #16765
Можеш да мапнеш файла в паметта, и да четеш докато стигнеш до \n символ - стринга ще ти е началото на указателя, до броя символи които си прочел, после местиш указателя след \n символа и повтаряш горната операция. Но вероятно определянето на code-page ако са ANSI файловете ще е мъка.
Това при всички случаи влиза в дефиницията "използване на допълнителен буфер".
Абе, как да форматирам първия ред на кода, като го преместя на долния ред форматиран и тага за код не излиза
Използвай правилните тагове за форматиране (пишат се от първата колона на текста):
;begin cpp
// your code here.
;end
С мапване в паметта не искам и вероятно ще стане още по-бавно – защото трябва да мапвам и размапвам на всяко викане на функцията.
|
Създадено на 24.10.2020, видяно: 1705 пъти. #16772
Според мен проблема е, че буфера ти е много по-голям от средната дължина на реда и изхвърляш повечето от прочетеното. Но трябва да ериш да провериш дали съм прав.
johnfound
Създадено на 24.10.2020, видяно: 1701 пъти. #16773
Според мен проблема е, че буфера ти е много по-голям от средната дължина на реда и изхвърляш повечето от прочетеното. Но трябва да ериш да провериш дали съм прав.
Хм, това е възможно. И тогава излиза, че бавенето е заради повторното четене (и евентуално лошо буфериране при някои от операционните системи)...
Но тъй като не може да се знае предварително каква ще е дължината на стринга, излиза, че винаги ще е зле - буфера ще е или прекалено малък, или прекалено голям...
|
Създадено на 24.10.2020, видяно: 1696 пъти. #16775
Според мен проблема е, че буфера ти е много по-голям от средната дължина на реда и изхвърляш повечето от прочетеното. Но трябва да ериш да провериш дали съм прав.
Хм, това е възможно. И тогава излиза, че бавенето е заради повторното четене (и евентуално лошо буфериране при някои от операционните системи)...
Но тъй като не може да се знае предварително каква ще е дължината на стринга, излиза, че винаги ще е зле - буфера ще е или прекалено малък, или прекалено голям...
Ами има две решения. По-лесното е спекулативно да четеш по-малко (например 40 байта) и аконямаш късмет да дочиташ.
Другия вариант е да смениш api-a и да дадешсобственността на буфера на функцията, която чете реда, а тя да връща указател към началото му. Така няма да ср налга четене на същите данни, може ни само memcpy.
bvbfan
Създадено на 25.10.2020, видяно: 1677 пъти. #16822
Това map-ване на файла не заема ли памет?
Не, това е mmap.
|
Създадено на 25.10.2020, видяно: 1658 пъти. #16844
Това map-ване на файла не заема ли памет?
Не, това е mmap.
mmp не заема ли памет? :)
bvbfan
Създадено на 25.10.2020, видяно: 1654 пъти. #16845
Виртуална, не реална.
|
Създадено на 25.10.2020, видяно: 1652 пъти. #16846
Виртуална, не реална.
Ох, пак започват идиотщините... Като започнеш да четеш mmap-нат файл, каква памет заема той?
bvbfan
Създадено на 25.10.2020, видяно: 1641 пъти. #16850
Файлът се мапва в паметта като виртуална такава, като swap. Нищо не се чете.
|
Създадено на 25.10.2020, видяно: 1639 пъти. #16851
Файлът се мапва в паметта като виртуална такава, като swap. Нищо не се чете.
И как знаеш какви са данните от файла? Някаква магия? :)
Като се опиташ да прочетеш първия байт от мапнатия файл какво се случва? :)
bvbfan
Създадено на 25.10.2020, видяно: 1633 пъти. #16852
Ти нямаш нищо общо с програмиране.
|
Създадено на 25.10.2020, видяно: 1631 пъти. #16853
Ти нямаш нищо общо с програмиране.
Виж сега, смешник, разбирам че нямаш никаква идея как работи mmap. Но аз съм писал няколко файлови системи за Линукс и поназнайвам това, онова. Освен това, макар че не съм експерт по memory management-a на Линукс, се оправям сравнително добре в кода (това дето е в linux/mm).
Ta, избягвай бълнуванията с какво имам общо и с какво не. :)
Та, да се върнем на въпроса, mmap-нал си файла, получил си адрес. Четеш първия байт от този адрес. Какво се случва? :)