PDA

View Full Version : مشکل با indy ها و تعداد thread ها در خصوص قفل شدن برنامه



dadvand
پنج شنبه 30 تیر 1384, 13:14 عصر
با سلام
ما یک برنامه سرور داریم و یک برنامه کلاینت که روی حدود 40 تا سیستم اجرا است . در برنامه سرور ما به ازای هر کلاینت وصل شده 2 تا thread میسازیم (این کار توسط خود indy ها است) و خود برنامه سرور هم 7-8 تا thread معمولا غیرفعال داره . در حالت عادی ما حدود 90 تا thread داریم .
مشکل ما اینجاست که برنامه سرور هر از چند گاهی که زمانش مشخص نیست قفل میکنه آیا ممکنه از تعداد زیاد thread ها باشه (در ضمن این thread ها از یک clientdataset به صورت مشترک استفاده میکنند که در همه جا ما نواحی بحرانی تعریف کردیم برای جلوگیری از تداخل کار thread ها).
سیستمی که سرور روش است cpu 1.6ghz است .

با تشکر

brians2000
پنج شنبه 30 تیر 1384, 13:43 عصر
سلام...

:) ابتدا این سیستم شما گازوییلیه! :)) ... شما به طور قطع از دست دادن حافظه رو دارید ... چنین چیزی مدیریت دقیق می خواهد ... برای استفاده از یک کلاینت دیتا ست مشترک باید حتما مدیریت منطقه بکنید به این معنی که هرجا با این دیتا بیس کار دارید حتما محوطه critical رو مشخص کنید و حتما هم به این صورت که حتما خروج از اون لحاظ بشه ! و من احتمال می دهم شما یک جا اونرو در ترای فاینالی تعریف نکردید یعنی یکجا این ثرید از محوطه بحرانی خارج نمیشه (قطعا همینطوره) در حقیقت شما یکجا لاست خروجی دارید.... و بگردید برای جایی که این خروجی از محوطه بحرانی در ترای فاینالی تعریف نشده پیداش می کنید! !!! تنها در این حالت است که چنین اتفاقی می افتد! در ضمن: ثریدها در ایندی تا اونجا که من می دونم در زمان اتصال مثلا ورکتایم وجود دارند و بعد ترمینیت می شوند! پس شما کاری در ایندی نکرده اید و اون ثرید های محترمه کاری به کار شما ندارند و اگر دستی مدیریت کردید که باید ترمینیت بکنید و حافظه رو هم خالی بکنید و همانطور که گفتم دو حالت هست:
شما از دست دادن حافظه دارید.
یا جایی محوطه بحرانی ازش خارج نشدید یعنی در ترای فاینالی تعریف نکردید و در نتیجه عجیبه برنامه شما نیمساعت بدون هنگ کردن کار می کنه! مشخصه : زمانی که شما از این محوطه خارج نشید دیگه چیزی اجرا نمیشه و ثرید های اصلی هم پنچر می شوند. در هر وضع: زمانی که ثریدی در حال اجرا نیست اصلا ثریدی وجود نداره که شما تعریفش کنید :)) فقط جا تو حافظه گرفته یه اسمه!

brians2000
پنج شنبه 30 تیر 1384, 13:47 عصر
ثرید رو بهتر از من معنیش رو می دونید: زمانی که می خواهید برنامه شما در چند موضع (ترجمه اش چجوریه) اجرا شود از آن استفاده می کنید به محض اجرا از مکان شروع کد مربوطه سی پی یو شروع به اجرا کد می کند و محوطه جدیدی رو برای اون تعریف می کند که ثرید بتواند از رجیسترهای مجزا و استک مجزا استفاده کند به عبارت بهتر یک اجرا از یک محوطه! بدون این موضوع اصلا ثریدی وجود ندارد اگر قرار بود مثلا 20 هزار نفر به یک سرور وصل شوند و 20000 ثرید روی آن همزمان اجرا شود که سرور فوت می شد! از این 20000 هزار نفر ممکنه هر 50 نفر یک ثرید رو تو یک لحظه ایجاد کنند پس متوسط عمر اون بسته به زمانیه که کلاینت درخواست داده!

