لقد أدى ظهور AJAX إلى تغيير كبير في وضع تشغيل عملاء تطبيقات الويب، فهو يسمح للمستخدمين بالتركيز على عملهم دون الاضطرار إلى تحمل تحديثات الصفحة المزعجة بشكل متكرر. من الناحية النظرية، يمكن لتقنية AJAX تقليل وقت انتظار عمليات المستخدم إلى حد كبير وتوفير حركة البيانات على الشبكة. ومع ذلك، هذا ليس هو الحال دائما. غالبًا ما يشتكي المستخدمون من انخفاض سرعة استجابة الأنظمة التي تستخدم AJAX.
شارك المؤلف في أبحاث وتطوير AJAX لسنوات عديدة وشارك في تطوير Dorado، وهي منصة AJAX ناضجة نسبيًا في الصين. وفقا لتجربة المؤلف، فإن السبب الجذري لهذه النتيجة ليس AJAX. في كثير من الأحيان يكون سبب الانخفاض في سرعة استجابة النظام هو تصميم الواجهة غير المعقول وعادات البرمجة غير الفعالة. سنقوم أدناه بتحليل العديد من الجوانب التي يجب الاهتمام بها أثناء عملية تطوير AJAX.
الاستخدام السليم لبرمجة العميل واستدعاءات الإجراءات عن بعد.
تعتمد البرمجة من جانب العميل بشكل أساسي على JavaScript. JavaScript هي لغة برمجة مفسرة، وكفاءة تشغيلها أقل قليلاً من كفاءة Java. وفي الوقت نفسه، تعمل JavaScript في بيئة مقيدة تمامًا مثل المتصفح. لذلك يجب أن يكون لدى المطورين فهم واضح للمنطق الذي يمكن تنفيذه من جانب العميل.
تعتمد كيفية استخدام البرمجة من جانب العميل في التطبيقات الفعلية على خبرة المطور وحكمه. لا يمكن فهم العديد من المشاكل هنا إلا. نظرًا للمساحة المحدودة، نلخص هنا تقريبًا الاحتياطات التالية:
تجنب الاستخدام المتكرر لاستدعاءات الإجراءات عن بعد قدر الإمكان، على سبيل المثال، تجنب استخدام استدعاءات الإجراءات عن بعد في أجسام الحلقة.
إذا أمكن، استخدم استدعاء الإجراء البعيد AJAX (استدعاء الإجراء البعيد غير المتزامن).
تجنب وضع عمليات البيانات ذات الوزن الثقيل على جانب العميل. على سبيل المثال: دفعات كبيرة من عمليات نسخ البيانات، والحسابات التي تتطلب كمية كبيرة من اجتياز البيانات، وما إلى ذلك.
تحسين طريقة تشغيل كائنات DOM.
في البرمجة من جانب العميل، غالبًا ما تكون العمليات على كائنات DOM هي الأكثر احتمالاً لاحتلال وقت وحدة المعالجة المركزية. بالنسبة لتشغيل كائنات DOM، غالبًا ما يكون فرق الأداء بين طرق البرمجة المختلفة كبيرًا جدًا.
فيما يلي ثلاث أجزاء من التعليمات البرمجية لها نفس النتائج تمامًا، وتتمثل وظيفتها في إنشاء جدول 10x1000 في صفحة الويب. ومع ذلك، فإن سرعات تشغيلها مختلفة إلى حد كبير.
/* رمز الاختبار 1 - الوقت المستغرق: 41 ثانية*/
var table = document.createElement("TABLE");
document.body.appendChild(table);
for(var i = 0; i < 1000; i++){
صف فار = table.insertRow(-1);
ل(فار ي = 0; ي < 10; ي++){
خلية فار = objRow.insertCell(-1);
cell.innerText = "( " + i + " , " + j + " )";
}
}
/* رمز الاختبار 2 - الوقت المستغرق: 7.6 ثانية*/
var table = document.getElementById("TABLE");
document.body.appendChild(table);
var tbody = document.createElement("TBODY");
table.appendChild(tbody);
for(var i = 0; i < 1000; i++){
فار الصف = document.createElement("TR");
tbody.appendChild(row);
ل(فار ي = 0; ي < 10; ي++){
فار الخلية = document.createElement("TD");
Row.appendChild(cell);
cell.innerText = "( " + i + " , " + j + " )";
}
}
/* رمز الاختبار 3 - الوقت المستغرق: 1.26 ثانية*/
var tbody = document.createElement("TBODY");
for(var i = 0; i < 1000; i++){
فار الصف = document.createElement("TR");
ل(فار ي = 0; ي < 10; ي++){
فار الخلية = document.createElement("TD");
cell.innerText = "( " + i + " , " + j + " )";
Row.appendChild(cell);
}
tbody.appendChild(row);
}
var table = document.getElementById("TABLE");
table.appendChild(tbody);
document.body.appendChild(table);
الفرق بين "رمز الاختبار 1" و"رمز الاختبار 2" هنا هو أنه يتم استخدام أساليب API مختلفة عند إنشاء خلايا الجدول. يكمن الاختلاف بين "رمز الاختبار 2" و"رمز الاختبار 3" في ترتيب المعالجة المختلف قليلاً.
لا يمكننا تحليل هذا الاختلاف الكبير في الأداء بين "رمز الاختبار 1" و"رمز الاختبار 2". ما هو معروف حاليًا هو أن InsertRow وinsertCell عبارة عن واجهات برمجة تطبيقات خاصة بالجدول في DHTML، وأن createElement وappendChild هما واجهات برمجة تطبيقات أصلية لـ W3C DOM. يجب أن يكون الأول عبارة عن تغليف للأخير. ومع ذلك، لا يمكننا أن نستنتج من هذا أن واجهة برمجة التطبيقات الأصلية لـ DOM أفضل دائمًا من واجهة برمجة التطبيقات الخاصة بالكائن. يوصى بإجراء بعض الاختبارات الأساسية على أدائها عندما تحتاج إلى الاتصال بواجهة برمجة التطبيقات (API) بشكل متكرر.
يأتي اختلاف الأداء بين "رمز الاختبار 2" و"رمز الاختبار 3" بشكل أساسي من الاختلاف في ترتيب البناء الخاص بهما. تتمثل طريقة "رمز الاختبار 2" في إنشاء كائن <TABLE> الخارجي أولاً، ثم إنشاء <TR> و<TD> بالتسلسل في الحلقة. تتمثل طريقة "رمز الاختبار 3" في إنشاء الجدول بأكمله في الذاكرة من الداخل إلى الخارج أولاً، ثم إضافته إلى صفحة الويب. والغرض من ذلك هو تقليل عدد المرات التي يعيد فيها المتصفح حساب تخطيط الصفحة قدر الإمكان. عندما نضيف كائنًا إلى صفحة ويب، يحاول المتصفح إعادة حساب تخطيط عناصر التحكم على الصفحة. لذلك، إذا تمكنا أولاً من إنشاء الكائن بأكمله المراد إنشاؤه في الذاكرة، ثم إضافته إلى صفحة الويب مرة واحدة. بعد ذلك، سيقوم المتصفح فقط بإعادة حساب التخطيط. لتلخيص ذلك في جملة واحدة، كلما قمت بتنفيذ appendChild لاحقًا، كلما كان ذلك أفضل. في بعض الأحيان، من أجل تحسين كفاءة التشغيل، يمكننا حتى التفكير في استخدام RemoveChild لإزالة عنصر التحكم الموجود من الصفحة، ثم إعادة وضعه مرة أخرى إلى الصفحة بعد اكتمال الإنشاء.
تحسين سرعة تراكم السلاسل عند استخدام AJAX لإرسال المعلومات، قد أحتاج غالبًا إلى تجميع بعض السلاسل الكبيرة نسبيًا لإكمال إرسال POST من خلال XmlHttp. على الرغم من أن تقديم مثل هذا الكم الكبير من المعلومات قد يبدو غير لائق، إلا أنه في بعض الأحيان قد نضطر إلى مواجهة مثل هذه الحاجة. ما مدى سرعة تراكم السلاسل في JavaScript؟ لنقم بالتجربة التالية أولاً. قم بتجميع سلسلة بطول 30000.
/* رمز الاختبار 1 - الوقت المستغرق: 14.325 ثانية*/
فار str = "";
لـ (var i = 0; i < 50000; i++) {
str += "xxxxxx";
}
استغرق هذا الكود 14.325 ثانية، ولم تكن النتائج مثالية. الآن نقوم بتغيير الكود إلى النموذج التالي:
/* رمز الاختبار 2 - الوقت المستغرق: 0.359 ثانية*/
فار str = "";
لـ (var i = 0; i < 100; i++) {
فار الفرعية = "";
لـ (var j = 0; j < 500; j++) {
الفرعية += "xxxxxx";
}
str += sub;
}
يستغرق هذا الرمز 0.359 ثانية! نفس النتيجة، كل ما نفعله هو تجميع بعض السلاسل الصغيرة أولاً ثم تجميعها في سلاسل أكبر. يمكن لهذا الأسلوب تقليل كمية البيانات المنسوخة في الذاكرة بشكل فعال في المراحل اللاحقة من تجميع السلسلة. بعد معرفة هذا المبدأ، يمكننا تفكيك الكود أعلاه للاختبار. يستغرق الكود أدناه 0.140 ثانية فقط.
/* رمز الاختبار 3 - الوقت المستغرق: 0.140 ثانية*/
فار str = "";
لـ (var i1 = 0; i1 < 5; i1++) {
فار str1 = "";
لـ (var i2 = 0; i2 < 10; i2++) {
فار str2 = "";
لـ (var i3 = 0; i3 < 10; i3++) {
فار str3 = "";
لـ (var i4 = 0; i4 < 10; i4++) {
فار str4 = "";
لـ (var i5 = 0; i5 < 10; i5++) {
str4 += "xxxxxx";
}
str3 += str4;
}
str2 += str3;
}
str1 += str2;
}
str += str1;
}
ومع ذلك، فإن النهج المذكور أعلاه قد لا يكون الأفضل! إذا كانت المعلومات التي نحتاج إلى إرسالها بتنسيق XML (في الواقع، في معظم الحالات، يمكننا محاولة تجميع المعلومات المراد إرسالها بتنسيق XML)، فيمكننا أيضًا العثور على طريقة أكثر كفاءة وأنيقة - باستخدام كائنات DOM للتجميع شخصيات بالنسبة لنا سلسلة. تستغرق الفقرة التالية 0.890 ثانية فقط لتجميع سلسلة بطول 950015.
/* استخدم كائنات DOM لتجميع المعلومات - الوقت المستغرق: 0.890 ثانية*/
فار xmlDoc;
إذا (نوع المتصفح == BROWSER_IE) {
xmlDoc = new ActiveXObject("Msxml.DOMDocument");
}
آخر {
xmlDoc = document.createElement("DOM");
}
var root = xmlDoc.createElement("root");
لـ (var i = 0; i < 50000; i++) {
var العقدة = xmlDoc.createElement("data");
إذا (نوع المتصفح == BROWSER_IE) {
Node.text = "xxxxxx";
}
آخر {
Node.innerText = "xxxxxx";
}
root.appendChild(node);
}
xmlDoc.appendChild(root
var str);
إذا (نوع المتصفح == BROWSER_IE) {
str = xmlDoc.xml;
}
آخر {
str = xmlDoc.innerHTML;
}
تجنب تسرب الذاكرة لكائنات DOM.
يعد تسرب الذاكرة لكائنات DOM في IE مشكلة غالبًا ما يتجاهلها المطورون. ومع ذلك، فإن العواقب التي يجلبها خطيرة للغاية! سيؤدي ذلك إلى استمرار ارتفاع استخدام ذاكرة IE، وتباطؤ سرعة التشغيل الإجمالية للمتصفح بشكل ملحوظ. بالنسبة لبعض صفحات الويب المسربة بشكل خطير، سيتم مضاعفة سرعة التشغيل حتى لو تم تحديثها عدة مرات.
تتضمن نماذج تسرب الذاكرة الأكثر شيوعًا "النموذج المرجعي الدوري" و"نموذج وظيفة الإغلاق" و"نموذج ترتيب إدخال DOM". بالنسبة لنموذجي التسرب الأولين، يمكننا تجنبهما عن طريق إلغاء الإشارة عند إتلاف صفحة الويب. أما بالنسبة لـ "نموذج ترتيب إدراج DOM"، فيجب تجنبه عن طريق تغيير بعض عادات البرمجة الشائعة.
يمكن العثور على مزيد من المعلومات حول نموذج تسرب الذاكرة بسرعة من خلال Google، ولن تشرح هذه المقالة الكثير من التفاصيل. ومع ذلك، أوصي هنا بأداة صغيرة يمكن استخدامها للعثور على تسربات ذاكرة صفحة الويب وتحليلها - Drip. الإصدار الأحدث الحالي هو 0.5، وعنوان التنزيل هو http://outofhanwell.com/ieleak/index.php.
التحميل المجزأ وتهيئة الصفحات المعقدة بالنسبة لبعض الواجهات في النظام المعقدة حقًا وغير الملائمة لاستخدام IFrame، يمكننا تنفيذ التحميل المجزأ. على سبيل المثال، بالنسبة لواجهة علامة تبويب متعددة الصفحات، يمكننا أولاً تنزيل الصفحة الافتراضية لعلامة التبويب متعددة الصفحات وتهيئتها، ثم استخدام تقنية AJAH (JavaScript وHTML غير المتزامنة) لتحميل المحتوى بشكل غير متزامن في صفحات علامات التبويب الأخرى. وهذا يضمن إمكانية عرض الواجهة للمستخدم في المقام الأول. قم بتوزيع عملية التحميل للواجهة المعقدة بأكملها في عملية تشغيل المستخدم.
استخدم GZIP لضغط حركة مرور الشبكة.
بالإضافة إلى التحسينات على مستوى التعليمات البرمجية المذكورة أعلاه، يمكننا أيضًا استخدام GZIP لتقليل حركة مرور الشبكة بشكل فعال. في الوقت الحاضر، تدعم جميع المتصفحات الشائعة بالفعل خوارزمية GZIP، وغالبًا ما نحتاج فقط إلى كتابة كمية صغيرة من التعليمات البرمجية لدعم GZIP. على سبيل المثال، في J2EE، يمكننا استخدام التعليمات البرمجية التالية في عامل التصفية لتحديد ما إذا كان متصفح العميل يدعم خوارزمية GZIP، ثم استخدام java.util.zip.GZIPOutputStream لتنفيذ إخراج GZIP حسب الحاجة.
/* رمز لتحديد كيفية دعم المتصفح لـ GZIP*/
سلسلة ثابتة خاصة getGZIPEncoding(HttpServletRequest request) {
String AcceptEncoding = request.getHeader("Accept-Encoding");
if (acceptEncoding == null) return null;
AcceptEncoding = AcceptEncoding.toLowerCase();
إذا (acceptEncoding.indexOf("x-gzip") >= 0) يُرجع "x-gzip";
إذا (acceptEncoding.indexOf("gzip") >= 0) يُرجع "gzip";
عودة فارغة؛
}
بشكل عام، يمكن أن تصل نسبة ضغط GZIP لـ HTML وJSP إلى حوالي 80%، كما أن فقدان الأداء الذي يسببه على الخادم والعميل لا يكاد يذكر. بالإضافة إلى عوامل أخرى، فإن مواقع الويب التي تدعم GZIP قد توفر لنا 50% من حركة مرور الشبكة. لذلك، يمكن أن يؤدي استخدام GZIP إلى تحسينات كبيرة في أداء التطبيقات التي لا تكون فيها بيئة الشبكة جيدة بشكل خاص. باستخدام Fiddler، أداة مراقبة HTTP، يمكنك بسهولة اكتشاف كمية بيانات الاتصال على صفحة الويب قبل وبعد استخدام GZIP. عنوان تنزيل Fiddler هو http://www.fiddlertool.com /fiddler/
يعد تحسين أداء تطبيقات الويب في الواقع موضوعًا كبيرًا جدًا. نظرًا لضيق المساحة، لا يمكن لهذه المقالة سوى تغطية عدد قليل من التفاصيل، كما أنها غير قادرة على أن تظهر لك بشكل كامل طرق تحسين هذه التفاصيل. آمل أن تتمكن هذه المقالة من جذب انتباه الجميع إلى تطبيقات الويب، وخاصة تحسين الأداء من جانب العميل. بعد كل شيء، تقنيات البرمجة من جانب الخادم معروفة للجميع منذ سنوات عديدة، ولا توجد إمكانية كبيرة لاستغلال الأداء من جانب الخادم. يمكن أن تؤدي تحسينات الطريقة من جانب العميل في كثير من الأحيان إلى تحسينات مفاجئة في الأداء.