
Pasiuna
Adunay usa ka yano ug mapuslanon kaayo nga gamit sa kalibutan - , ug kini nahitabo nga kini nakagamot sa among proseso sa produksiyon sa dugay nga panahon (bisan kung dili posible nga i-install ang bersyon niini, apan siguradong dili kini ang katapusan nga magamit). Gigamit namo kini alang sa gituyo nga katuyoan niini - pagtukod og binary patches. Kung imong tan-awon kung unsa ang naa sa repository, kini mahimong usa ka gamay nga kasubo: sa tinuud, gibiyaan kini sa dugay na nga panahon ug kadaghanan niini karaan na kaayo (ang akong kanhing kauban kaniadto naghimo og daghang mga pag-edit didto, apan kana dugay na ang milabay) . Sa kinatibuk-an, nakahukom ko nga banhawon kini nga butang: Gibiyaan nako, gilabay ang wala nako plano nga gamiton, gibalhin ang proyekto sa , inlined nga "mainit" nga mga microfunction, gikuha ang dagkong mga arrays gikan sa stack (ug mga arrays sa variable nga gitas-on, nga prangka nga naghimo kanako nga "bomba"), midagan pag-usab sa profiler - ug nahibal-an nga mga 40% sa oras nga gigugol sa ...
Busa unsa ang naa sa fwrite?
Sa kini nga code, fwrite (sa akong espesipikong kaso sa pagsulay: pagtukod og usa ka patch tali sa duol nga 300 MB nga mga file, ang input data hingpit nga naa sa panumduman) gitawag nga minilyon ka beses nga adunay gamay nga buffer size. Dayag nga kini nga butang mohinay, ug busa gusto nako nga maimpluwensyahan kini nga kaulaw. Wala pa'y tinguha nga ipatuman ang nagkalain-laing matang sa mga tinubdan sa datos, asynchronous input-output, gusto ko nga mangita og mas simple nga solusyon. Ang una nga butang nga nahunahunaan mao ang pagdugang sa gidak-on sa buffer
setvbuf(file, nullptr, _IOFBF, 64* 1024)apan wala ako nakakuha usa ka hinungdanon nga pag-uswag sa resulta (karon fwrite giisip alang sa mga 37% sa oras) - nga nagpasabut nga dili gihapon kini usa ka butang nga kanunay nga pagsulat sa datos sa disk. Sa pagtan-aw "sa ilawom sa hood" sa fwrite, imong makita nga ang usa ka lock / unlock FILE nga istruktura nahitabo sa sulod sa usa ka butang nga sama niini (pseudo-code, ang tanan nga pag-analisar gihimo sa ilawom sa Visual Studio 2017):
size_t fwrite (const void *buffer, size_t size, size_t count, FILE *stream)
{
size_t retval = 0;
_lock_str(stream); /* lock stream */
__try
{
retval = _fwrite_nolock(buffer, size, count, stream);
}
__finally
{
_unlock_str(stream); /* unlock stream */
}
return retval;
}
Sumala sa profiler, ang _fwrite_nolock nagkantidad lamang sa 6% sa panahon, ang nahabilin kay sa ibabaw. Sa akong partikular nga kaso, ang kaluwasan sa thread klaro nga sobra, mao nga akong isakripisyo kini pinaagi sa pag-ilis sa fwrite nga tawag sa - Dili nimo kinahanglan nga mahimong maalamon sa mga argumento. Kinatibuk-an: kini nga yano nga pagmaniobra hinungdanon nga nakunhuran ang gasto sa pagrekord sa resulta, nga sa orihinal nga bersyon mikabat sa hapit katunga sa oras nga gigugol. Pinaagi sa dalan, sa kalibutan sa POSIX adunay parehas nga function - . Sa kinatibuk-an, ang parehas nga magamit sa fread. Sa ingon, gamit ang usa ka pares nga #defines, mahimo ka makakuha usa ka hingpit nga cross-platform nga solusyon nga wala’y kinahanglan nga mga kandado kung dili kini kinahanglan (ug kini kanunay nga mahitabo).
fwrite, _fwrite_nolock, setvbuf
Mobiya na ta sa orihinal nga proyekto ug mag-focus sa pagsulay sa usa ka piho nga kaso: pagsulat og dako nga file (512 MB) sa gagmay kaayong mga tipak—usa ka byte matag usa. Sistema sa pagsulay: AMD Ryzen 7 1700, 16 GB RAM, 7200 rpm HDD, 64 MB cache. Windows 10 1809, ang binary gitukod isip 32-bit, ang mga pag-optimize gipagana, ang librarya static nga nalambigit.
Sample alang sa eksperimento:
#include <chrono>
#include <cstdio>
#include <inttypes.h>
#include <memory>
#ifdef _MSC_VER
#define fwrite_unlocked _fwrite_nolock
#endif
using namespace std::chrono;
int main()
{
std::unique_ptr<FILE, int(*)(FILE*)> file(fopen("test.bin", "wb"), fclose);
if (!file)
return 1;
constexpr size_t TEST_BUFFER_SIZE = 256 * 1024;
if (setvbuf(file.get(), nullptr, _IOFBF, TEST_BUFFER_SIZE) != 0)
return 2;
auto start = steady_clock::now();
const uint8_t b = 77;
constexpr size_t TEST_FILE_SIZE = 512 * 1024 * 1024;
for (size_t i = 0; i < TEST_FILE_SIZE; ++i)
fwrite_unlocked(&b, 1, sizeof(b), file.get());
auto end = steady_clock::now();
auto interval = duration_cast<microseconds>(end - start);
printf("Time: %lldn", interval.count());
return 0;
}
Ang mga variable mahimong TEST_BUFFER_SIZE, ug alang sa usa ka magtiayon nga mga kaso atong pulihan ang fwrite_unlocked sa fwrite. Magsugod ta sa fwrite nga kaso nga walay klarong pagbutang sa buffer size (comment out setvbuf ug ang kaubang code): time 27048906 µs, write speed - 18.93 MB/s. Karon atong ibutang ang buffer size sa 64 KB: oras - 25037111 μs, speed - 20.44 Mb/s. Karon atong sulayan ang operasyon sa _fwrite_nolock nga walay pagtawag sa setvbuf: 7262221 µs, speed - 70.5 Mb/s!
Sunod, mag-eksperimento kita sa gidak-on sa buffer (setvbuf):

