ํž˜๋“ค์ด์ง€ ์•Š๊ณ  C/C++ ํŒŒ์ผ I/O ๊ฐ€์†ํ™”

ํž˜๋“ค์ด์ง€ ์•Š๊ณ  C/C++ ํŒŒ์ผ I/O ๊ฐ€์†ํ™”

๋จธ๋ฆฌ๋ง

์„ธ์ƒ์—๋Š” ์ด๋ ‡๊ฒŒ ๊ฐ„๋‹จํ•˜๊ณ  ๋งค์šฐ ์œ ์šฉํ•œ ์œ ํ‹ธ๋ฆฌํ‹ฐ๊ฐ€ ์žˆ์Šต๋‹ˆ๋‹ค. B๋ธํƒ€, ๊ทธ๋ฆฌ๊ณ  ๊ทธ๊ฒƒ์€ ๋งค์šฐ ์˜ค๋žซ๋™์•ˆ ์šฐ๋ฆฌ ์ƒ์‚ฐ ๊ณผ์ •์— ๋ฟŒ๋ฆฌ ๋ฐ•ํ˜€ ์žˆ์—ˆ์Šต๋‹ˆ๋‹ค(๋น„๋ก ํ•ด๋‹น ๋ฒ„์ „์„ ์„ค์น˜ํ•  ์ˆ˜๋Š” ์—†์—ˆ์ง€๋งŒ ํ™•์‹คํžˆ ๋งˆ์ง€๋ง‰์œผ๋กœ ์‚ฌ์šฉ ๊ฐ€๋Šฅํ•œ ๋ฒ„์ „์€ ์•„๋‹ˆ์—ˆ์Šต๋‹ˆ๋‹ค). ์šฐ๋ฆฌ๋Š” ์ด๋ฅผ ์˜๋„๋œ ๋ชฉ์ , ์ฆ‰ ๋ฐ”์ด๋„ˆ๋ฆฌ ํŒจ์น˜ ๊ตฌ์ถ•์— ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค. ์ €์žฅ์†Œ์— ์žˆ๋Š” ๋‚ด์šฉ์„ ๋ณด๋ฉด ์กฐ๊ธˆ ์Šฌํ”„๊ฒŒ ๋ฉ๋‹ˆ๋‹ค. ์‚ฌ์‹ค ์ €์žฅ์†Œ๋Š” ์˜ค๋ž˜ ์ „์— ๋ฒ„๋ ค์กŒ๊ณ  ๋Œ€๋ถ€๋ถ„์ด ๋งค์šฐ ๊ตฌ์‹์ž…๋‹ˆ๋‹ค. (๋‚ด ์ „ ๋™๋ฃŒ๊ฐ€ ๊ทธ๊ณณ์—์„œ ์—ฌ๋Ÿฌ ๋ฒˆ ํŽธ์ง‘ํ•œ ์ ์ด ์žˆ์ง€๋งŒ ๊ทธ๊ฑด ์˜ค๋ž˜ ์ „ ์ผ์ž…๋‹ˆ๋‹ค.) . ์ผ๋ฐ˜์ ์œผ๋กœ ๋‚˜๋Š” ์ด ๋ฌธ์ œ๋ฅผ ๋ถ€ํ™œ์‹œํ‚ค๊ธฐ๋กœ ๊ฒฐ์ •ํ–ˆ์Šต๋‹ˆ๋‹ค. ๋‚˜๋Š” ํฌํฌํ•˜๊ณ , ์‚ฌ์šฉํ•  ๊ณ„ํš์ด ์—†๋Š” ๊ฒƒ์„ ๋ฒ„๋ฆฌ๊ณ , ํ”„๋กœ์ ํŠธ๋ฅผ ๋‹ค์Œ์œผ๋กœ ์˜ฎ๊ฒผ์Šต๋‹ˆ๋‹ค. cmake, ์ธ๋ผ์ธ๋œ "ํ•ซ" ๋งˆ์ดํฌ๋กœ ํ•จ์ˆ˜, ์Šคํƒ์—์„œ ํฐ ๋ฐฐ์—ด(๋ฐ ์†”์งํ•˜๊ฒŒ "ํญํƒ„"์œผ๋กœ ๋งŒ๋“œ๋Š” ๊ฐ€๋ณ€ ๊ธธ์ด ๋ฐฐ์—ด)์„ ์ œ๊ฑฐํ•˜๊ณ  ํ”„๋กœํŒŒ์ผ๋Ÿฌ๋ฅผ ๋‹ค์‹œ ํ•œ ๋ฒˆ ์‹คํ–‰ํ•œ ๊ฒฐ๊ณผ ์•ฝ 40%์˜ ์‹œ๊ฐ„์ด ์ž‘์—…์— ์†Œ๋น„๋œ๋‹ค๋Š” ์‚ฌ์‹ค์„ ์•Œ๊ฒŒ ๋˜์—ˆ์Šต๋‹ˆ๋‹ค. ์“ฐ๊ธฐ...

