سؤال

أعرف أن هذا السؤال وقد تم به ولكن لدي لمسة مختلفة قليلا على ذلك.عدة قد أشارت إلى أن هذا سابق لأوانه التحسين الذي هو صحيح تماما إذا كنت تسأل لأجل التطبيق العملي و العملي السماء فقط.مشكلتي هي متجذرة في مشكلة عملية ولكن أنا لا تزال غريبة على الرغم من ذلك.


أنا خلق مجموعة من البيانات SQL لإنشاء البرنامج النصي (كما سوف يتم حفظها إلى القرص) إلى إعادة إنشاء مخطط قاعدة البيانات (بسهولة العديد من مئات الجداول وجهات النظر ، إلخ.).هذا يعني ان سلسلة سلسلة هو إلحاق فقط.بـ stringbuilder ، وفقا MSDN, يعمل عن طريق الحفاظ على مخزن مؤقت داخلي (بالتأكيد char []) ، نسخ سلسلة الأحرف إلى ذلك ، إعادة تخصيص مجموعة حسب الضرورة.

ومع ذلك ، فإن قانون بلدي لديه الكثير من تكرار سلاسل ("CREATE TABLE [", "الذهاب ", الخ.) وهو ما يعني أنني يمكن الاستفادة منها يجري اعتقالهم ولكن ليس إذا كنت تستخدم بـ stringbuilder لأنها ستكون نسخ في كل مرة.فقط المتغيرات هي أساسا الجدول أسماء هذه موجودة بالفعل مثل السلاسل في الكائنات الأخرى التي هي بالفعل في الذاكرة.

وبقدر ما أستطيع أن أقول أنه بعد قراءة البيانات في بلدي الكائنات التي تم إنشاؤها التي تحمل معلومات المخطط ثم كل سلسلة معلومات يمكن استخدامها من قبل تتدرب ؟

على افتراض ذلك ، ألن قائمة أو LinkedList من السلاسل تكون أسرع لأنها تحتفظ مؤشرات المعتقلين السلاسل ؟ ثم إنه مكالمة واحدة فقط إلى سلسلة.Concat() واحد تخصيص الذاكرة من السلسلة بأكملها وهذا بالضبط هو طول الصحيح.

قائمة أن تخصيص string[] من المعتقلين مؤشرات قائمة مرتبطة إلى إنشاء العقد وتعديل مؤشرات ، لذا فهي ليست "حرة" أن تفعل ولكن إذا أنا وصل العديد من الآلاف من المعتقلين سلاسل ثم أنها سوف تبدو أنها ستكون أكثر كفاءة.

الآن أعتقد أنني يمكن أن تأتي مع بعض مجريات الأمور على حرف التهم لكل SQL & عدد كل نوع من الحصول على فكرة تقريبية و قبل مجموعة بلدي بـ stringbuilder القدرة على تجنب إعادة تخصيص لها char[] ولكن أود أن تخطى بهامش عادل للحد من احتمال إعادة تخصيص.

حتى في هذه الحالة التي من شأنها أن تكون أسرع للوصول واحد متصلا سلسلة:

  • بـ stringbuilder
  • قائمة<string> من المعتقلين سلاسل
  • LinkedList<string> من المعتقلين سلاسل
  • بـ stringbuilder بسعة ارشادي
  • شيء آخر ؟

كما مسألة منفصلة (قد لا تذهب دائما إلى القرص) أعلاه:الواحد StreamWriter إلى ملف إخراج تكون أسرع بعد ؟ بدلا من استخدام قائمة أو LinkedList ثم يكتب لهم إلى ملف من قائمة بدلا من الأول وصل في الذاكرة.

تحرير: كما طلبت ، الإشارة (.NET framework 3.5) إلى MSDN.يقول: "جديد يتم إلحاق البيانات إلى نهاية المخزن المؤقت إذا كانت غرفة المتاحة ؛ خلاف ذلك, جديد, أكبر العازلة يتم تخصيص البيانات من الأصل العازلة يتم نسخ جديدة العازلة ، ثم بيانات جديدة يتم إلحاق جديدة العازلة." يعني لي شار[] هذا هو realloced لجعلها أكبر (الذي يتطلب نسخ البيانات القديمة إلى تغيير حجم المصفوفة) ثم إلحاق.

هل كانت مفيدة؟

المحلول