نکته مهم اینه که : ثریدها در هر سی پی یو بین 16 تا حداکثر 64 تا باشند... ولی برای باگ خودتون : به اون دوتا توضیح من مراجعه کنید فکر کنم به دومی می رسید! محوطه بحرانی از دست رفته! (ترجمه ای!!!)

در ضمن: آقای کرامتی این وی بی که نصب کردید :)) عجیب روی حرف ی حساسیت داره.

brians2000
پنج شنبه 30 تیر 1384, 13:58 عصر
خوب... ببینیم این زیون!!!! چرا اینقدر کشش بالاست (همچینم بالانیست ای ام دی پوز زده! )

خوب :)) گفتیم که هرکدوم یک سری رجیستر می خواهند و یک استک و... :)) خوب... زمانی که یک محوطه کد به این صورت اجرا میشه مشخصا استک بیشتری می خواهد و برای اینکه سی پی یو به سرعت برسد و بتواند حجم بیشتری را در دسترس داشته باشد (هی از حافظه نخونه) کش بیشتری که دارد به دادش می رسد و :)) فرض کنید مثلا 500 تا ثرید همزمان میشه... ولی مشخصا حجم مشخصی از یک اجرا به این صورت جواب می ده و بعد از مدتی سیستم رو در حدی کند می کنه که غیر قابل استفاده میشه (کسی تاحالا با سرور فیفا بازی کرده؟؟؟ بعضی از ادمین ها نصفه شبی اینکارو می کنند ! ) ... خوب... این مشخصه. یک نفر اگر 8 دست هم داشته باشد بالاخره ظرفیتی دارد و باید دستش خالی بشه که یه چیزی رو بگیره!

brians2000
جمعه 31 تیر 1384, 01:19 صبح
دو تا سوال: تو یه همچین حالتی :
1- شما باید محوطه بحرانی رو استثینائا! عمومی تعریف کنی!!!!!!!!!!!!!!!! در حقیقت لاک ها عمومی تعریف می شوند و احتمالا تو محلی توی پراسیجر تعریف کردی که مثل اینه که اصلا نیست !!!

http://www.pergolesi.demon.co.uk/prog/threads/Ch9.html

اینو یه دید بزن... !!! جالبه... :) خوب تو می خواهی یک لاک محلی باشی یعنی خودش خودشو بلاکه؟؟؟؟؟ میشه مگه!

احتمال دیگه همونطور که گفتم عدم خروج شما از محوطه بحرانی است ...
در هر وضع: در زمانی که یک ثرید در حالت انتظار است اجرایی ندارد... و بعد از محوطه انتظار مجددا اجرا شروع میشه !
و یک نکته: بگذار ایندی کار خودشو بکنه خیلی خوب تعریف شده...
ولی در مقابل هر ثریدی که ایجاد می شه باید یه جلسه هم برای دیتا بیس ایجاد شه که بتونه بازگشت هارو توش ذخیره کنه و یا با محوطه بحرانی عمومی اونرو مدیریت کنی .
:)) شرمنده فکر کنم از دستم شاکی شده باشی ولی به نظر من اینکار هارو باید خوند در موردش و بعد اجرا کرد چون فکر کنم ناچار بشی کل برنامه تو تریس کنی تا یه جا همین سه تا ایراد در بیاد! معمولا (و همیشه) لاکها عمومی تعریف می شوند و یا برای بازدهی بهتر منطقه ای ... البته اولی کم دردسر تره و دومی ... به نظر من هیچ تاثیری نداره توی سرعت ولی اگر محوطه بحرانی تو بخواهد طول بدهد کارش رو ثرید های دیگر که از محوطه اشتراکی بحرانی استفاده می کنند هم لاک می شوند ...