๊ทธ๋Ÿผ fwrite๋Š” ์–ด๋–ป๊ฒŒ ๋๋‚˜์š”?

์ด ์ฝ”๋“œ์—์„œ fwrite(๋‚ด ํŠน์ • ํ…Œ์ŠคํŠธ ์‚ฌ๋ก€: ๊ฐ€๊นŒ์šด 300MB ํŒŒ์ผ ์‚ฌ์ด์— ํŒจ์น˜๋ฅผ ๊ตฌ์ถ•ํ•˜๊ณ  ์ž…๋ ฅ ๋ฐ์ดํ„ฐ๊ฐ€ ์ „์ ์œผ๋กœ ๋ฉ”๋ชจ๋ฆฌ์— ์žˆ์Œ)๋Š” ์ž‘์€ ๋ฒ„ํผ ํฌ๊ธฐ๋กœ ์ˆ˜๋ฐฑ๋งŒ ๋ฒˆ ํ˜ธ์ถœ๋ฉ๋‹ˆ๋‹ค. ๋ถ„๋ช…ํžˆ ์ด ์ผ์ด ๋А๋ ค์งˆ ๊ฒƒ์ด๋ฏ€๋กœ ๋‚˜๋Š” ์–ด๋–ป๊ฒŒ๋“  ์ด ๋ถˆ๋ช…์˜ˆ์— ์˜ํ–ฅ์„ ๋ฏธ์น˜๊ณ  ์‹ถ์Šต๋‹ˆ๋‹ค. ์•„์ง์€ ๋‹ค์–‘ํ•œ ์œ ํ˜•์˜ ๋ฐ์ดํ„ฐ ์†Œ์Šค, ๋น„๋™๊ธฐ ์ž…์ถœ๋ ฅ์„ ๊ตฌํ˜„ํ•˜๋ ค๋Š” ์š•๊ตฌ๊ฐ€ ์—†์œผ๋ฉฐ ๋” ๊ฐ„๋‹จํ•œ ์†”๋ฃจ์…˜์„ ์ฐพ๊ณ  ์‹ถ์—ˆ์Šต๋‹ˆ๋‹ค. ๊ฐ€์žฅ ๋จผ์ € ๋– ์˜ค๋ฅธ ๊ฒƒ์€ ๋ฒ„ํผ ํฌ๊ธฐ๋ฅผ ๋Š˜๋ฆฌ๋Š” ๊ฒƒ์ด์—ˆ์Šต๋‹ˆ๋‹ค.

setvbuf(file, nullptr, _IOFBF, 64* 1024)

๊ทธ๋Ÿฌ๋‚˜ ๊ฒฐ๊ณผ๋Š” ํฌ๊ฒŒ ํ–ฅ์ƒ๋˜์ง€ ์•Š์•˜์Šต๋‹ˆ๋‹ค(ํ˜„์žฌ fwrite๊ฐ€ ์ „์ฒด ์‹œ๊ฐ„์˜ ์•ฝ 37%๋ฅผ ์ฐจ์ง€ํ•จ). ์ด๋Š” ์—ฌ์ „ํžˆ ๋””์Šคํฌ์— ๋ฐ์ดํ„ฐ๋ฅผ ์ž์ฃผ ์“ฐ๋Š” ๋ฌธ์ œ๊ฐ€ ์•„๋‹ˆ๋ผ๋Š” ์˜๋ฏธ์ž…๋‹ˆ๋‹ค. fwrite์˜ "๋‚ด๋ถ€"๋ฅผ ๋ณด๋ฉด FILE ์ž ๊ธˆ/์ž ๊ธˆ ํ•ด์ œ ๊ตฌ์กฐ๊ฐ€ ๋‹ค์Œ๊ณผ ๊ฐ™์€ ๋‚ด๋ถ€์—์„œ ๋ฐœ์ƒํ•˜๊ณ  ์žˆ์Œ์„ ์•Œ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค(์˜์‚ฌ ์ฝ”๋“œ, ๋ชจ๋“  ๋ถ„์„์€ 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;
}

