بافر ظرفی برای نگهداری ردیفهای داده به صورت بایت به بایت است. هر بایت شامل ۸ بیت میشود. پس یک بایت فرضی میتواند ظاهری مانند 00110101 داشته باشد. در سطح پایینتر، همه دادهها در کامپیوتر با استفاده از بیتها نمایش داده میشوند. بافر قسمتی از حافظه است که برای نگهداری موقت دادهها استفاده میشود. هر نرمافزاری میتواند بافر مخصوص به خود را داشته باشد. برای اینکه بدانیم مهمترین مزیت استفاده از بافر در برنامه نویسی چیست باید توجه کنیم که در سطوح سختافزاری سرعت و نرخ پردازش و تولید و مصرف داده بین ابزار گوناگون با هم مساوی نیست. بافرها نقشی کلیدی برای جلوگیری از هدر رفت دادهها در میان این ناهمخوانیهای پشت پرده نرمافزارها دارند.
برعکس آرایهها، لیستها، مجموعهها، دیکشنریها و حتی مواردی مانند JSON، بافرها معمولا در دورهها یا مقالات مقدماتی زبان های برنامه نویسی پوشش داده نمیشود. بنابراین معمولا جویندگان دانش، برای پیداکردن اطلاعات بیشتر درباره بافرها باید شخصا وارد عمل شده و به جست و جو بپردازند. در این مطلب از مجله فرادرس تلاش کردیم که درباره چیستی بافر، وظیفه اصلی و مشکلات سر راه عملکرد آن صحبت کنیم. با پیگیری این مطلب میتوانیم به یک لایه عمیقتر از بحث کدنویسی بپردازیم.
بافر در برنامه نویسی چیست؟
بافر اصطلاحی عمومی است. این اصطلاح، به معنای چیز یا شخصی است که بین دو چیز، در تقابل یا تعامل با هم، حایل میشود. اما بهطور کلی، میتوانیم گفت که بافر ابزاری برای کاهش اثر نوسانات در عرضه و تقاضا است. در علوم کامپیوتر، بافر فضای ذخیرهسازی موقتی است که در زمان تبادل دادهها توسط اجزای سیستم با یکدیگر استفاده میکنیم.
در دنیای واقتی به صورت همزمان چندین تولید کننده و مصرف کننده داده وجود دارند. اما در این مطلب برای توضیح بهتر مفاهیم، بر روی موقعیت فرضی تمرکز میکنیم که فقط یک تولیدکننده و مصرفکننده داده وجود دارند.
بیشتر سیستم عامل ها همراه با بافرهای از پیش تعریف شده برای استفاده در موقعیتهای مختلف عرضه میشوند. برای مثال، تبادل داده بین یک CPU سریع و وسیله خارجی کند بدون وجود بافری به عنوان واسطه بین آنها غیر ممکن است.
همچنین به عنوان توسعه دهنده، میتوانیم در زمان توسعه و برنامه نویسی نرمافزارها بافر سفارشی خود را نیز ایجاد کنیم.
بافر بین تولیدکننده و مصرفکننده داده
فرض میکنیم سیستمی داریم که شامل یک مصرفکننده و یک تولیدکننده داده میشود. برنامه تولید کننده در حال تولید دادههای جدیدی است که برنامه مصرفکننده استفاده میکند.
الان ممکن است که برنامه تولیدکننده، دادهها را با سرعت بیشتری از توان برنامه مصرفکننده برای پردازش آنها ایجاد و ارسال کند. در این مورد، برنامه دوم مقداری داده تولید خواهد کرد که یا کیفیت خیلی کمی دارند یا بهطور کل غلط هستند. برای جلوگیری کردن از چنین اتفاقی، از بافری که به اندازه کافی حجم داشته باشد بین این دو برنامه جداگانه استفاده خواهیم کرد.
بنابراین، بافر به عنوان فضای ذخیرهسازی واسطه عمل میکند. تولیدکننده، دادههای تولید شده را درون بافر ذخیره خواهد کرد. برنامه مصرفکننده نیز دادهها را یک به یک متناسب با سرعت توان پردازشش از بافر برمیدارد. اگر سرعت پردازش مصرفکننده کندتر از فرایند تولید داده باشد، آنها منتظر میمانند تا مصرفکننده دادهها را بردارد. در همین حال، تولید کننده به گذاشتن داده در بافر ادامه میدهد. در نتیجه هیچ دادهای از دست نخواهد رفت.
بافرها وقتی مفید هستند که بین نرخ تولید و پردازش دادهها هماهنگی وجود نداشته باشد. اگرچه مهم است که اندازه بافر را به درستی تعیین کنیم.
آشنایی بیشتر با انواع ساختمان داده
بافرها نوعی از ساختمان های داده هستند که برای ذخیرهسازی دادهها البته بهصورت موقت بهکار برده میشوند. ساختمان داده شامل انواع ساختارهای داده دیگری مانند صف و پشته نیز میشود. هر کدام از این ساختارهای داده به منظوری متفاوت و با روش متفاوتی به ذخیرهسازی دادهها میپردازند. برای آشنایی بیشتر با این ساختارهای خاص و حرفهای در ساختمان داده و تماشایی روشهای پیادهسازی این مولفههای ساختمان دادهای، با زبانهای برنامهنویسی مختلف میتوانید به وبسایت آموزشی فرادرس مراجعه کنید. فرادرس یکی از بهترین تولیدکنندگان محتوای آموزشی به زبان فارسی است که فیلمهای آموزشی بسیار غنی و باکیفیتی را برای کمک به پیشرفت علمی و عملی همراهان عزیزش تهیه کرده است.
در این بخش چند مورد از فیلمهای آموزشی را معرفی کردهایم که بهطور مستقیم به مبحث ساختمان داده مربوط میشوند. در صورت تمایل با کلیک بر روی تصویر بالا میتوانید وارد صفحه اصلی این مجموعه آموزشی شوید و فیلمهای بیشتری را در اینباره مشاهده کنید.
اندازه بافر در برنامه نویسی چیست؟
اندازه بافرها بر روی کل بهرهوری سیستم تاثیر میگذارد. اگر فضایی بیشتر از نیازمان برا بافر رزرو کنیم، نتیجه کار عدم استفاده بخش زیادی از حافظه خواهد شد. در مقابل، اگر فضای در نظر گرفته برای بافر، فضای کوچکی باشد، از دست رفتن دادهها و ایجاد نتایج غلط را تجربه خواهیم کرد.
فقط از طریق آزمایش دقیق که تمام سناریوهای ممکن را پوشش دهد، میتوانیم اندازه بهینه را برای بافر برنامههای خود تعیین کنیم.
محیط کار برنامه ها
محیطی که برنامه طراحی شده در آن کار خواهد کرد و نیازمندیهای مشخص شده برنامه میتوانند به تخمین اندازه بافر کمک کنند.
برای نمونه، اگر برنامهای که نوشتهایم از ساختار شبکهای برای اتصال به تولیدکننده و مصرفکننده استفاده کند، به بافر بزرگی در هر سمت فرستنده و گیرنده نیاز خواهیم داشت. علت مسئله این است که در کانالهای بیسیم، اتلاف داده زیاد اتفاق میافتد. به همین دلیل واسطههای این شبکهها مستعد از دست دادن داده و کندی عملکرد هستند. در چنین مواردی وجود بافر میتواند این خطاها را بدون تاثیرگذاری بر روی کیفیت سرویس کاهش دهد.
به عنوان یک از رایجترین مثالها، میتوان به سرویس انتشار آنلاین ویدئو اشاره کرد. در این مثال، معمولا پخش کننده ویدئو سمت کاربر، اندازه بافر را با توجه به تابعی از ویژگیهای شبکه تنظیم میکند. پخش کننده ویدئو سمت کاربر، محتوای رسانهای را از طریق واسطه از سرور واکشی میکند و سپس دادههای واکشی شده را در بافر ذخیره میکند. بنابراین کاربر نهایی هیچگونه تاخیر یا خرابی در پخش ویدئو را تجربه نخواهد کرد.
نرخ تولید و دریافت داده بافر در برنامه نویسی چیست؟
برای جلوگیری از سرریز بافر، معمولا اندازه آن را بر روی مضربی از تفاوت نرخ تولید و مصرف دادهها تنظیم میکنیم. برای مثال، اگر دادهها با نرخ ۲ واحد در ثانیه تولید شدهاند اما نرخ مصرفشان به اندازه ۱ واحد بر ثانیه بود، برای جلوگیری از سرریز باید اندازه بافر را با فرمول زیر تنظیم کنیم.
محل قرار گیری بافر
این مسئله اندازه بافر را نیز تعیین میکند. اگر فضای دیسک حافظه سیستم را به عنوان بافر در نظر بگیریم، عملیات مربوط به خواندن و نوشتن دادهها نسبت به بافری که در RAM قرار دارد بسیار کندتر خواهد بود.
بیشتر فایل سیستمها در بلاکهایی با اندازه بین 4096 یا 8192 بایت (توانهای بزرگی از عدد ۲) عملیات خواندن و نوشتن را انجام میدهند. بنابراین مجبور هستیم که اندازه بافر خود را به عنوان ضریبی از اندازه بلاکهای دیسک تعیین کنیم. با این روش، میتوانیم عملیات خواندن و نوشتن را به شدت کارآمد کنیم.
برای اینکه بتوانیم عملکر بافر را بهتر درک کنیم لازم است با ساختار حافظه اصلی رم نیز بیشتر آشنا شویم. برای این کار پیشنهاد میکنیم که به مطلب راهنمای جامع مدیریت حافظه در سیستم عامل در مجله فرادرس مراجعه کنید.
مشکلات مربوط به بافر در برنامه نویسی چیست؟
بافرها همینطور که مزایای زیادی دارند و میتوان گفت که به معنای واقعی کلمه، جزئی ضروری از برنامهها هستند و مشکلات خاص خودشان را نیز دارند. بهطور عمده بافرها دو مشکل عمده دارند.
- «سرریز» (Overflow)
- «زیرریز» (Underflow)
در ادامه این مطلب هر دوی این مشکلات را توضیح دادهایم و برای هر کدام روشهای روبهرو شدن و حل مشکل را نیز بیان کردهایم.
Overflow
زمانی که برنامه تولیدکننده، دادهها را با سرعتی خیلی بیشتر از توان پردازش دادهها توسط مصرف کننده تولید کند. حتی با اینکه مصرف کننده از بافر کمک میگیرد، مشکل سرریز بافر یا بافر محدود شده اتفاق میافتد. در چنین مواردی ظرفیت بافر پُر میشود و دادههای جدید یا باید با دادههای قدیمی جایگزین شوند -بر روی آن نوشته شوند- یا از دست بروند.
برای نمونه، فرض کنیم که برنامه تولید کنندهای که در اختیار داریم، جملاتی را با سرعت ۱۰ حرف الفبا در ثانیه تولید میکند. فضای ذخیرهسازی بافر به اندازه ۸ حرف الفبا جای دارد و مصرف کننده در هر دو ثانیه میتواند ۱ حرف را بخواند. در چنین موقعیتی «سرریز» (Overflow) بافر در همان اولین ثانیهها رخ میدهد.
برای مدیریت چنین مشکلی راههای مختلفی به ذهن برنامهنویسها میرسد. برای نمونه، میتوانیم از بافر بزرگتری استفاده کنیم. اما این بافر بزرگتر هم هنوز در نهایت پر میشود. اما اگر عملیات جاری، زمان کمتری را برای تکمیل وظایفش نسبت به پر شدن بافر صرف کند، ممکن است که از سرریز بافر جلوگیری کنیم.
به همچنین میتوانیم سرعت مصرف کننده را بالاتر ببریم یا سرعت تولید کننده داده را پایین تر بیاوریم. البته توجه کنید که در صورت عملکرد کندتر تولیدکننده نسبت به مصرفکننده، ممکن است با مشکل متفاوتی روبهرو شویم. یعنی مشکل زیرریز یا Underflow بافر رخ دهد.
Underflow
مشکل زیرریز در بافرها وقتی رخ میدهد که برنامه تولیدکننده، بافر را با سرعت خیلی کمتری نسبت به پردازش دادهها توسط برنامه مصرفکننده پُر میکند. به عنوان نتیجه، بافر همیشه بهطور ناقصی پر میشود یا حتی خالی میماند. بنابراین مصرفکننده نیز بیشتر اوقات بهصورت بیکار و بیاستفاده است. در نتیجه این مشکل، کل سیستم دچار عملکرد ضعیفی میشود. هم از لحاظ زمانی، سیستم زمان بسیاری را بیکار میماند و هم از لحاظ حافظهای نیز میزان زیادی حافظه در بافر بلااستفاده میماند.
برای حل کردن این مسئله هم چند راه مختلف وجود دارد. روش اول استفاده از بافری کوچکتر است. با استفاده از این روش، در هر لحظه از زمان، بافر دادههای بیشتری را نسبت به فضای خالی خواهد داشت. با این روش حافظه کمتری بیاستفاده میماند.
روش دوم هم این است که سرعت تولیدکننده داده را افزایش یا سرعت مصرف کننده داده را کاهش دهیم. اگرچه باید توجه کنیم که اگر سرعت مصرفکننده داده نسبت به تولید کننده داده کمتر شود ممکن است با خطای Overflow روبهرو شویم.
همگام سازی Synchronization
اگر بتوانیم تولیدکننده داده را طوری مدیریت کنیم که در زمان پر بودن بافر دست از تولید دادههای جدید بکشد، میتوان از بروز مشکلات Overflow و Underflow جلوگیری کرد. همچنین باید مصرفکننده داده را مجبور کنیم که در زمان خالی بودن بافر از واکشی دادهها اجتناب کند. بنابراین، مصرفکننده و تولیدکننده داده را با هم همگامسازی میکنیم.
ایدهکلی به این شکل است که تولیدکننده را قبل از تولید هر داده جدید، مجبور به بررسی بافر کنیم. اگر بافر پر بود، تولیدکننده وارد فاز خواب موقت یا استراحت خواهد شد. در غیر این صورت، طبق روال معمول دادههای جدیدی به بافر اضافه خواهد کرد.
مصرفکننده نیز هر وقت که آماده پردازش دادههای جدید است، اول باید بافر را بررسی کند. اگر بافر خالی بود، مصرفکننده وارد فاز خواب موقت یا استراحت خواهد شد. اما اگر بافر خالی نبود، مصرفکننده قدیمیترین داده پردازش نشده را از درون بافر برمیدارد.
در چنین فرایندی با استفاده از قفل اختصاصی بافرها، از عملیات خواندن و نوشتن بر روی بافر محافظت میکنیم. از آنجا که عملیات بررسی توسط تولیدکننده و مصرفکننده داده به صورت اختصاصی و مجزا از هم انجام میپذیرد، هر دو میتوانند بعد از انجام بررسی خود قفل گفته شده را باز کنند. بررسی مربوط به هر کدام که شکست بخورد، برنامه مربوط وارد خواب موقت میشود. این اتفاق با فراهم کردن رفتار ثابتی در هربار اجرای اپلیکیشن، تضمین میکند که هیچ شرایط مسابقهای بین این دو برنامه رخ ندهد و همگام با هم به اجرای وظایف مربوطه بپردازند.
روش های موثر برای آموزش اصولی برنامه نویسی
همانطور که میدانیم هر نرمافزاری میتواند بافر مخصوص به خود را داشته باشد. برای اینکه بدانیم روش تعریف بافر در برنامه نویسی چیست باید به سراغ آموزشهای حرفهای برویم. کار با بافرها جزو مهارتهای تخصصی برنامهنویسی محسوب میشود. حرفهایترین آموزشهای برنامهنویسی نیز نیازمند صرف هزینه و زمان زیادی هستند. وبسایت آموزشی فرادرس، به عنوان یکی از بزرگترین تولیدکنندگان محتوای آموزشی فارسی همیشه به دنبال راهی بوده که بتواند با کیفیتترین آموزشها را در اختیار جویندگان علم قرار دهد. فیلمهای آموزشی فرادرس از لحاظ هزینه و زمان نسبت به کلاسهای حضوری بسیار مقرون به صرفهتر بوده و همیشه قابلیت بازبینی مجدد را دارند.
بخش مربوط به آموزش زبانهای برنامهنویسی فرادرس، فیلمهای آموزشی متنوعی را متناسب با انواع سطوح علمی مخاطبان عزیز با بهترین کیفیت فراهم کرده است. در این بخش چندمورد از فیلمهای سطح بالا و تخصصی مربوط به چند زبان برنامهنویسی متفاوت را معرفی کردهایم.
اگر نیاز به آموزشی زبان دیگر یا مبحث دیگری دارید با کلیک بر روی تصویر بالا وارد صفحه اصلی مجموعه آموزش شوید و گزینه مورد نظر خود را بیابید.
تفاوت حافظه Cache با بافر در برنامه نویسی چیست؟
با وجود اینکه بافر و Cache هردو با هدف مشابهی درباره ذخیرهسازی دادهها به صورت حافظه موقت بهکار برده میشوند، اما یکسان نیستند. از بافرها زمانی استفاده میکنیم که بین نرخ تولید دادهها و استفاده از دادهها در هر قسمت سیستم ناهماهنگی باشد. از طرف دیگر، هدف استفاده از حافظه Cache ذخیرهسازی دادههایی است که اخیرا بیشترین تکرار را در استفادههای پردازشی داشتهاند. اینکار باعث افزایش سرعت پردازش دادهها توسط سیستم میشود.
بهعلاوه، اندازه Cache معمولا بهطرز قابل توجهی کوچکتر از بافر است. در ضمن Cacheها دادهها را با سرعت بیشتری نسبت به بافرها میخوانند و مینویسند. به مطالب بالا باید اضافه کنیم که همه برنامهها در زمان اجرا و پردازش، Cache را با یکدیگر به اشتراک میگذارند. درحالی که هر برنامهای میتواند بافر مخصوص خود را داشته باشد. همچنین، اندازه Cache همیشه ثابت است، در حالی که اندازه بافر با توجه به پیادهسازی آن قابل پیکربندی یا ثابت شدن است.
جمع بندی
در این مطلب از مجله فرادرس درباره بافرها و نقش مهمشان در برنامهنویسی کامپیوتر صحبت کردیم. از بافرها وقتی استفاده میکنیم که اپلیکیشن یا بخش تولید کننده داده در نرمافزاری، نسبت به نرمافزار مصرفکننده دادهها سریعتر یا کندتر عمل میکند. نکات مهم درباره اندازه بافرها را عرضه کردیم و درباره مهمترین مشکلات موجود بر سر راه بافرها بحث و روشهای مدیریت این مشکلات را بیان کردیم. فهمیدیم که بهترین راه حل برای جلوگیری از بروز خطاهای مربوط به سرریز و زیرریز استفاده از تکنیک همگامسازی است.
در نهایت هم بافر را با حافظه نهان درون پردازشگر مرکزی کامپویتر یا همان Cache مقایسه کردیم. هرچه قدر که نسبت به انواع روشهای مدیریت دادهها در سیستم اطلاعات عمیقتری داشته باشیم، میتوانیم نرمافزارهای با ثباتتر و سریعتری را طراحی کنیم.
source