brians2000
جمعه 31 تیر 1384, 01:43 صبح
نکته مهم: در استفاده از محوطه های بحرانی اگر خیلی می خواهید کارتون رو دقیق بنویسید و محوطه بحرانی شما ممکنه تاخیر داشته باشه اونرو منطقه بندی یعنی : هر کلاس خودشو لاک کنه ولی می تونید از محوطه بحرانی عمومی هم در برنامه هایی که تاخیر ندارند استفاده کنید.
محوطه بحرانی غیر عمومی که ایجاد میشه مثل اینه که وجود نداره... در حقیقت شما محوطه بحرانی رو باید باز نگه دارید که مقادیرش حفظ بشوند در غیر اینصورت ایجاد و از بین بردن اون کار صحیحی نیست.
حتما ورودی و خروجی محوطه بحرانی را در محوطه ترای فاینالی انجام بدهید : باید خروج انجام بشود و گرنه لاک از دست رفته و برنامه هنگ می کنه!
دو یا سمپل بنویسید که طرز برخورد اونرو درک کنید.
در برنامه های مالتی ثرید لطفا بخصوص در ایندی از چیزی که خروجی نامطئن حالا هرچی (مطمئن! ) داشته باشه روی صفحه مثلا یک گرید برای دیتا بیسی که زمان تغییر کی ست باعث ریفرش صفحه میشه و باعث ایجاد ثرید مضاعف میشه در داخل ثرید خودداری کنید مثلا توی ثرید ها ننویسید : لیبل 1 کپشن مساوی سلام! از دیتا بیس هاتون هیچچچچچ عملکرد نمایشی روی صفحه سرور نداشته باشید!
از دست دادن حافظه رو روش دقت کنید.
بگذارید ترمینیت ها درست انجام بشه... ایندی خودش اینکارو به شدت عالی مدیریت م کنه.
مدیریت حافظه رو درست انجام بدهید!
نوع تعریف محوطه بحرانی مشخصه: مثلا یا عمومی (همه چی یه جا) که خوب.. بد نیست و برای بانک اطلاعاتی هر کدام یک دونه مشخصا برای اون لازمه که تعریف عمومی بشه... سعی کنید از جلسه ها استفاده کنید و سژن های دیتابیس رو ایجاد کنید که از محوطه اشتراکی استفاده نشه .
خیلی هاتون به اینتراوب فحش می دهید که چرا ای دو او مثلا کار نمی کنه؟ توی فرم سرور کنترل لطف کنید ایجاد کننده کام رو مالتی ثرید تعریف کنید. بعد توی حرف به صورت مجزا از اون استفاده کنید... ! نترسید... برای اینکار ویندوز و طراحان دلفی و ایضا مایکروسافت قبلا فکر کرده و بعد از ایجاد یک کانکشن بعدی ها سریع خواهند بود... !!!
توی ایندی بازهم تاکید می کنم: هیچ چیزی که از جی دی آی استفاده کنه رو دست نزنید... از گرید ها دیتا بیس بسته به بانک اطلاعاتی استفاده نکنید.
برنامه های برودکاستر مثلا صدا یا چت میتونند در صورت استفاده از یو دی پی یا نان بلاکینگ تک خطه باشند به عبارت بهتر : اگردرست بنویسید برنامه رو تا 80 مگابیت!!! که حجم زیادیه می تونید رو یه سی پی یو جواب بگیرید و اجازه بدید ویندوز خودش مدیریت ارسال رو به عهده بگیره ولی به غیر از اون چیزهایی که تاخیر دارند (غیر از آی ام و منتشرکننده ها ) باید مالتی ثرید نوشته بشوند : ارسال فایل... سرورهای اچ تی تی پی ... کلا چیزهایی که فاقد جواب آنی نیستند باید اینطور تعریف بشوند.

زیاد از محوطه بحرانی در صورت عدم ضرورت استفاده نکنید.. در صورت استفاده بیش از حد کلا سرعت رو به حد افتضاحی پایین میاره...
همونطور که گفتم... آِی ام ها و منتشر کننده ها مثلا یه چت روم با صدا می تونه در صورتی که از ارسال آنی استفاده کنه تک ثرید باشه و نگران سرعت نباشید... ولی اگر کوچکترین پردازش غیر آنی دارید باید از نوع مالتی ثرید استفاده کنید.
در مقابل هر کانکشن در ایندی یه ثرید ایجاد میشه که در حالت انتظار خواهد ماند ...