ํ”„๋กœํŒŒ์ผ๋Ÿฌ์— ๋”ฐ๋ฅด๋ฉด _fwrite_nolock์€ ์‹œ๊ฐ„์˜ 6%๋งŒ ์ฐจ์ง€ํ•˜๋ฉฐ ๋‚˜๋จธ์ง€๋Š” ์˜ค๋ฒ„ํ—ค๋“œ์ž…๋‹ˆ๋‹ค. ๋‚ด ํŠน๋ณ„ํ•œ ๊ฒฝ์šฐ์—๋Š” ์Šค๋ ˆ๋“œ ์•ˆ์ „์„ฑ์ด ํ™•์‹คํžˆ ๊ณผ์ž‰์ด๋ฏ€๋กœ fwrite ํ˜ธ์ถœ์„ ๋‹ค์Œ์œผ๋กœ ๋Œ€์ฒดํ•˜์—ฌ ์Šค๋ ˆ๋“œ ์•ˆ์ „์„ฑ์„ ํฌ์ƒํ•˜๊ฒ ์Šต๋‹ˆ๋‹ค. _fwrite_nolock - ๋…ผ์Ÿ์— ๋Šฅ์ˆ™ํ•  ํ•„์š”๋„ ์—†์Šต๋‹ˆ๋‹ค. ์ „์ฒด: ์ด ๊ฐ„๋‹จํ•œ ์กฐ์ž‘์œผ๋กœ ์ธํ•ด ๊ฒฐ๊ณผ ๊ธฐ๋ก ๋น„์šฉ์ด ํฌ๊ฒŒ ์ค„์–ด๋“ค์—ˆ์œผ๋ฉฐ ์›๋ณธ ๋ฒ„์ „์—์„œ๋Š” ์†Œ์š” ์‹œ๊ฐ„์˜ ๊ฑฐ์˜ ์ ˆ๋ฐ˜์— ๋‹ฌํ–ˆ์Šต๋‹ˆ๋‹ค. ๊ทธ๊ฑด ๊ทธ๋ ‡๊ณ , POSIX ์„ธ๊ณ„์—๋„ ๋น„์Šทํ•œ ๊ธฐ๋Šฅ์ด ์žˆ์Šต๋‹ˆ๋‹ค. fwrite_unlocked. ์ผ๋ฐ˜์ ์œผ๋กœ ๋งํ•˜๋ฉด fread์—๋„ ๋™์ผํ•˜๊ฒŒ ์ ์šฉ๋ฉ๋‹ˆ๋‹ค. ๋”ฐ๋ผ์„œ ํ•œ ์Œ์˜ #define์„ ์‚ฌ์šฉํ•˜๋ฉด ํ•„์š”ํ•˜์ง€ ์•Š์€ ๊ฒฝ์šฐ ๋ถˆํ•„์š”ํ•œ ์ž ๊ธˆ ์—†์ด ์™„์ „ํžˆ ํฌ๋กœ์Šค ํ”Œ๋žซํผ ์†”๋ฃจ์…˜์„ ์–ป์„ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค(์ด๋Ÿฐ ์ผ์€ ๊ฝค ์ž์ฃผ ๋ฐœ์ƒํ•ฉ๋‹ˆ๋‹ค).

fwrite, _fwrite_nolock, setvbuf