الخاص بك مسألة منفصلة, Win32 لديه WriteFileGather وظيفة التي يمكن أن بكفاءة كتابة قائمة من (المعتقلين) السلاسل إلى القرص ولكن من شأنه أن يجعل فرق ملحوظ فقط عند استدعائه بشكل غير متزامن ، الكتابة إلى القرص سوف تلقي بظلالها على جميع ولكن كبيرة للغاية تسلسالت.

الخاص بك السؤال الرئيسي:ما لم يتم التوصل إلى ميغا بايت من النص ، أو عشرات الآلاف من البرامج النصية ، لا تقلق.

هل يمكن أن نتوقع بـ stringbuilder إلى مضاعفة حجم التخصيص على كل تخصيص.هذا يعني تزايد العازلة من 256 بايت إلى 1 ميغا بايت فقط إعادة تخصيص 12 - جيد جدا, بالنظر إلى أن التقديرات الأولية كانت 3 أوامر من حجم قبالة هدف.

مجرد ممارسة بعض التقديرات:بناء منطقة عازلة من 1MB سوف اكتساح حوالي 3 ميغابايت من الذاكرة (1MB المصدر, 1MB الهدف ، 1MB بسبب نسخ خلال realloation).

قائمة مرتبطة تنفيذ الاجتياح حوالي 2MB, (وهذا هو تجاهل 8 بايت / جسم علوي في سلسلة المرجع).إذا كنت تقوم بحفظ 1 ميغابايت من الذاكرة يقرأ/يكتب ، مقارنة نموذجية عرض النطاق الترددي الذاكرة من 10 جيجابت/ثانية و 1MB L2 ذاكرة التخزين المؤقت.)

نعم, قائمة التنفيذ يحتمل أن تكون أسرع ، والفرق أن المسألة إذا كانت مخازن هي أمر من حجم أكبر.

عن أكثر شيوعا حالة الصغيرة السلاسل ، الحسابي مكاسب لا يكاد يذكر ، وسهولة يقابلها عوامل أخرى:أما بـ stringbuilder رمز المرجح في مدونة ذاكرة التخزين المؤقت بالفعل ، قابلة للحياة هدف microoptimizations.أيضا ، وذلك باستخدام سلسلة داخليا يعني لا نسخ في كل حال النهائية سلسلة يناسب الأولي العازلة.

باستخدام قائمة مرتبطة أيضا اسقاط توزيع مشكلة من س(عدد الأحرف) O(عدد أجزاء) - قائمة سلسلة المراجع تواجه نفس المشكلة مثل سلسلة من الأحرف!


لذا المنظمة البحرية الدولية تنفيذ بـ stringbuilder هو الحق في الاختيار الأمثل من أجل قضية مشتركة ، و يحط في الغالب بشكل غير متوقع كبيرة تستهدف مخازن.أتوقع قائمة التنفيذ أن تحط على عدد كبير جدا من قطاعات صغيرة أولا ، الذي هو في الواقع المتطرفة النوع من السيناريو بـ stringbuilder هو محاولة لتحسين.

لا يزال, سيكون من المثير للاهتمام أن نرى المقارنة بين فكرتين ، وعندما يبدأ القائمة أن تكون أسرع.

نصائح أخرى

إذا لم تنفذ شيئا من هذا القبيل لن نبني بـ stringbuilder (أو أي دولة أخرى في المخزن المؤقت الذاكرة الخاصة بك النصي).أود فقط أن تيار إلى الملف الخاص بك بدلا من ذلك ، وجعل جميع سلاسل مضمنة.

هنا مثال البرمجية الزائفة (ليس عبارة صحيحة أو أي شيء):

FileStream f = new FileStream("yourscript.sql");
foreach (Table t in myTables)
{
    f.write("CREATE TABLE [");
    f.write(t.ToString());
    f.write("]");
    ....
}

ثم, سوف تحتاج أبدا في الذاكرة تمثيل السيناريو الخاص بك مع جميع النسخ من السلاسل.

آراء ؟

في تجربتي أنا صحيح المخصصة بـ stringbuilder يتفوق معظم كل شيء آخر على كميات كبيرة من بيانات سلسلة.يستحق إضاعة بعض الذاكرة, حتى, تجاوز التقدير الخاص بك بنسبة 20% أو 30% للحيلولة دون تخصيص.ليس لدي حاليا من الصعب الأرقام إلى تراجع استخدام البيانات ، ولكن نلقي نظرة على هذه الصفحة لمزيد من.

ومع ذلك ، كما جيف مولعا مشيرا, لا قبل الأوان تحسين!