brians2000
جمعه 31 تیر 1384, 02:08 صبح
و در انتها:

من خودم خیلی اشتباه می کنم.. خیلیها فکر می کنند من دیگه همه کار رو راحت انجام می دهم... ولی دقیقا برعکسه... من توی خیلی از کارها تنبلم بلد بودن رو خوب که مشخصه هرکسی بانک اطلاعاتی رو بلده ولی من چون از اول گرایش چیز دیگه رو داشتم (طراحی انژین ها گرافیک) اکثر برنامه هایی که فروختم تو همین مایه ها بوده... چند وقتیه که تو کار سیستم های اینجوری هستم ولی بازهم خوب... مثلا من تو طراحی برنامه ام از تجربه دیگران استفاده می کنم خیلی وقتها اینترنت رو می گردم که ببینم چی صحیحه؟ و تست می کنم کد رو که درکش کنم چون با حرف به جایی نمیشه رسید.... گاهی که تو کارها دخالت می کنم توی نوع طراحی اونهاست که روز بروز محتاط تر می شم... یعنی قبل یک اجرا یه پروو می کنم... برای بانکهای اطلاعاتی توی سیستمی که دارم بطور کلی بنا به نوع مشتری پشتوانه رو 8 نوع مختلف قرار دادم یعنی که مشتری و خودم رو وابسته به اراکل یا دی بی آی سم نکردم... دی بی آی سم توی جستجوی رندم توی حافظه راه حل عالی ای هستش به خاطر سادگی کار و در عین حال سرعت بالا حتی در حجم بالای اطلاعات ولی همین دی بی آِی سم در زمانی که در سرور می خواهد جواب بازدهی سنگین رو بدهد مشکل دارد و بهتره که از اراکل استفاده بشه ولی این اراکل زمانی که مثلا یه سرور ورودی می نویسید که حجم بالایی رو باید جواب بده می تونه جای خودش رو به حتی دی بی آی سم بده چون در این حالت چیزی که می خواهید جستجوی شانسی سریع است : مثلا : رایان رو پیدا کن! احمد رو پیدا کن! خوب... :) شما در نظر بگیرید سرور یاهو چجوریه؟ یاهو الان 9500 ورودی در ثانیه داره (نمی دونم درسته آمار یا نه؟ ) خوب... :)) ... معمولا چنین کاری فرق عمده داره ! نمی گم اراکل جواب نمی ده ولی اراکل کارش مثلا گرفتن گزارش از حجم بالای اطلاعات و یا کوئری گرفتنه و :)) برای یه دونه رکورد که می خواهید آی دی رو چک کنید مثلا تو این حجم بالا هزینه سخت افزار رو بالا می بره و شاید اصلا کارش این نباشه! البته اینهم هست که توی مثلا 50 تا در دقیقه چیزی نیست... این حجم سیستم اختصاصی رو می طلبه...
توی سیستم آفلاینی که من تعریف کردم توی برنامه ام کار رو تقسیم کردم :
اولا از بانک اطلاعاتی استفاده نکردم! از تعقیب خطی و آدرس دهی مطلق فیزیکی استفاده کردم
تعداد هاردهارو داینامیک گرفتم که ذخیره روی اونها داینامیک باشه .