์›๋ž˜ ํ”„๋กœ์ ํŠธ์—์„œ ๋ฒ—์–ด๋‚˜ ํŠน์ • ์‚ฌ๋ก€๋ฅผ ํ…Œ์ŠคํŠธํ•ด ๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค. ๋ฐ”๋กœ 512MB ํฌ๊ธฐ์˜ ํŒŒ์ผ์„ 1๋ฐ”์ดํŠธ์”ฉ ์•„์ฃผ ์ž‘์€ ๋ฉ์–ด๋ฆฌ๋กœ ๋‚˜๋ˆ„์–ด ์“ฐ๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค. ํ…Œ์ŠคํŠธ ์‹œ์Šคํ…œ ์‚ฌ์–‘์€ ๋‹ค์Œ๊ณผ ๊ฐ™์Šต๋‹ˆ๋‹ค. AMD Ryzen 7 1700, 16GB RAM, 7200rpm HDD, 64MB ์บ์‹œ. Windows 10 1809๋…„ ๋ฒ„์ „์—์„œ ๋ฐ”์ด๋„ˆ๋ฆฌ๋Š” 32๋น„ํŠธ๋กœ ๋นŒ๋“œ๋˜์—ˆ๊ณ , ์ตœ์ ํ™”๊ฐ€ ํ™œ์„ฑํ™”๋˜์—ˆ์œผ๋ฉฐ, ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๋Š” ์ •์ ์œผ๋กœ ๋งํฌ๋˜์—ˆ์Šต๋‹ˆ๋‹ค.

์‹คํ—˜ ์ƒ˜ํ”Œ:


#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;
}

๋ณ€์ˆ˜๋Š” TEST_BUFFER_SIZE๊ฐ€ ๋˜๋ฉฐ, ๋ช‡ ๊ฐ€์ง€ ๊ฒฝ์šฐ์— fwrite_unlocked๋ฅผ fwrite๋กœ ๋Œ€์ฒดํ•ฉ๋‹ˆ๋‹ค. ๋ฒ„ํผ ํฌ๊ธฐ๋ฅผ ๋ช…์‹œ์ ์œผ๋กœ ์„ค์ •ํ•˜์ง€ ์•Š๊ณ  fwrite ์‚ฌ๋ก€๋ถ€ํ„ฐ ์‹œ์ž‘ํ•˜๊ฒ ์Šต๋‹ˆ๋‹ค(setvbuf ๋ฐ ๊ด€๋ จ ์ฝ”๋“œ ์ฃผ์„ ์ฒ˜๋ฆฌ). ์‹œ๊ฐ„ 27048906 ยตs, ์“ฐ๊ธฐ ์†๋„ - 18.93 MB/s. ์ด์ œ ๋ฒ„ํผ ํฌ๊ธฐ๋ฅผ 64KB(์‹œ๊ฐ„ - 25037111ฮผs, ์†๋„ - 20.44Mb/s)๋กœ ์„ค์ •ํ•ด ๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค. ์ด์ œ setvbuf๋ฅผ ํ˜ธ์ถœํ•˜์ง€ ์•Š๊ณ  _fwrite_nolock์˜ ์ž‘๋™์„ ํ…Œ์ŠคํŠธํ•ด ๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค: 7262221 ยตs, ์†๋„ - 70.5 Mb/s!

๋‹ค์Œ์œผ๋กœ ๋ฒ„ํผ ํฌ๊ธฐ(setvbuf)๋ฅผ ์‹คํ—˜ํ•ด ๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค.

ํž˜๋“ค์ด์ง€ ์•Š๊ณ  C/C++ ํŒŒ์ผ I/O ๊ฐ€์†ํ™”

