PDA

View Full Version : دلیل افت سرعت در اجرای دو حلقه تو در تو در سی شارپ



Behnam6670
چهارشنبه 20 خرداد 1394, 10:55 صبح
سلام دوستان
من رو یه نرم افزاری دارم کار میکنم تو قسمت گزارشاتم یه جا یه گیر کوچولو دارم اونم اینه که یه جایی هست من باید گزارش کارکرد افراد رو تو یه بازه زمانی مشخص نشون.

تعداد افراد 200 نفر
بازه تاریخی 30 روز

حالا وسط این دوتا حلقه کلی محاسبات انجام میشه!!!!!!:لبخند:

اولش که حلقه شروع به کار میکنه سرعت خوبه(تقریبا تا 10 تا پرسنل اول)بعد از این کلا سرعت کم میشه بصورتی که کاملا چشمگیره .

دوستان راه حلی به ذهنشون نمیرسه؟؟؟؟؟

میخوام این دوتا حلقه با سرعت بالا انجام بشن.دوستان اگه بخوان میتونم Team هم بدم تا اگه بتونن راهنمایی کنن.ممنون از شما
09359656582

ali_md110
چهارشنبه 20 خرداد 1394, 11:06 صبح
کدهای حلقه و اینکه از چه روشی استفاده میکنید قرار بدید وگرنه کمکی نمیشه کرد