brians2000
جمعه 31 تیر 1384, 02:09 صبح
در همه جا یک اصل رو رعایت کردم تعقیب خطی .......................... یعنی دقیقا اینطوریه که آفلاین ها توی یک فایل ردیف ذخیره می شوند که دسترسی به اونها به طرف جلو باشه ... و لیستها همدیگرو تعقیب می کنند... یه آفلاین 50 کاراکتری 64 بایت میگیره ... یعنی دوتا 64 بیتی تعقیبی که قبلی و بعدی رو مشخص می کنند... پس مثلا اگر یوزر 100 یه چیزی رو بفرسته من اونرو رو هم پشته می کنم... بعدا یوزر دومی که اومد اونرو خطی بهش پس می دهم.... متاسفانه این کارها دردسر داره و مثلا مثل همین سایت نیست که بگیم آقا میریزم تو بانک اطلاعاتی بعد کوئری می گیرم! اصلا چنین چیزی تو این حجم کار معنی نداره! به عبارت بهتر بانک اطلاعاتی وجود نداره که بتونه اینرو به این سادگی ها جواب بده. .............سیستمی که من استفاده کردم دقیقا مشابه یاهو هستش... همون سیستم دقیقا اینجا هم تکرار شده و ....

در نهایت :) ... اینکار رو بر اساس نیاز بنویسید... از ما گفتن!

dadvand
شنبه 01 مرداد 1384, 11:49 صبح
سلام :
آقای brians2000 خیلی منون از پاسخهاتون . خیلی کامل و جامع بود.
ولی در مورد برنامه ما تمام مواردی که گفته بودید کاملا رعایت شده است ضمن اینکه ما از درون thread ها به بانک اطلاعاتی دسترسی نداریم. در ضمن ما ذر برنامه سرور از دو تا tcpserver استفاده کردهایم که از یکی برای انتقال اطلاعات با حجم بالا و نامعلوم استفاده مکنیم مثل فایلها و از دیگری برای انتقال پیامها ودستورات که یک رکورد با حجم ثابت است.
پیامهای کوتاه در سیستم مرتب رد بدل میشوند تقریبا ثانیه ای 70 تا 100 تا که البته چون پیامها کوتاه هستند این کار سریع انجام میشه و در ضمن برای عدم تداخل همیشه از ناحیه بحرانی استفاده کرده ایم
یک تیکه از کد رو براتون می نویسم :

Unit MainU;
\\form definitions

TMSGRecord = record
Command:string[100];
.....
end;

var
CS:TRTLCritialSection;

procedure frmMain.OnCreate(...);
begin
InitializeCrititialSection(CS);
end;

procedure frmMain.OnDestroy(...);
begin
DeleteCrititialSection(CS);
end;

procedure frmMain.TCPServerMSGOnExecute(T:TidPeerThread);
var
MSG:TMSGRecord;
IntIP:LongWord;
begin
T.Connection.ReadBuffer(MSG,SizeOf(TMSGRecord));
IntIP:=IPToInteger(T.Connection.socket.binding.pee rIP);

if MSG.Command = '...' then
begin
EnterCriticialSection(CS);
try
if cdsClients.Locate('IP',IntIP,[]) then
begin
...:=cdsClientsStatue.Statue;
cdsClients.Edit;
....
cdsClients.post;
end;
finally
LeaveCriticialSection(CS);
end;
end
else if MSG.Command = '...' then
begin

end
.
.
.


end;



end;

این سیستم روی شبکه بزرگ اجرا میشود لذا کاملا بای قابل اطمینان باشه که برای آن ما در بسیاری از نقاط برنامه از بلوک های try except هم استفاده کردهایم به عنوان مثال قطع شبکه رفتن برق استفاده شدن یک فایل توسط برنامه دیگر و ...

در مورد ایندی ها مدیریت حافظه را خودشان انجام میدهند و ما به صورت دستی آنهارا مدیریت نمیکنیم.
در ضمن در مورد memory leak هم که گفته بودید برنامه با آن مواجه نمیشود و در زمانی هم که ما از تمام رکوردهای موجود 50000 تا گزارش میگیریم مقدار حافظه مصرفی حداکثر بین 30 تا 40 مگابایت است که چون سیستم ما 512 مگ رم دارد هیچگاه با کمبود حافظه مواجه نمیشود.

البته ما این سیسم را در خانه که روی دوتا سیستم ساعتها امتحان کره ایم و هیچوقت با مشکل hang مواجه نشدیم و این مشکل در سایت که 40 تا pc دارد پیش می آید. و در ضمن زمان قفل کردن هم مشخص نیست و گاهی سیستم چندین ساعت بدون مشکل کار میکند.

