PDA

View Full Version : مبتدی: تعریف متغیر و مدیریت حافظه



kolibri
چهارشنبه 11 اردیبهشت 1398, 11:16 صبح
سوال در مورد مدیریت حافظه دارم.
فرض کنید یک متد به صورت مداوم (مثلا در یک حلقه یا با استفاده از یک تایمر) فراخوانی می شود، یا اصلا در درون یک حلقه با تکرار بسیار بالا، پردازشی صورت میگیرد و نتیجه رو باید در درون یک متغیر بریزم.
وقتی حلقه در حال اجراست، میزان استفاده از رم به صورت تساعدی بالا می رود و هیچ گاه از اطلاعات قبل پاک نمی شود.
بهنرین حالت برای ایجاد یک متغیر که در یک حلقه پر می شود چی هست؟

من از دو روش استفاده کردم ولی همچنان همین مشکل رو داشتم.
1. متغیر رو بیرون از حلقه یا متد تعریف کردم.
2. متغیر رو در درون حلقه یا متد تعریف کردم.

متغیر هم رشته با حجم بالا است و چیز خاصی نیست. :لبخند:

asiatec
چهارشنبه 11 اردیبهشت 1398, 12:44 عصر
هرجا کارتون با متغیر تموم میشه مقدار نال بدین بش

kolibri
چهارشنبه 11 اردیبهشت 1398, 13:24 عصر
هرجا کارتون با متغیر تموم میشه مقدار نال بدین بش
فکر نکنم نال کردن کاری از پیش ببره، چون همون مقدار فضار اشغال میشه به نظرم (غیر از استینگ)، مثلا شما یه متغیر int ایجاد کنید، چ 0 بذارید و چه 112131321، یه حجم از رم رو اشغال می کنند.

farhad_shiri_ex
چهارشنبه 11 اردیبهشت 1398, 14:20 عصر
فکر نکنم نال کردن کاری از پیش ببره، چون همون مقدار فضار اشغال میشه به نظرم (غیر از استینگ)، مثلا شما یه متغیر int ایجاد کنید، چ 0 بذارید و چه 112131321، یه حجم از رم رو اشغال می کنند.

به هر حال CLR نوع مقداری را در stack تعریف میکنه بنابراین در زمان تعریف مقدار حافظه لازم مثلا همون 4 بایت را رزرو میکنه حالا مقدارش هرچی میخواد باشه! چه 0 باشه وچه عدد 1-232
به نظرم بهتر بود که سورس مورد نظرتون را اینجا قرار می دادید! به نظرم دوتا راه حل داره!
1- اگر مصرف بهینه حافظه خیلی مهم هست! که بهتره از کد های unsafe به زبان ++C استفاده کنید.
2- می توانید حافظه لازم برنامه را روی heap تعریف کنید.
اگر شما در یک حلقه دارید داخل یک رشته هربار اطلاعاتی مینویسید به هرحال چه داخل حلقه و چه خارج از حلقه باید از این رشته اطلاعات استفاده کنید و مجددا رشته را خالی کنید قطعا می دونید که رشته ها آرایه هایی از بایت هستند و نکته دیگر هم اینکه در سی شارپ حتما بهتر هست که از stringBuilder استفاده کنید اونهم به این علت که کلاس string به صورت immutable تعریف شده در صورتی که قصد داشته باشید به رشته بایت جدیدی اضافه کنید CLR مجددا یک شی جدید و سازنده کپی را فراخوانی میکند که کار بهینه ای نیست به همین علت از کلاس stringBuilder استفاده کنید.
بنابراین اگر در یک حلقه در صورتی که تعریف ومقداردهی و عملیات بازپس گیری منابع چه توسط برنامه نویس و چه توسط GC به درستی انجام بشه افزایش تصاعدی استفاده از حافظه کمی غیر معقول به نظر میرسه اگر اینچنین هست باید سورس را حتما Trace کنید و به Unboxing / Boxing و عملیاتهای رشته ای و ... توجه داشته باشید.