تحرير:كما @كولن بورنيت أشار إلى الاختبارات التي جيف إجراء لا يتفق مع براين الاختبارات ، ولكن نقطة ربط جيف بعد حوالي المبكرة الأمثل في العام.العديد من المعلقين على جيف الصفحة الإشارة إلى القضايا مع الاختبارات.

فعلا StringBuilder يستخدم مثيل String داخليا. String هي في الواقع قابلة للتغيير داخل System الجمعية, وهذا هو السبب StringBuilder يمكن أن يكون بناء على أعلى من ذلك.يمكنك جعل StringBuilder قليلا أكثر فعالية عن طريق تعيين مدة معقولة عند إنشاء مثيل.وبهذه الطريقة سيتم القضاء على/تقليل عدد عمليات تغيير الحجم.

سلسلة تتدرب يعمل السلاسل التي يمكن تحديدها في وقت الترجمة.وبالتالي إذا كنت تولد الكثير من السلاسل أثناء التنفيذ أنها لن تكون المعتقلين إلا إذا كنت تفعل ذلك بنفسك عن طريق الاتصال تتدرب على طريقة السلسلة.

تتدرب ينفعك فقط اذا سلاسل الخاص بك متطابقة.متطابقة تقريبا سلاسل لا تستفيد من التدريب ، لذلك "SOMESTRINGA" و "SOMESTRINGB" سوف يكون اثنين من سلاسل مختلفة حتى لو كانوا معتقلين.

إذا كان كل (أو معظم) من السلاسل كونه متصلا يتم اعتقالهم ، ثم المخطط الخاص بك قد تعطيك دفعة الأداء ، كما أن potentally استخدام ذاكرة أقل ، يمكن حفظ بضعة سلسلة كبيرة من النسخ.

ومع ذلك ، إذا كان أو لم يكن في الواقع يحسن الأداء يعتمد على حجم البيانات التي يتم معالجتها ، لأن التحسن في عوامل ثابتة لا في أمر من حجم الخوارزمية.

الطريقة الوحيدة أن أقول حقا هو تشغيل التطبيق الخاص بك باستخدام كل طرق قياس النتائج.ومع ذلك, إلا إذا كنت تحت الذاكرة كبيرة وضغط بحاجة إلى وسيلة لإنقاذ بايت, لم أكن عناء فقط استخدام سلسلة البناء.

A StringBuilder لا يستخدم char[] لتخزين البيانات ، فإنه يستخدم داخلية قابلة للتغيير السلسلة.وهذا يعني أنه لا يوجد أي خطوة إضافية لإنشاء النهائي السلسلة كما هو عند لسلسلة قائمة السلاسل ، StringBuilder فقط ترجع السلسلة الداخلية العازلة العادية السلسلة.

فإن إعادة تخصيص أن StringBuilder لا زيادة قدرة يعني أن البيانات حسب متوسط نسخ إضافية 1.33 مرات.إذا كنت يمكن أن توفر تقدير جيد على حجم عند إنشاء StringBuilder يمكنك تقليل ذلك حتى furter.

غير أن قليلا من المنظور يجب أن ننظر في ما هو عليه أن كنت تحاول تحسين.ما سوف يستغرق أكثر من مرة في البرنامج الخاص بك هو في الواقع كتابة البيانات إلى القرص ، حتى إذا كان يمكنك تحسين التعامل مع السلسلة أن تكون أسرع مرتين باستخدام StringBuilder (وهو أمر غير مرجح) ، والفرق الكلي سوف لا يزال يكون إلا بنسبة قليلة.

هل تعتبر C++ على هذا ؟ هل هناك مكتبة الفئة التي بالفعل يبني T/عبارات SQL ، ويفضل أن يكون مكتوب في C++.

أبطأ شيء عن سلاسل malloc.فإنه يأخذ 4KB في السلسلة على الأنظمة الأساسية 32-بت.النظر في تحسين عدد من سلسلة الكائنات التي تم إنشاؤها.

إذا كان يجب استخدام C#, أنا أنصح شيئا من هذا القبيل:

string varString1 = tableName;
string varString2 = tableName;

StringBuilder sb1 = new StringBuilder("const expression");
sb1.Append(varString1);

StringBuilder sb2 = new StringBuilder("const expression");
sb2.Append(varString2);

string resultingString = sb1.ToString() + sb2.ToString();

حتى أن الذهاب بقدر ما ترك الكمبيوتر تقييم أفضل مسار إنشاء مثيل الكائن مع حقن التبعية الأطر إذا perf هذا مهم.

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top