در مورد cpu usage برنامه هم در اکثر مواقع task manager صفر را نشان میدهد زیرا اکثر thread ها در حالت معمول غیر فعالند.البته همان طور که قبلا گفتم هر client تقریبا در هر 25 ثانیه دو پیام میفرستد که چون پیامها کوتاه هستند 200 بایت این کار به سرعت انجام میشود و در اکثر مواقع بیکارند.

البته در زمانی هم که سیستم قفل میکند cpu usage برنامه صفر است.

ما در تماسی که با یکی دیگر از برنامه نویسان که عضو سایت هم هستند سه منبع مشکل را گفتند به این ترتیب :
یک : از یک antifreeze استفاده کنید . که چون برنامه ارسال هر چیزی را از داخل thread انجام میدهد این مورد منتفی است.
دو : اشکال در کد برنامه . که این مو رد محتمل است.
سه : اشکال در شبکه (در شبکه از سوییچ استفاده میشود). آیا به نظر شما این مورد برای ما محتمل است.
چون این بنده خدا (tuska) گفته که قبلا با این مشکل مواجه شده است.

Touska
شنبه 01 مرداد 1384, 13:45 عصر
آره من با این مشکلات قبلا مواجه شده ام.

brians2000
یک شنبه 02 مرداد 1384, 09:06 صبح
من چند تا مشکل رو گفتم...
حدس می زنم مشکل شما سخت افزاری باشه ولی در مورد کارت شبکه این موضوع کمی بی ربطه :
دوستی که گفتند آنتی فریز لطف کردند ولی آنتی فریز! ربطی به سرورهای ایندی نداره و البته ایشون استاد ما هستند ولی با شما مزاح فرمودند اون بیچاره مال کلاینت هاست فقط.
اشکال سخت افزاری محتمل ترین مشکل موجود است!
ربطی بین قطع وصل و ایراد شبکه و هنگ کردن یک برنامه وجود ندارد.
ایندی در حال حاضر یکی از کم ایراد ترین سورسهای موجود برای نرم افزارهای سرور است.

brians2000
یک شنبه 02 مرداد 1384, 09:15 صبح
مشکل شما سخت افزاری می تواند باشد ولی داخل کامپیوتر و دوستی که فرموده اند کابل شبکه بفرمایید از کجا چنین منطقی را در آورده اند؟
آنتی فریز هم ربطی به سرورها ندارد و تنها مربوط به کلاینت هاست و ایشان بازهم مزاح فرموده اند.
اشکال شما از رم و یا سی پی یو است بهتر است یک سی پی یو دیگر را امتحان کنید.
احتمال می دهم که شما یک جا عملکرد استفاده از جی دی آی رو داشته باشید .
کلیه عناصر مرتبط با بانک اطلاعاتی و یا هرچیزی را از سرور حذف کنید. گرید های بانک اطلاعاتی و سایر موارد.
گفتم: شما نباید اصلا در بخش سرور روی ثریدی غیر از ثرید اصلی برنامه عملکرد نمایش داشته باشید واضحتر بگویم: هیچ عملی مربوط به نمایش از طریق یا مربوط به ثرید های عزیز ایندی نباید استفاده شود... شما اینکار را می کنید حتما یک جا... این باعث ایجاد خطا می شود.
در ضمن: سی پی یو را عوض کنید حداقل ای ام دی های آتلون 64 بگذارید که کش سی پی یو بتواند پاسخگوی ثرید ها باشد یا پی 4! این کامیپوتر خیلی نحیف است !

یکی از زوار هم قصد دارند (اکانت بنده را پاک کنند و برخورد!!!!!!!!!!! کنند : بنده هم جواب ایشان را دادم اگر اختیار دست ایشان است بهتر است ما اینجا نباشیم! چون واقعا فاجعه بزرگی است !!!!!!!!!

پی نوشت: یکی از دوستان پیغام خصوصی ای دادند به بنده که (دلم< کباب >) شد!