Ang datos nakuha pinaagi sa pag-average sa 5 nga mga eksperimento; Tapolan kaayo ako sa pagkalkulo sa mga sayup. Alang kanako, ang 93 MB / s kung ang pagsulat sa 1 byte sa usa ka regular nga HDD usa ka maayo kaayo nga sangputanan, kinahanglan nimo nga pilion ang kamalaumon nga gidak-on sa buffer (sa akong kaso, ang 256 KB tama ra) ug ilisan ang fwrite sa _fwrite_nolock/fwrite_unlocked ( sa kaso kung dili kinahanglan ang kaluwasan sa hilo, siyempre).
Ingon usab sa fread sa parehas nga kahimtang. Tungod kay wala koy hardware nga makina nga adunay Linux (dili maihap ang single-board nga mga kompyuter), nakahukom ko nga magpahigayon og limitado nga eksperimento sa usa ka virtual machine (Hyper-V, OpenSUSE 15, GCC 8.3.1) - ang Ang sumbanan, sa prinsipyo, parehas: "hubo" fwrite 20 Mb/s, fwrite + 256 KB buffer naghimo og 23 Mb/s, fwrite_unlocked nga adunay parehas nga buffer - 35 Mb/s (64-bit binary, assembled g++ -o2 - s -static-libgcc -static-libstdc++ fwrite_test. cpp -o fwrite_test).
Pagkahuman
Ang katuyoan sa pagsulat niini nga artikulo mao ang paghubit sa usa ka yano ug epektibo nga pamaagi sa daghang mga kaso (wala pa gyud nako makit-an ang _fwrite_nolock/fwrite_unlocked nga mga gimbuhaton kaniadto, kini dili kaayo popular - apan kawang). Wala ako magpakaaron-ingnon nga ang materyal bag-o, apan nanghinaut ko nga ang artikulo mahimong mapuslanon sa komunidad.
Source: www.habr.com
