PDA

View Full Version : سوال: ایجاد آرایه ای باحداکثر 500 هزار داده



md3848
جمعه 08 فروردین 1399, 11:05 صبح
سلام - میخوام یه List از یه کلاس ایجاد کنم - که خب کلاس فوق، 25 تا داده ( 1 رکورد ) رو در خودش ذخیره میکنه / حالا میخوام یه لیستی از رکرودها رو ذخیره کنم به کمک کد زیر.
List<myClass> Records = new List<myClass>();
مسئله ای که هستش اینه که ممکنه حداکثر 500 هزارتا رکورد داشته باشم که خب حجم فایل text اش میشه 70 میگ / آیا این مسئله مشکلی میتونه ایجاد کنه؟ و آیا کار درستیه؟ برا این که سرعت خوندن نوشتنش زیاده ( فک کنم ) اینکارو میخوام بکنم - نظر دوستان چیه؟

taghvajou
جمعه 08 فروردین 1399, 16:45 عصر
سلام و وقت بخیر

چند تا نکته:
1- اگه ساختار کلاس رو هم بذارین گاهی برای همفکری بهتره که کلاس شما شامل 25 داده، چه چیزهایی میشه.
2- گفتیم لیست رو به "به کمک کد زیر" ذخیره کنی. ولی فقط یه خط کد هست که تعریف لیست کلاس! کد ذخیره دیده نمیشه. اگه لازمه ویرایش کنین که بهتر بشه همفکری کرد.
3- برای 500 هزار تا رکورد، فکر میکنم بیشتر از 70 مگ بشه. اگه 70 مگا بایت رو تقسیم کنیم به 500هزار رکورد با 25 تا داده میشه، تقریبا هر داده 5 بایت. یه اینتیجر (int) قفط 4 بایته! اگه شما متن و تاریخ و اینها داخلش باشه که بیشتر میشه!
4- اینکه فایل (تکست یا هر فایل) هفتاد مگ یا صد مگ یا هرچقدر بشه ، محدودیت نداریم مگر سایز هارد یا حافظه و فرمت سیستمی حافظه. (مثلا FAT32 محدودیت حدودا 4 گیگ داره در سایز فایل) که با توجه به هاردهای ما و فرمت ان تی اف اس، جای نگرانی نیست.
5- فرمت تکس عملا همه چی رو باینتری میکنه و نهایتا انتهای هر خط رو ذخیره میکنه. پس با توجه به اینکه باینتری هستش و خیلی ساختار نداره، گاهی کم حجم و سریعتر تلقی میشه.

اما !!!!
در مورد اینکه پرسیدین کار درستیه، مبهمه! چی کار درستیه؟ برای چه کاری؟ هدف انتقال داده است؟ هدف ذخیره و بازیابی؟ هدف ذخیره موقته؟ برای چی اون لیست 500هزار تایی رو میخواین تو یه فایل ذخیره کنین؟

md3848
جمعه 08 فروردین 1399, 17:53 عصر
رکورد داده به صورت زیر هستش :
$LOC,9,+05.12,-18.5,00.0000000,N,000.0000000,E,0000.0,000.0,00H00 M00,x4,65,23,110.30,040.03,-0/0027,90.0,20.15,150.0,19.88,-00.1,0,1,0,1019,09.8,*0D
که خب حاوی تقریبا 25 تا داده مختلف هستش که اینا باید split بشن و بعد ConvertToDouble
حالا کلاسمون رکورد فوق رو میگیره و داده هاشو تو متغییر های مختلف ذخیره میکنه
ما هم یه لیست از کلاس فوق ایجاد میکنیم
حالا حجمش حداقل 70 میگ ( حجم 500 هزار تا رکورد تو فایل txt ) یا 200 میگ و یا بیشتر - کاری ندارم.
-------------
حالا رکورد ها رو از فایل تکس میخونیم یا به صورت آنلاین به پورت Serial وصل میشیم و داده ها رو میخونیم ( حداکثر سرعت 100 رکرود در ثانیه هستش و حداقل 1 رکورد در ثانیه )
حالا من میخوام یه آرایه ای از داده ها داشته باشم تا هر زمان میخوام بهشون دسترسی داشته باشم ( تو قسمت های مختلف برنامه ازشون استفاده کنم.)

