حل مشکل کندی لود شدن سایت در جی کوئری
مسئله: آیا سایت شما پس از کلیک کردن کاربر، در لود شدن خیلی کند است و نمی دانید چرا. چه بخشی از کدها باعث شده لود شدن سایت اینقدر طول بکشد؟
راه حل: از یک پروفایلر(profiler) استفاده کنید، یا از یکی از نمونه های در دسترس که به فراوانی یافت می شوند استفاده کنید یا از یک نمونه ی ساده که خودتان می توانید بنویسید، استفاده کنید.
پروفایلر، یک راه برای پیدا کردن بخش هایی از کدهای ما است که بیشترین زمان را صرف می کنند. شما احتمالاً قبلاً حداقل از یک پروفایلر خوب جاوا اسکریپت به راحتی استفاده کرده اید.
فایرباگ(Firebug) یک پروفایلر دارد و بقیه در اینترنت اکسپلورر ۸ و سافاری ۴ نیز تعبیه شده اند. همه اینها عملکردهای پروفایلر هستند: شما شروع به پروفایل کردن میکنید، با صفحه خود تعامل میکنید و پروفایل کردن را متوقف میکنید و آنگاه یک گزارش به شما داده می شود که نشان می دهد در هر عملکرد، چقدر زمان گذشته است. همین کافی است تا به شما بگوید کدام کد را باید سرعت ببخشید.
همچنین برخی پروفایلرهای مخصوص جی کوئری نیز وجود دارند که می توانید با یک سرچ عبارت jquery profiler آنها را پیدا کنید. اینها به شما امکان می دهند تا کارایی سلکتور خود را شکل دهید و نگاه عمیق تری به کارایی عملکرد جی کوئری داشته باشید. برای انجام یک پروفایلینگ دقیق، که در آن نیاز داریم بخش های منحصر به فردی از کدهای کوچکتر از سطح تابع(smaller than the function level) را آنالیز کنیم، می توانیم یک پروفایلر ساده را در قالب چند خط کد، بنویسیم. مثلا می توانیم کد کلاسیک زیر را بنویسیم:
var t1 = +new Date;
// ... do stuff ...
var t2 = +new Date;
alert( ( t2 - t1 ) + ' milliseconds' );
نکته: عبارت +new Date در کد بالا، فقط یک راه ساده تر برای نوشتن کد آشنای new Date().getTime() است، که زمان فعلی را به میلی ثانیه برمی گرداند. در کد بالا، دو دستور new Date وجود دارد؛ این دستور یک آبجکت Date به ما می دهد که زمان فعلی را بیان می کند. (قرار دادن جفت پرانتزها() اختیاری است، زیرا هیچ آرگومانی وجود ندارد). عملگر + این آبجکت را به یک عدد تبدیل می کند. جاوا اسکریپت با فراخوانی متد .valueOf() از آبجکت، آن آبجکت را به یک عدد تبدیل می کند. و متد .valueOf() برای یک آبجکت Date، تصادفاً، همان کاری است که متد .getTime() انجام می دهد و زمان را به میلی ثانیه به ما تحویل می دهد.
اگر تنها 15 دقیقه کدنویسی کنیم، می توانیم به یک برنامه ی کامل تر و ساده تر برای استفاده، دست پیدا کنیم:
(function() {
var log = [], first, last;
time = function( message, since ) {
var now = +new Date;
var seconds = ( now - ( since || last ) ) / 1000;
log.push( seconds.toFixed(3) + ': ' + message + '<br />' );
return last = +new Date;
};
time.done = function( selector ) {
time( 'total', first );
$(selector).html( log.join('') );
};
first = last = +new Date;
})();
اکنون یک تابع به نام time() داریم که می توانیم هروقت که بخواهیم آن را برای ثبت زمان سپری شده، از آخرین اجرای تابع time()، فراخوانی کنیم(یا به طور اختیاری از یک زمان خاص قبلی). وقتی که آماده هستیم نتیجه را گزارش کنیم، تابع time.done() را فراخوانی می کنیم. به مثال زیر توجه کنید:
// do stuff
time( 'first' );
// do more stuff
time( 'second' );
// and more
time( 'third' );
time.done( '#log' );
کد جاوا اسکریپت ما نیاز دارد کد HTML زیر را در صفحه خود اضافه کنیم:
<div id="log">
</div>
پس از اینکه کد اجرا شود، عنصر <div> با استفاده از یک لیست(list) مانند زیر پر می شود:
0.102 first
1.044 second
0.089 third
1.235 total
مشاهده خواهید کرد که بیشترین مقدار زمان، بین فراخوانی time('first') و time('second') سپری شده است.
مراقب فایرباگ باشید!
اگر فایرباگ را در صفحه فعال کرده باشید، زمانبندی انجام میشود که میتواند نتایج را به میزان قابل توجهی تغییر دهد. تابع eval() در جاوا اسکریپت، که جی کوئری 1.3.2 و نسخه های قبلی، از آن برای ارزیابی داده های JSON استفاده می کنند، به شدت تحت تأثیر قرار میگیرد:
یک آرایه از هزار نام و آدرس در قالب بخش 5.11 در صفحه 109 کتاب، به طور نرمال 0.2 ثانیه در فایرفاکس زمان می برد؛ اما اگر پنل اسکریپت فایرباگ فعال شده باشد، 55 ثانیه طول می کشد. نسخه های بعدی جی کوئری برای انجام این کار از Function() استفاده می کنند که از فایرباگ تاثیر نمی پذیرد.
اگر فایرباگ روی صفحه ی شما به همین بدی تاثیر می گذارد، و اگر نمی توانید یک راه حل پیدا کنید، ممکن است بخواهید مشکل Firebug را پیدا کنید و یک هشدار را نمایش دهید:
<div id="firebugWarning" style="display:none;">
Your warning here
</div>
$(document).ready( function() {
if( window.console && console.firebug )
$('#firebugWarning').show();
});
برای بسیاری از تمرین های بهینه سازی، این کد ممکن است کافی باشد. اما اگر کدی که نیاز داریم تا با آن تست کنیم، در درون یک حلقه قرار داشته باشد، چه می شود؟
for( var i = 0; i < 10; ++i ) {
// do stuff
time( 'first' );
// do more stuff
time( 'second' );
// and more
time( 'third' );
}
time.done( '#log' );
حالا پروفایلر کوچک ما آن ورودیهای first و second و third را هر کدام ۱۰ بار لیست میکند؛ تعمیر آن خیلی سخت نیست. تنها نیاز داریم زمان صرف شده برای هر برچسب پیام خاص را وقتی چندین بار فراخوانی میشود، جمع کنیم:
(function() {
var log = [], index = {}, first, last;
// Accumulate seconds for the specified message.
// Each message string has its own total seconds.
function add( message, seconds ) {
var i = index[message];
if( i == null ) {
i = log.length;
index[message] = i;
log[i] = { message:message, seconds:0 };
}
log[i].seconds += seconds;
}
time = function( message, since ) {
var now = +new Date;
add( message, ( now - ( since || last ) ) / 1000 );
return last = +new Date;
}
time.done = function( sel ) {
time( 'total', first );
$(sel).html(
$.map( log, function( item ) {
return(
item.seconds.toFixed(3) + ': ' + item.message + '<br />'
);
}).join('')
);
};
first = last = +new Date;
})();
با این تغییر، نتایج مفیدی از آن حلقه به دست می آوریم:
0.973 first
9.719 second
0.804 third
11.496 total
وقتی نتایج تست زمانبندی متفاوت است
وقتی که تست های زمان بندی را در یک صفحه وب اجرا می کنیم، همیشه نتایج مشابهی را دریافت نمی کنیم. اگر یک صفحه را بارگذاری مجدد کنیم یا یک تست را چندین بار مجدداً چندین بار اجرا کنیم، در حقیقت نتایج زمان بندی احتمالاً کمی تغییر می کند؛ باید چه کار کنیم تا اعدادی حقیقی را به دست بیاوریم؟ آیا باید میانگین نتایج را به دست بیاوریم؟ احتمالاً خیر. در زیر یک نمودار از تابع fillTable() که در بخش 5.11 قرار دارد، برای 50 اجرای متوالی قرار داده ایم که با فاصله حدود ۱۰ ثانیه ایجاد شده است:

در اینجا، یک الگوی مشخص وجود دارد: اکثریت زیادی از اجراها در محدوده ۱۵۰ تا ۲۰۰ میلیثانیه هستند، و تعداد کمی از اجراهای پراکنده زمان بیشتری میبرند. به نظر می رسد که احتمالاً زمان بندی حقیقی، چیزی حدود 175 میلی ثانیه است. و اجراهایی که خیلی بیشتر طول می کشد، توسط دیگر پردازش ها در رایانه(machine) تحت تاثیر قرار می گیرند. این امکان نیز وجود دارد که برخی از اجراهای طولانی تر، تحت تاثیر زباله روبی(garbage collection یا مدیریت حافظه) در مرورگر قرار گرفته باشند. تشخیص این زمان، از زمان صرف شده توسط سایر فرآیندها دشوار است، بنابراین احتملاً بهترین کار،نادیده گرفتن این دادهها است.
- بازدید: 89
1. سعی کنید نظرات شما مرتبط با مقاله ی مورد نظر باشد، در غیر این صورت پاسخ داده نخواهد شد.
2. سوالات خود را به صورت کوتاه بیان کنید و از پرسیدن چند سوال به طور همزمان خودداری کنید.
3. سوال خود را به طور واضح بیان کنید و از کلمات مبهم استفاده نکنید.