kolibri
چهارشنبه 11 اردیبهشت 1398, 15:02 عصر
به هر حال CLR نوع مقداری را در stack تعریف میکنه بنابراین در زمان تعریف مقدار حافظه لازم مثلا همون 4 بایت را رزرو میکنه حالا مقدارش هرچی میخواد باشه! چه 0 باشه وچه عدد 1-232
به نظرم بهتر بود که سورس مورد نظرتون را اینجا قرار می دادید! به نظرم دوتا راه حل داره!
1- اگر مصرف بهینه حافظه خیلی مهم هست! که بهتره از کد های unsafe به زبان ++C استفاده کنید.
2- می توانید حافظه لازم برنامه را روی heap تعریف کنید.
اگر شما در یک حلقه دارید داخل یک رشته هربار اطلاعاتی مینویسید به هرحال چه داخل حلقه و چه خارج از حلقه باید از این رشته اطلاعات استفاده کنید و مجددا رشته را خالی کنید قطعا می دونید که رشته ها آرایه هایی از بایت هستند و نکته دیگر هم اینکه در سی شارپ حتما بهتر هست که از stringBuilder استفاده کنید اونهم به این علت که کلاس string به صورت immutable تعریف شده در صورتی که قصد داشته باشید به رشته بایت جدیدی اضافه کنید CLR مجددا یک شی جدید و سازنده کپی را فراخوانی میکند که کار بهینه ای نیست به همین علت از کلاس stringBuilder استفاده کنید.
بنابراین اگر در یک حلقه در صورتی که تعریف ومقداردهی و عملیات بازپس گیری منابع چه توسط برنامه نویس و چه توسط GC به درستی انجام بشه افزایش تصاعدی استفاده از حافظه کمی غیر معقول به نظر میرسه اگر اینچنین هست باید سورس را حتما Trace کنید و به Unboxing / Boxing و عملیاتهای رشته ای و ... توجه داشته باشید.

سلام و تشکر بابت پاسخ گویی، این کدی هست که دارم:
private IResult<MediaList> media;
private string json;

private async void GetData(object state)
{
Debug.WriteLine(DateTime.Now);
media = await api.GetUserMediaAsync("ra.sad");
json = JsonConvert.SerializeObject(media.Value);
Debug.WriteLine(json);
}
این متد به وسیله تایمر برای گرفتن مدیای جدید از سایت مورد نظر فراخوانده می شود.
var stateTimer = new Timer(GetData);

stateTimer.Change(0, 300000);

farhad_shiri_ex
چهارشنبه 11 اردیبهشت 1398, 15:26 عصر
سلام و تشکر بابت پاسخ گویی، این کدی هست که دارم:
private IResult<MediaList> media;
private string json;

private async void GetData(object state)
{
Debug.WriteLine(DateTime.Now);
media = await api.GetUserMediaAsync("ra.sad");
json = JsonConvert.SerializeObject(media.Value);
Debug.WriteLine(json);
}
این متد به وسیله تایمر برای گرفتن مدیای جدید از سایت مورد نظر فراخوانده می شود.
var stateTimer = new Timer(GetData);

stateTimer.Change(0, 300000);
الان همین غیرهمزمان کردن متد خودش مستعد افزایش بار حافظه هست! یعنی رکویست هایی که برای سرور ارسال میکنید نتیجه برگشت داده میشود! حالا تصور کنید یک یا چند رکوئست موفق نباشد و در صف قرار داشته باشد خوب دراینصورت افزایش بار حافظه دیگه ربطی به تعریف متغییر نمی تونه داشته باشه!
ولی به هرحال همانطور که عرض کردم بهتره که متغییر رشته ای json را بعد از نمایش در Debug خالی کنید! ویا بهتره که این متغیر را static تعریف کنید.

kolibri
چهارشنبه 11 اردیبهشت 1398, 15:37 عصر
الان همین غیرهمزمان کردن متد خودش مستعد افزایش بار حافظه هست! یعنی رکویست هایی که برای سرور ارسال میکنید نتیجه برگشت داده میشود! حالا تصور کنید یک یا چند رکوئست موفق نباشد و در صف قرار داشته باشد خوب دراینصورت افزایش بار حافظه دیگه ربطی به تعریف متغییر نمی تونه داشته باشه!
ولی به هرحال همانطور که عرض کردم بهتره که متغییر رشته ای json را بعد از نمایش در Debug خالی کنید! ویا بهتره که این متغیر را static تعریف کنید.
برای اشکال اول، یک تایم اوت در نظر گرفتم که بعد از گذشت زمانی، ریکوئست کنسل بشه.
اما مورد دوم، متشکرم.

farhad_shiri_ex
چهارشنبه 11 اردیبهشت 1398, 17:02 عصر
اما مورد دوم، متشکرم.
خواهش میکنم دوست عزیز!