taghvajou
جمعه 08 فروردین 1399, 18:35 عصر
تعدد و تکرر لود دیتا و استفاده دیتا رو سناریو ما موثره.
ایا داده ها تند تند تغییر میکنند یا هر از چند گاهی؟
و اینکه ایا برنامه هم مرتب در حال اجراس یا فقط برای انجام یه عملیاتی اجرا میشه و بعد اتمام بسته میشه.
فرض میکنیم یه دستگاهی یه بار یه سری داده تولید میکنیم و ما هم داده ها رو میگیریم که تحلیل کنیم.
اگه قرار باشه از فایل تکست لود بشه سریع میشه خوند،
ولی اگه قراره از پورت سریال بگیریم، برای دریافت اون تعداد داده، زمان زیادی میبره، و چون ممکنه برنامه وسط راه بسته بشه یا ویندوز خاموش بشه، بهتره اطلاعات رو داخل یه جدول ذخیره کنیم و با استفاده از ویژگی های منحصر بفردش مثلا طول و عرض جغرافیایی کلید اصلی بذاریم و ایندکس کنیم. فرمت کردن ها و کانورت کردن ها و کلاس بندی ها رو میشه انجام داد. حالا یه جدول داخل دیتابیس ولو اکسس، و یا حتی داخل ایکس ام ال.

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

ShayanFiroozi
یک شنبه 10 فروردین 1399, 11:26 صبح
سلام ،

به نظر میاد شما در خصوص داده کاوی میخواین کار کنین ، به هر حال چند نکته هست که باید بهش توجه کنین :

1- CLR حداکثر اجازه میده هر شی 2 گیگابایت رم استفاده کنه و اگر بیشتر شد شما صد در صد OutOfMemory Exception رو دریافت میکنین که طبیعی هم هست. ( این موضوعی هستش که خیلی ها رعایت نمیکنن و شایدم اطلاع ندارن)
2- لیست ها خیلی برای این کار ضعیف هستند ، شاید عملیات Load و یا Insert اطلاعات در اونا سریع باشه ولی عملیات جستجو و یا Lookup بسیار ضعیفه مخصوصا با این تعداد رکورد.
3- شما بهتره از HashSet ها استفاده کنین و برای جستجو هم از متد Contains که در HashSet ها پیاده سازی شده ، با این تعداد رکورد عملیات Lookup شما باید حدود 1 میلی ثانیه یا کمتر بشه که صد البته بستگی به مشخصات سیستم شما داره.

md3848
سه شنبه 12 فروردین 1399, 11:16 صبح
چی فک میکردیم چی شد، خب مث این که داستان شد!، حدود 30 هزار تا رکورد شد 3 گیگ تقریبا ( 3 گیگ رم ویندوز رو مصرف کرد ) :لبخند::متعجب::افسرده::گریه:: تفکر: ( تموم این شکلک ها، گویای وضعیت کنونی منه :لبخند: )
( کلاسی که داده های رکورد فوق رو تجزیه کنه و هر داده رو در متغییر مخصوصش بریزه و خود اصل رکورد رو هم ذخیره کنه )

آخرش هم برنامه بسته شد، گفت زیادی داری از رم استفاده میکنی :لبخند: ( که خب دوستموم در بالا این نکته رو اشاره کردن )

خب دیگه مث این که باید بریم سراغ دیتابیس ولی مشکلی که دارم سرعت خوندن، نوشتن، جستجو در دیتابیس هستش.
1-آفلاین : ذخیره تمام رکوردها در دیتابیس و نمایش در مپ و چارت‌ها ( این که چقدر طول میکشه زیاد مهم نی ) -> در چارت‌ها، رخداد moveMove میام موقعیت کرسر رو میخونم و تولتیپ تمام Series ها رو یکجا نمایش میدم، که خب باید سرعت جستجو در دیتابیس بالا باشه.
2-آنلاین : رکورد ها با حداقل سرعت 1 رکورد در ثانیه ( و حداکثر 100 رکورد در ثانیه ) در یافت میشوند از پورت سریال، که خب هم باید در مپ و چارت ها نمایش داده بشن و هم در دیتابیس ذخیره بشن، که خب سرعت ذخیره داده در دیتابیس کم باشه به مشکل نمیخورم؟:متفکر:

با این اوصاف کدوم دیتابیس بهتره؟ که سرعت خوندن نوشتن جستجو اش بالا باشه
( من خودم فعلا دارم از sqlite استفاده میکنم / البته برا تنظیمات برنامه و نه ذخیره رکورد ها، رکورد ها که فعلا تو همون آرایه/لیست دارن ذخیره میشن و ... )




