Mengapa nilai tipe null berubah di dalam loop?


109

Menjalankan cuplikan ini di konsol Chrome:

function foo() {
    return typeof null === 'undefined';
}
for(var i = 0; i < 1000; i++) console.log(foo());

harus mencetak 1000 kali false, tetapi pada beberapa mesin akan mencetak falseuntuk beberapa iterasi, kemudian truesisanya.

masukkan deskripsi gambar di sini

Mengapa ini terjadi? Apakah ini hanya bug?


4
Ini mengembalikan 1000 kali benar bagi saya ...
Hoàng Long

2
saya pikir itu bug, saya punya 262 salah / 738 benar
Jax Teller

1
itu sesuatu yang aneh dengan konsol chrome: jika Anda mendorong ke sebuah array dan mencatat array, itu saja false. sebagaimana adanya, jumlah trues berfluktuasi di chrome.
dandavis

1
@ HoàngLong seperti yang saya katakan dalam pertanyaan, ini hanya terjadi pada beberapa mesin. Mungkin juga hal itu terjadi hanya pada beberapa versi Chrome
Agos

2
@ HoàngLong pastikan Anda menjalankannya di Chrome
Nobita

Jawaban:



37

Ini sebenarnya adalah mesin JavaScript V8 ( Wiki bug ).

Mesin ini digunakan di Chromium, Maxthron, Android OS, Node.js dll.

Deskripsi bug yang relatif sederhana dapat Anda temukan di topik Reddit ini :

Mesin JavaScript modern mengkompilasi kode JS menjadi kode mesin yang dioptimalkan ketika dijalankan (kompilasi Just In Time) untuk membuatnya berjalan lebih cepat. Namun, langkah pengoptimalan memiliki beberapa biaya performa awal sebagai gantinya untuk percepatan jangka panjang, sehingga mesin secara dinamis memutuskan apakah suatu metode layak dilakukan tergantung pada seberapa umum metode tersebut digunakan.

Dalam kasus ini, tampaknya hanya ada bug di jalur yang dioptimalkan, sedangkan jalur yang tidak dioptimalkan berfungsi dengan baik. Jadi pada awalnya metode ini berfungsi sebagaimana mestinya, tetapi jika dipanggil dalam loop cukup sering pada titik tertentu, mesin akan memutuskan untuk mengoptimalkannya dan menggantinya dengan versi buggy.

Bug ini tampaknya telah diperbaiki di V8 itu sendiri ( commit ), juga di Chromium ( laporan bug ) dan NodeJS ( commit ).


Saya mengonfirmasi bahwa bug tersebut masih ada di Node.js 6.2.2 yang membuat saya khawatir.
Michael Shopsin

Itu diperbaiki di mesin V8 hari ini (21.06), saya yakin perangkat lunak terkait akan segera diperbarui.
Sergey Novikov

Melakukan backport perbaikan v8 ke Node.js 6.2.x sedang berlangsung karena masalah # 7348 dimiliki oleh TheAlphaNerd .
Michael Shopsin

18

Untuk menjawab pertanyaan langsung mengapa itu berubah, bug tersebut ada dalam rutinitas pengoptimalan "JIT" dari mesin V8 JS yang digunakan oleh Chrome. Pada awalnya, kode dijalankan persis seperti yang tertulis, tetapi semakin sering Anda menjalankannya, semakin besar potensi manfaat pengoptimalan yang melebihi biaya analisis.

Dalam kasus ini, setelah eksekusi berulang dalam loop, kompilator JIT menganalisis fungsi tersebut, dan menggantinya dengan versi yang dioptimalkan. Sayangnya, analisis membuat asumsi yang salah, dan versi yang dioptimalkan sebenarnya tidak memberikan hasil yang benar.

Secara khusus, pengguna Reddit RainHappens menyarankan bahwa ini adalah kesalahan dalam jenis propagasi :

Itu juga melakukan beberapa jenis propagasi (seperti dalam tipe apa variabel dll). Ada tipe khusus "tidak terdeteksi" ketika variabel tidak terdefinisi atau null. Dalam hal ini pengoptimal mengatakan "null tidak terdeteksi, sehingga dapat diganti dengan string" tidak ditentukan "untuk perbandingan.

Ini adalah salah satu masalah sulit dengan pengoptimalan kode: bagaimana menjamin bahwa kode yang telah diatur ulang untuk kinerja akan tetap memiliki efek yang sama seperti aslinya.


Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.