Siapa pun dapat membuat kesalahan Rockstar (dan saya juga bisa.)



Beberapa bulan yang lalu, sebuah artikel luar biasa [terjemahan dalam Habré: satu dan dua ] tentang Grand Theft Auto Online muncul di berita .



Saya menyarankan Anda untuk membaca seluruh artikel, tetapi singkatnya, GTA Online tiba - tiba memiliki kinerja kuadrat ketika mem-parsing gumpalan JSON yang besar (karena banyak panggilan strlen



); setelah memperbaiki kesalahan ini, waktu pemuatan berkurang hampir 70%.



Ini memicu perdebatan yang hidup : Apakah C yang harus disalahkan untuk ini? Atau mungkin "kotoran web" ? Atau kapitalisme dan insentifnya ?



Namun, semua orang setuju pada satu hal : mereka tidak akan pernah menulis omong kosong seperti itu.



( Dapatkah Anda merasakan apa yang akan datang? )




Salah satu proyek sampingan saya adalah penampil model 3D berkinerja tinggi yang disebut Erizo .





Dengan kode pintar, ini membuka biner STL 97MB pada Macbook Pro 2013 hanya dalam 165 milidetik. Ini kecepatan yang luar biasa .



Untuk alasan kompatibilitas, saya juga menulis parser kecil untuk ASCII STL .



ASCII STL adalah format teks biasa yang tidak ditentukan dengan baik yang terlihat seperti ini:



solid cube_corner
          facet normal 0.0 -1.0 0.0
            outer loop
              vertex 0.0 0.0 0.0
              vertex 1.0 0.0 0.0
              vertex 0.0 0.0 1.0
            endloop
          endfacet
          facet normal 0.0 0.0 -1.0
            outer loop
              vertex 0.0 0.0 0.0
              vertex 0.0 1.0 0.0
              vertex 1.0 0.0 0.0
            endloop
          endfacet
          ...
endsolid
      
      





Saya menulis parser yang sangat kuat dengan komentar seperti ini:



/*     ASCII STL:  , 
 *   'vertex',         float. */
      
      





Memuat ASCII STL selalu tampak agak lambat, tetapi saya berasumsi itu karena format teks yang tidak efisien.



( Awan berkumpul. )






Beberapa peristiwa terjadi dalam beberapa hari:





Berikut adalah log unduhan stempel waktu ASCII STL 1,5 MB (dalam detik):



[erizo] (0.000000) main.c:10      | Startup!
[erizo] (0.162895) window.c:91    | Created window
[erizo] (0.162900) window.c:95    | Made context current
[erizo] (0.168715) window.c:103   | Initialized GLEW
[erizo] (0.178329) window.c:91    | Created window
[erizo] (0.178333) window.c:95    | Made context current
[erizo] (1.818734) loader.c:109   | Parsed ASCII STL
[erizo] (1.819471) loader.c:227   | Workers have deduplicated vertices
[erizo] (1.819480) loader.c:237   | Got 5146 vertices (7982 triangles)
[erizo] (1.819530) loader.c:240   | Waiting for buffer...
[erizo] (1.819624) loader.c:326   | Allocated buffer
[erizo] (1.819691) loader.c:253   | Sent buffers to worker threads
[erizo] (1.819883) loader.c:258   | Joined worker threads
[erizo] (1.819887) loader.c:279   | Loader thread done
[erizo] (1.821291) instance.c:32  | Showed window
      
      





Lebih dari 1,8 detik berlalu dari saat peluncuran ke tampilan jendela!



Melihat parser ASCII dengan segar, saya melihat bahwa alasannya jelas:



    /*  The most liberal ASCII STL parser:  Ignore everything except
     *  the word 'vertex', then read three floats after each one. */
    const char VERTEX_STR[] = "vertex ";
    while (1) {
        data = strstr(data, VERTEX_STR);
        if (!data) {
            break;
        }

        /* Skip to the first character after 'vertex' */
        data += strlen(VERTEX_STR);

        for (unsigned i=0; i < 3; ++i) {
            SKIP_WHILE(isspace);
            float f;
            const int r = sscanf(data, "%f", &f);
            ABORT_IF(r == 0 || r == EOF, "Failed to parse float");
            if (buf_size == buf_count) {
                buf_size *= 2;
                buffer = (float*)realloc(buffer, buf_size * sizeof(float));
            }
            buffer[buf_count++] = f;

            SKIP_WHILE(!isspace);
        }
    }
      
      





Anda dapat melihat bahwa dalam kode ada satu sscanf



yang membaca satu nilai float dari awal aliran data dan setiap kali memeriksa panjang seluruh string .



Ya, saya membuat kesalahan yang sama dengan programmer yang bekerja di GTA Online: Saya tiba-tiba menulis parser kuadrat!



Mengganti panggilan sscanf



dengan panggilan strtof



mengurangi waktu pemuatan hampir 10 kali: dari 1,8 detik menjadi 199 milidetik.



[erizo] (0.000000) main.c:10      | Startup!
[erizo] (0.178082) window.c:91    | Created window
[erizo] (0.178086) window.c:95    | Made context current
[erizo] (0.184226) window.c:103   | Initialized GLEW
[erizo] (0.194469) window.c:91    | Created window
[erizo] (0.194472) window.c:95    | Made context current
[erizo] (0.196126) loader.c:109   | Parsed ASCII STL
[erizo] (0.196866) loader.c:227   | Workers have deduplicated vertices
[erizo] (0.196871) loader.c:237   | Got 5146 vertices (7982 triangles)
[erizo] (0.196921) loader.c:240   | Waiting for buffer...
[erizo] (0.197013) loader.c:326   | Allocated buffer
[erizo] (0.197082) loader.c:253   | Sent buffers to worker threads
[erizo] (0.197303) loader.c:258   | Joined worker threads
[erizo] (0.197306) loader.c:279   | Loader thread done
[erizo] (0.199328) instance.c:32  | Showed window
      
      








Ini adalah pengingat yang sempurna bahwa meskipun Anda telah memprogram selama bertahun-tahun, selalu ada jebakan . Dalam sscanf



tidak mengisi kompleksitas waktu, sehingga pistol sangat licik menembak dirinya sendiri di kaki, dan tampaknya bagi saya bahwa tidak ada yang saya mengembara dalam kegelapan ketidaktahuan.



Anda sendiri mungkin tidak diingatkan seperti ini, tetapi setiap kali Anda membaca cerita yang luar biasa tentang kode yang buruk, ingatlah - itu juga bisa terjadi pada Anda!



(Jelas, moral dari ceritanya adalah ini: jangan gunakan sscanf



token tunggal dari awal baris untuk menguraikan beberapa kali; Saya yakin Anda akan baik-baik saja jika Anda menghindarinya.)






Periklanan



VDSina menawarkan VPS yang kuat dan terjangkau dengan pembayaran harian. Saluran Internet untuk setiap server adalah 500 Megabit, perlindungan terhadap serangan DDoS termasuk dalam tarif, kemampuan untuk menginstal Windows, Linux atau OS secara umum dari gambar Anda, dan juga panel kontrol server berpemilik yang sangat nyaman . Cobalah!






All Articles