Behnam6670
چهارشنبه 20 خرداد 1394, 12:58 عصر
foreach (var users in getPersons)
{
totalTime = new totalTimes();
IOProgress.Maximum = lstDate.Count;
IOProgress.Value = 0;
for (int i = 0; i < lstDate.Count; i++)
{
IOProgress.CenterText = "گزارش کارکرد پرسنل:" + "شماره پرسنلی:" + users.IndexKey + "تاریخ:" + lstDate[i];
IOProgress.Value = i;
karkardCls = new KarkardClass();
t1 = t2 = t3 = tFinal = new TimeSpan();
filter = filter.OrderBy(c => c.fDateS);
//بررسی نام شیفت
var shiftName = FillItemsOfShift(lstDate[i], users.Shift.ToString(), users.IndexKey);


//ورود و خروج
var getItem = filter.Where(c => c.fIdentity.Equals(users.IndexKey) && c.fDate.Equals(lstDate[i]));


//مرخصی یا ماموریت
var checkMM = Program.db.tblSMIOMMs.Where(c => c.fidentity.Equals(users.IndexKey) && c.fDateS.Equals(lstDate[i]));


//Add To List
karkardCls.ID = users.ID;
karkardCls.Name = users.Name;
karkardCls.Family = users.Family;
karkardCls.Date = lstDate[i];
karkardCls.Day = new ProjectClass.ConvertDate().getWeek(new ProjectClass.DateValidation().GetDate(karkardCls.D ate).DayOfWeek, 'A'); //روز
karkardCls.iDate = Convert.ToInt64(karkardCls.Date.Replace("/", ""));
karkardCls.ShiftName = shiftName;


var getShiftItem = Program.db.tblSMIOSateKaris.SingleOrDefault(c => c.fIdentiti.Equals(shiftName) && c.fSal == sYear());


#region طول شیفت
if (getShiftItem != null)
{
karkardCls.ShiftLenght = getShiftItem.fDTIME != null && shiftName != "-" ? getShiftItem.fDTIME : "00:00";
totalTime.tShiftLenght += new TimeSpan(getTime(karkardCls.ShiftLenght).iH, getTime(karkardCls.ShiftLenght).iM, 0);
}
#endregion


//بررسی مرخصی یا ماموریت
if (checkMM.Any())
{
foreach (var item in checkMM)
{
karkardCls.Desc = karkardCls.Desc + " " + Program.db.tblSMIOMMTitles.SingleOrDefault(c => c.fid.Equals(item.fKind)).fTitle;
karkardCls.In1 = " ";//ورود1
karkardCls.Out1 = " ";//خروج1
karkardCls.In2 = " ";//ورود2
karkardCls.Out2 = " ";//خروج2
karkardCls.In3 = " ";//ورود3
karkardCls.Out3 = " ";//خروج3


}
}


//نداشتن تردد
if ((!getItem.Any() || getItem.Count() % 2 != 0) && !checkMM.Any())
{
karkardCls.Desc = shiftName.Equals("-") ? "تعطیل" : " غیبت روزانه";
karkardCls.In1 = " ";//ورود1
karkardCls.Out1 = " ";//خروج1
karkardCls.In2 = " ";//ورود2
karkardCls.Out2 = " ";//خروج2
karkardCls.In3 = " ";//ورود3
karkardCls.Out3 = " ";//خروج3


}
//
else if (getItem.Any())
{


//
var IO = getItem.OrderBy(c => c.fDateS).ToList();


//else
//{


if (getShiftItem != null)
{
#region محاسبه اولین ورود و آخرین خروج


long firstTime = IO.Min(c => c.fTimeS);
long lastTime = IO.Max(c => c.fTimeS);


//محاسبه اولین ورود
string fIN = firstTime.ToString();
string m_fIN = fIN.Substring(fIN.Length - 2, 2);
string h_fIN = fIN.Remove(fIN.Length - 2, 2);
if (h_fIN.Length < 2)
h_fIN = "0" + h_fIN;
string fINTime = h_fIN + ":" + m_fIN;
//


//محاسبه آخرین ورود
string fOUT = lastTime.ToString();
string m_ffOUT = fOUT.Substring(fOUT.Length - 2, 2);
string h_fOUT = fOUT.Remove(fOUT.Length - 2, 2);
if (h_fOUT.Length < 2)
h_fOUT = "0" + h_fOUT;
string ffOUTime = h_fOUT + ":" + m_ffOUT;
#endregion


try
{
karkardCls.In1 = IO[0] != null ? IO[0].fTime : "00:00";//ورود1
karkardCls.Out1 = IO[1] != null ? IO[1].fTime : "00:00";//خروج1
karkardCls.In2 = IO[2] != null ? IO[2].fTime : "00:00";//ورود2
karkardCls.Out2 = IO[3] != null ? IO[3].fTime : "00:00";//خروج2
karkardCls.In3 = IO[4] != null ? IO[4].fTime : "00:00";//ورود3
karkardCls.Out3 = IO[5] != null ? IO[5].fTime : "00:00";//خروج3
}
catch (Exception)
{
goto Next;
}
Next:


#region گرد کردن زمانهای ورود و خروج
var getRoundedTime = Program.db.tbLSateKariRounds.Where(c => c.fkId.Equals(getShiftItem.fid));


foreach (var roundedTime in getRoundedTime)
{
TimeSpan rtime1 = new TimeSpan(getTime(roundedTime.fFtime.Replace(":", "")).iH, getTime(roundedTime.fFtime.Replace(":", "")).iM, 0);
TimeSpan rtime2 = new TimeSpan(getTime(roundedTime.fLtime.Replace(":", "")).iH, getTime(roundedTime.fLtime.Replace(":", "")).iM, 0);

if (karkardCls.Out1 != null)
{
TimeSpan karkardClsItem = new TimeSpan(getTime(karkardCls.Out1.Replace(":", "")).iH, getTime(karkardCls.Out1.Replace(":", "")).iM, 0);
if (karkardClsItem >= rtime1 && karkardClsItem <= rtime2)
karkardCls.Out1 = roundedTime.fToTime;
}
if (karkardCls.In2 != null)
{
TimeSpan karkardClsItem = new TimeSpan(getTime(karkardCls.In2.Replace(":", "")).iH, getTime(karkardCls.In2.Replace(":", "")).iM, 0);
if (karkardClsItem >= rtime1 && karkardClsItem <= rtime2)
karkardCls.In2 = roundedTime.fToTime;
}
if (karkardCls.Out2 != null)
{
TimeSpan karkardClsItem = new TimeSpan(getTime(karkardCls.Out2.Replace(":", "")).iH, getTime(karkardCls.Out2.Replace(":", "")).iM, 0);
if (karkardClsItem >= rtime1 && karkardClsItem <= rtime2)
karkardCls.Out2 = roundedTime.fToTime;
}
if (karkardCls.In3 != null)
{
TimeSpan karkardClsItem = new TimeSpan(getTime(karkardCls.In3.Replace(":", "")).iH, getTime(karkardCls.In3.Replace(":", "")).iM, 0);
if (karkardClsItem >= rtime1 && karkardClsItem <= rtime2)
karkardCls.In3 = roundedTime.fToTime;
}
if (karkardCls.Out3 != null)
{
TimeSpan karkardClsItem = new TimeSpan(getTime(karkardCls.Out3.Replace(":", "")).iH, getTime(karkardCls.Out3.Replace(":", "")).iM, 0);
if (karkardClsItem >= rtime1 && karkardClsItem <= rtime2)
karkardCls.Out3 = roundedTime.fToTime;
}
}
#endregion


#region کارکرد
try
{
t1 = timeSpan(karkardCls.Out1.Replace(":", ""), karkardCls.In1.Replace(":", ""));
t2 = timeSpan(karkardCls.Out2.Replace(":", ""), karkardCls.In2.Replace(":", ""));
t3 = timeSpan(karkardCls.Out3.Replace(":", ""), karkardCls.In3.Replace(":", ""));
}
catch (Exception)
{
//Nothing;
}
tFinal = t1 + t2 + t3;
totalTime.tKarkard += tFinal;
//بررسی مرخصی ساعتی
if (karkardCls.In3 != null && karkardCls.Out3 != null)
{
var getMorakhasi = IO.Where(c => c.fKind.Equals("5") || c.fKind.Equals("6")).ToList();
if (getMorakhasi.Any())
{
TimeSpan moirakhasiTime = timeSpan(getMorakhasi[1].fTimeS.ToString(), getMorakhasi[0].fTimeS.ToString());
karkardCls.Morkhasi = moirakhasiTime.ToString(@"hh\:mm");
karkardCls.Desc = "مرخصی ساعتی";
totalTime.tMorkhasi += moirakhasiTime;
}


}
//بررسی ماموریت ساعتی
if (karkardCls.In3 != null && karkardCls.Out3 != null)
{
var getMoamoriat = IO.Where(c => c.fKind.Equals("7") || c.fKind.Equals("8")).ToList();
if (getMoamoriat.Any())
{
TimeSpan moirakhasiTime = timeSpan(getMoamoriat[1].fTimeS.ToString(), getMoamoriat[0].fTimeS.ToString());
karkardCls.Mamoriat = moirakhasiTime.ToString(@"hh\:mm");
tFinal = tFinal.Add(moirakhasiTime);
karkardCls.Desc = "ماموریت ساعتی";
totalTime.tMamoriat += moirakhasiTime;
}


}
karkardCls.Karkard = tFinal.ToString(@"hh\:mm");




#endregion


#region تعجیل خروج
if (lastTime < long.Parse(getShiftItem.fFExitTime.Replace(":", "")))
{
TimeSpan tajil = timeSpan(getShiftItem.fFExitTime.Replace(":", ""), lastTime.ToString());
karkardCls.Tajil = tajil.ToString(@"hh\:mm");
totalTime.tTajil += tajil;
}
#endregion


#region تاخیر ورود


if (firstTime > long.Parse(getShiftItem.fFSTIME.Replace(":", "")))
{
TimeSpan takhir = timeSpan(firstTime.ToString(), getShiftItem.fFSTIME.Replace(":", ""));
karkardCls.Takhir = takhir.ToString(@"hh\:mm");
karkardCls.KasreKar = karkardCls.Takhir;
totalTime.tTakhir += takhir;
}
#endregion


#region اضافه کار


if (getShiftItem.fFrackezafekar.Trim().Length >= 5)
{
if (!string.IsNullOrEmpty(getShiftItem.fFrackezafekar .Replace(":", "")))
{
if (getShiftItem.fFrackezafekar.Trim().Length >= 5 && getShiftItem.fCalcfrackezafekar.Value)
{
long getEzafekarLenght = long.Parse(getShiftItem.fFrackezafekar.Replace(":", ""));


if (lastTime > getEzafekarLenght)
{
//اضافه کار در روز
ezafekarLenght = timeSpan(lastTime.ToString(), getEzafekarLenght.ToString());


//اضافه کار اول شیفت
if (getShiftItem.fSfrackezafekar.Trim().Length >= 5 && getShiftItem.fZSE.Trim().Length >= 5)
{
long fezTime = long.Parse(getShiftItem.fSfrackezafekar.Replace(":", ""));
long eezTime = long.Parse(getShiftItem.fZSE.Replace(":", ""));


firstShiftTime = timeSpan(eezTime.ToString(), fezTime.ToString());
karkardCls.EzAval = firstShiftTime.ToString(@"hh\:mm");
totalTime.tEzAval += firstShiftTime;
}
else
{
firstShiftTime = new TimeSpan();
karkardCls.EzAval = "00:00";
}
//






//اضافه کار مابین شیفت
if (getShiftItem.fSecoundTime.Value && getShiftItem.fc2ez.Value)
{
var getNormallIo = IO.Where(c => c.fKind == "1" || c.fKind == "2").ToList();
if (getNormallIo.Count == 4)
{
BetweenShift = timeSpan(getNormallIo[2].fTimeS.ToString(), getNormallIo[1].fTimeS.ToString());
karkardCls.ezBetween = BetweenShift.ToString(@"hh\:mm");
totalTime.tEzBetween += BetweenShift;
}
}
else
{
BetweenShift = new TimeSpan();
karkardCls.ezBetween = "00:00";
}
//
//کسر تعجیل از اضافه کار
if (getShiftItem.fKasreTajil.Value)
{
var getNormallIo = IO.Where(c => c.fKind == "1" || c.fKind == "2").ToList();
if (getNormallIo.Count == 4)
if (getNormallIo[1].fTimeS < long.Parse(getShiftItem.fFExitTime.Replace(":", "")))
{
TimeSpan tajil = timeSpan(getShiftItem.fFExitTime.Replace(":", ""), getNormallIo[1].fTimeS.ToString());


if (getShiftItem.fFFExit.Trim().Length >= 5)
{
TimeSpan tajileMojaz = timeSpan(getShiftItem.fFExitTime.Replace(":", ""), getShiftItem.fFFExit.Replace(":", ""));


if (tajil > tajileMojaz)
{
tajil.Subtract(tajileMojaz);
ezafekarLenght.Subtract(tajil);
totalTime.tTajil += tajil;
}
}
else
{
ezafekarLenght.Subtract(tajil);
}


}
}//


//کسر تاخیر از اضافه کار
if (getShiftItem.FKasreTakhir.Value)
{
if (firstTime > long.Parse(getShiftItem.fFSTIME.Replace(":", "")))
{
TimeSpan takhir = timeSpan(firstTime.ToString(), getShiftItem.fFSTIME.Replace(":", ""));
if (getShiftItem.fFRACTIME.Trim().Length >= 5)
{
TimeSpan takhireMojaz = timeSpan(getShiftItem.fFRACTIME.Replace(":", ""), getShiftItem.fFSTIME.Replace(":", ""));
if (takhir > takhireMojaz)
{
takhir.Subtract(takhireMojaz);
ezafekarLenght.Subtract(takhir);
totalTime.tTakhir += takhir;
}
}
else
{
ezafekarLenght.Subtract(takhir);
}


}


}//




}
}
}
}
//اضافه کار تعطیل
if (shiftName.Equals("-"))
{
ezTatil = timeSpan(lastTime.ToString(), firstTime.ToString());
karkardCls.EzTatil = ezTatil.ToString(@"hh\:mm");
totalTime.tEzTatil += ezTatil;
}
else
{
ezTatil = new TimeSpan();
karkardCls.EzTatil = "00:00";
}
//


//محاسبه اضافه کار


string ezafeKarTime = ezafekarLenght.ToString(@"hh\:mm");


karkardCls.ezKarKharj = ezafeKarTime;
TimeSpan tAll = new TimeSpan();
if (getShiftItem.FTatil.Value)
tAll = (ezafekarLenght + firstShiftTime + BetweenShift + ezTatil);
else
tAll = (ezafekarLenght + firstShiftTime + BetweenShift);
totalTime.tAllEz += tAll;
karkardCls.EzAll = tAll.ToString(@"hh\:mm");
//
#endregion
}
karkardCls.Mamoriat = karkardCls.Mamoriat != null ? karkardCls.Mamoriat : "00:00";
karkardCls.Morkhasi = karkardCls.Morkhasi != null ? karkardCls.Morkhasi : "00:00";
}
//

ali_md110
چهارشنبه 20 خرداد 1394, 13:24 عصر
با توجه به این حلقه معلومه برنامتون کارایی پایین داره
یک راه حل : آیا امکانش هست بعضی فیلدهایی که میخواین توی گزارش بیاد هنگام ثبت رکورد محاسبه شده و توی یک فیلد مختص خودش ذخیره کنید؟
مثلا جمع کارکردهای یک شخص: به محض ورود یا حضور غیاب یک شخص بیاد کارکردهاشون محاسبه کنه و ذخیره کنه تا هنگام گزارش نخواین این جستجو ها رو بزنید

SabaSabouhi
چهارشنبه 20 خرداد 1394, 13:52 عصر
سلام
من دلیل مشکل شما رو نمی‌دونم، اما چیزی که نوشتی، امکان نداره مگه این که از یک منبعی استفاده کنی و آزادش نکنی
و معطل اون منبع بمونی ( مثل حافظه یا گیر کردن در Transactionهای دیتابیس )

اما این کدی که فرستادی، یه چیز مهمی توش دیدم که لازم دونستم یه پست بزنم.
دوست من، شما یه تابعی داری که فقط یه حلقه‌اش بیش‌تر از 400 خط هست. اگه این پروژه دانشجویی باشه که هیچ، اما
اگه مشتری داره، مطمئن باش که اگه 6 ماه دیگه ( تازه نمی‌گم 2 سال ) یه مشکلی پیش بیاد، با این نحوه‌ی کد نوشتن
برای حل مشکل و در کل پشتیبانی دچار مشکلات بسیار زیادی می‌شی.
من عدد خاصی در نظر ندارم، اما سعی کن تعداد خطوط هر تابع از 50 خط تجاوز نکنه. برای این کار شناسایی اشیاء و سپردن
کارهای هر شی به خود اون شی می‌تونه به مقدار زیادی حجم این نوع توابع رو کم کنه. و خیلی روش‌های دیگه.

صبا صبوحی

Behnam6670
چهارشنبه 20 خرداد 1394, 14:40 عصر
تشکر از جواب دوستان

این قطه کدی که براتون گذاشتم نمونه از کدهای نرم افزار حضور و غیاب بود که سرمایه گذاری زیادی روش صورت گرفته و خودم تو شرکتمون دارم روش کار میکنم.

از اینکه روشهای بسیار زیادی برای بدست آوردن نتیجه ای که من تو این قطعه کد دنبالش هستم وجود داره، من شک ندارم،من خروجیی که میخوام رو گرفتم ولی به چه بهایی!!!!!!

راندمان کار بسیار اومده پایین بصورتی که سیستم تو محاسبه کارکرد اشخاص خیلی افت سرعت پیدا میکنه:افسرده: .

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

تو قسمت گزارشات یه قسمت من تعریف کردم برای نمایش کارکرد اشخاص به تفکیک روز.
دوستانی که با نرم افزارها حضور غیاب کار کردن میدونن که کار این نرم افزارها به چه شکل هستش و چه آیتم هایی دارند(ساعت کاری-شیفت-شیفت چرخشی-مرخصی-ماموریت-قوانین اضافه کاری-قوانین محاسباتی فانون کار و کلی آیتم دیگه) .

تو بخش نمایش کارکرد یک شخص تو یک تاریخ خاص سیستم باید تمام این ضریبها و پارامترهایی که تعریف شده برای شخص رو محاسبه کنه و نشون بده.

فکرشو بکنید برای اضافه کار یا ماموریت یا مرخصی چه محاسبات سنگینی باید انجام بشه تا نهایت مثلا نشون بده اضافه کار آقای احمدی روز یکشنبه 04:00 ساعت بوده!!!!!!!! برای همین تمام آیتمها بهم وابسته هستند.

من این کد رو گذاشتم تا اساتید ببینید و نظر بدن تا اینکه بلکه بشه ایده ای از نظرات اساتید گرفته بشه.

ممنون از توجه و وقتی که گذاشتید

reza_ali202000
چهارشنبه 20 خرداد 1394, 14:55 عصر
اول از همه دیتا بیست رو بهینه کن و کلاستر بندی کن. انیدکس گذاری ها انجام بده(توی خود sql server ) میتونی از پیشنهاداتش استفاده کنی.
دوم اینکه یه دو سه هفته ای وقت بزاری و کم کم از دوتا فراخونیات شروع کنی و تجمیعشون کنی اونم توی اس کیو ال. مثلا الان یه بار میاد حضور افراد رو چک میکنه ساعت میده و یه بار هم میاد خروج افراد رو چک میکنه و ساعت میده. حالا شما بیا به طور ارام و پیوسته این دوتا رو یکی کن. بعد برو سراغ دوتای دیگش و بعد دست اخر میبینی که اصلا نیازی به حلقه هم دیگه نیس. ولی باید اهسته و پیوسته انجام بشه.
اگه میبینید برنامه جواب میده فعلا براشون نصب کنید و بعداز یه مدت بهشون سربزنین و اپدیتش کنین با کدهای جدید.

asman.abi
چهارشنبه 20 خرداد 1394, 21:08 عصر
در کد نویسی فهم مسئله خیلی مهمه. اگه مسئله فهمیده بشه راه حل های خیلی ساده ای براش یافت میشه. قبلا هم در این تالار باهاش خیلی مواجهه شدیم.

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

موفق باشید.