5๋ฒˆ์˜ ์‹คํ—˜์„ ํ‰๊ท ํ•˜์—ฌ ๋ฐ์ดํ„ฐ๋ฅผ ์–ป์—ˆ๋Š”๋ฐ ๋„ˆ๋ฌด ๊ฒŒ์„๋Ÿฌ์„œ ์˜ค์ฐจ๋ฅผ ๊ณ„์‚ฐํ•  ์ˆ˜๊ฐ€ ์—†์—ˆ์Šต๋‹ˆ๋‹ค. ๋‚˜๋กœ์„œ๋Š” ์ผ๋ฐ˜ HDD์— 93๋ฐ”์ดํŠธ๋ฅผ ์“ธ ๋•Œ 1MB/s๊ฐ€ ๋งค์šฐ ์ข‹์€ ๊ฒฐ๊ณผ์ž…๋‹ˆ๋‹ค. ์ตœ์ ์˜ ๋ฒ„ํผ ํฌ๊ธฐ๋ฅผ ์„ ํƒํ•˜๊ณ (์ œ ๊ฒฝ์šฐ์—๋Š” 256KB๊ฐ€ ๋”ฑ ๋งž์Šต๋‹ˆ๋‹ค) fwrite๋ฅผ _fwrite_nolock/fwrite_unlocked( ๋ฌผ๋ก  ์Šค๋ ˆ๋“œ ์•ˆ์ „์„ฑ์ด ํ•„์š”ํ•˜์ง€ ์•Š์€ ๊ฒฝ์šฐ).
๋น„์Šทํ•œ ์กฐ๊ฑด์—์„œ fread๋„ ๋งˆ์ฐฌ๊ฐ€์ง€์ž…๋‹ˆ๋‹ค. Linux๊ฐ€ ์„ค์น˜๋œ ํ•˜๋“œ์›จ์–ด ๋จธ์‹ ์ด ์—†๊ธฐ ๋•Œ๋ฌธ์—(๋‹จ์ผ ๋ณด๋“œ๋Š” ํฌํ•จ๋˜์ง€ ์•Š์Œ) ๊ฐ€์ƒ ๋จธ์‹ (Hyper-V, OpenSUSE 15, GCC 8.3.1)์—์„œ ์ œํ•œ๋œ ์‹คํ—˜์„ ์ˆ˜ํ–‰ํ•˜๊ธฐ๋กœ ๊ฒฐ์ •ํ–ˆ์Šต๋‹ˆ๋‹ค. ํŒจํ„ด์€ ๋‹ค์Œ๊ณผ ๊ฐ™์Šต๋‹ˆ๋‹ค. ๊ธฐ๋ณธ์ ์œผ๋กœ ๋™์ผ: "๋„ค์ดํ‚ค๋“œ" fwrite 20 Mb/s, fwrite + 256 KB ๋ฒ„ํผ๋Š” 23 Mb/s๋ฅผ ์ƒ์„ฑ, fwrite_unlocked๋Š” ๋™์ผํ•œ ๋ฒ„ํผ - 35 Mb/s(64๋น„ํŠธ ๋ฐ”์ด๋„ˆ๋ฆฌ, ์–ด์…ˆ๋ธ”๋œ g++ -o2 -s -static-libgcc -static-libstdc++ fwrite_test.cpp -o fwrite_test).

์‚ฌํ›„

์ด ๊ธ€์„ ์“ด ๋ชฉ์ ์€ ๋งŽ์€ ๊ฒฝ์šฐ์— ๊ฐ„๋‹จํ•˜๊ณ  ํšจ๊ณผ์ ์ธ ๊ธฐ์ˆ ์„ ์„ค๋ช…ํ•˜๋Š” ๊ฒƒ์ด์—ˆ์Šต๋‹ˆ๋‹ค. (๋‚˜๋Š” ์ด์ „์— _fwrite_nolock/fwrite_unlocked ํ•จ์ˆ˜๋ฅผ ์ ‘ํ•ด๋ณธ ์ ์ด ์—†์œผ๋ฉฐ ๊ทธ๋‹ค์ง€ ์ธ๊ธฐ๊ฐ€ ์—†์ง€๋งŒ ํ—›๋œ ๊ฒƒ์ž…๋‹ˆ๋‹ค.) ๋‚˜๋Š” ๊ทธ ์ž๋ฃŒ๊ฐ€ ์ƒˆ๋กœ์šด ๊ฒƒ์ด๋ผ๊ณ  ์ฃผ์žฅํ•˜์ง€ ์•Š์ง€๋งŒ, ๊ทธ ๊ธฐ์‚ฌ๊ฐ€ ์ปค๋ฎค๋‹ˆํ‹ฐ์— ๋„์›€์ด ๋˜๊ธฐ๋ฅผ ๋ฐ”๋ž๋‹ˆ๋‹ค.

์ถœ์ฒ˜ : habr.com

DDoS ๋ณดํ˜ธ, VPS VDS ์„œ๋ฒ„๊ฐ€ ์žˆ๋Š” ์‚ฌ์ดํŠธ๋ฅผ ์œ„ํ•œ ์•ˆ์ •์ ์ธ ํ˜ธ์ŠคํŒ… ๊ตฌ์ž… ๐Ÿ”ฅ DDoS ๊ณต๊ฒฉ ๋ฐฉ์ง€ ๊ธฐ๋Šฅ์ด ํƒ‘์žฌ๋œ ์•ˆ์ •์ ์ธ ์›น์‚ฌ์ดํŠธ ํ˜ธ์ŠคํŒ…, VPS ๋ฐ VDS ์„œ๋ฒ„๋ฅผ ๊ตฌ๋งคํ•˜์„ธ์š” | ProHoster