ایا داده ها تند تند تغییر میکنند یا هر از چند گاهی؟
داده های توی رکورد، بعضیاشون تند تند تغییر میکنن، بعضیاشون مث gps و ساعت و ارتفاع ثانیه ای یکبار، بقیه لحظه ای تغییر میکنن.


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

ShayanFiroozi
چهارشنبه 13 فروردین 1399, 16:46 عصر
بنده در خصوص دیتابیس تخصص ندارم ولی فکر میکنم SQL Server خوب باشه.

ضمنا با این حجم کار و سرعت بالا شما بهتره با همون RAM کار کنی تا دیتابیس ، چون هر چی نباشه به هر حال Read/Write فایل خودش زمان میبره ، از هارد SSD استفاده کن تقریبا 10 برابر افزایش سرعت میگیری(البته اگر با دیتابیس کار میکنی).

به نظر بنده شما معماری نرم افزار و دیتا هاتون رو بهینه تر کنین ، جوری که همچین اطلاعات زیادی رو با هم توی یه Object قرار ندین.

نکته : چون زیاد RAM رو Allocate میکنی ، دیتاهای بلا استفاده رو پاک کن و بعدش دستور GC.Collect(); رو اجرا کن که CLR حافظه بلا استفادشو به سیستم برگردونه.

md3848
پنج شنبه 14 فروردین 1399, 10:02 صبح
خب عذر میخوام، یه مشکلی در map بود که باعث مصرف زیاد رم میشد حلش که کردم:خجالت:، الان برا 36k رکورد، حجم رم مصرفی میشه حدود 100 میگ ( حجم فایل text رکورد ها، 5 میگه تقریبا، رم مصرفی قبل از add کردن رکورد ها حدود 30 میگ بود، فلذا رم مصرفی برا فایل رکورد فوق میشه 70 میگ؛ پس اگه فایل 360k رکورد رو اد کنم، رم مصرفی میشه 700 میگ، که خب مشکلی با این میزان رم مصرفی ندارم، وقتی مفته رم مفته و سرعتش هم خوبه چرا استفاده نکنیم :لبخند: )


شما بهتره با همون RAM کار کنی تا دیتابیس
آره فعلا همین تصمیم رو گرفتم.


از هارد SSD استفاده کن تقریبا 10 برابر افزایش سرعت میگیری
حرف شما صحیح ولی خب هر یوزری که هارد ssd نداره.


به نظر بنده شما معماری نرم افزار و دیتا هاتون رو بهینه تر کنین ، جوری که همچین اطلاعات زیادی رو با هم توی یه Object قرار ندین.
همینکارو کردم. ممنون بابت اطلاع.

ShayanFiroozi
پنج شنبه 14 فروردین 1399, 11:27 صبح
خب عذر میخوام، یه مشکلی در map بود که باعث مصرف زیاد رم میشد حلش که کردم:خجالت:، الان برا 36k رکورد، حجم رم مصرفی میشه حدود 100 میگ ( حجم فایل text رکورد ها، 5 میگه تقریبا، رم مصرفی قبل از add کردن رکورد ها حدود 30 میگ بود، فلذا رم مصرفی برا فایل رکورد فوق میشه 70 میگ؛ پس اگه فایل 360k رکورد رو اد کنم، رم مصرفی میشه 700 میگ، که خب مشکلی با این میزان رم مصرفی ندارم، وقتی مفته رم مفته و سرعتش هم خوبه چرا استفاده نکنیم :لبخند: )


آره فعلا همین تصمیم رو گرفتم.


حرف شما صحیح ولی خب هر یوزری که هارد ssd نداره.


همینکارو کردم. ممنون بابت اطلاع.



خوشحالم که مشکل حل شده ، فقط حتما به جای لیست ها از HashSet ها استفاده کنین ، سرعت Lookup تقریبا صفره ، چون مرحله جستجوی لیست ها O(n) هستش و لی HashSet ها O(1).

md3848
پنج شنبه 14 فروردین 1399, 12:09 عصر
خوشحالم که مشکل حل شده ، فقط حتما به جای لیست ها از HashSet ها استفاده کنین ، سرعت Lookup تقریبا صفره ، چون مرحله جستجوی لیست ها O(n) هستش و لی HashSet ها O(1).
این لینک چیز جالبیه ( #HashSet vs. List in C )
https://stackoverflow.com/questions/150750/hashset-vs-list-performance

ممنون از taghvajou / ShayanFiroozi

تنها ضدحالی که این HashSet میزنه اینه که نمیشه مثل list به آیتماش دسترسی داشت :متفکر:
data[i]
و باید از کد زیر استفاده کرد :
data.ElementAt(i)