اینتل و ردیس بهبودهای قابلتوجهی در عملکرد داشتهاند. در اینجا تکنیکهای بهینهسازی را که برای ارزیابی و حداکثرسازی عملکرد دستور GEO ردیس استفاده کردیم، به اشتراک میگذاریم؛ از جمله کاهش محاسبات زائد و سادهسازی الگوریتمها.
تمام کارها نتیجه دادند. به طور کلی، عملکرد Redis را تا چهار برابر سرعت قبلی بهبود دادیم.
دستورات GEO در Redis (بهصورت رسمی شاخصهای جغرافیایی) ابزار قدرتمندی برای کار با دادههای جغرافیایی هستند. Redis میتواند مختصات جغرافیایی یک شیء را ذخیره کند، مانند مکانهای فروشگاه یا کامیونهای تحویل در حرکت. سپس Redis میتواند محاسبات ریاضی و عملیات مبتنی بر مختصات را بر روی آن دادهها انجام دهد، مانند تعیین فاصله بین دو نقطه (کامیون تحویل سفارش نهارم چقدر فاصله دارد؟) یا یافتن تمام نقاط ثبتشده در شعاع معینی از یک نقطه دیگر (نزدیکترین فروشگاه حیوانات خانگی به مکان فعلی من کجا است؟).
در نهایت، طول و عرضها فقط دادههایی برای برنامههای شما هستند تا به آنها دسترسی داشته و بهروزرسانی کنند. همانند هر پایگاه دادهای که بخشی از منطق کسبوکار حیاتی شماست، شما بهترین عملکرد ممکن را میخواهید – بهویژه زمانی که سیستمهای دسترسی به دادهها بهصورت فیزیکی در حال حرکت هستند (مانند آن کامیون تحویل) و بنابراین به پاسخهای زمان واقعی نیاز دارند. برای رسیدن به این هدف، بهینهسازی پرسوجوها و الگوریتمهایی که برای تعامل با دادههای GEO استفاده میکنید مهم است.
برای به حداکثر رساندن عملکرد اجرای دستورات GEO در Redis، به تحلیل عملکرد و تکنیکهای شناسایی بار کاری پرداختهایم. اهداف ما شناسایی گلوگاهها، بهینهسازی استفاده از منابع و بهبود عملکرد کلی بود.
در این پست، تکنیکهای بهینهسازی مانند کاهش محاسبات زائد و سادهسازی الگوریتمها و نتایج تحلیلمان را به اشتراک میگذاریم. نتیجهگیری: میتوانیم تا چهار برابر توان پردازشی در درخواستهای GEOSEARCH دست یابیم، و این بهبود هماکنون به عنوان بخشی از Redis 7 منتشر شده است.
تحلیل عملکرد و مورد استفاده جغرافیایی
تحلیل عملکرد و شناسایی ویژگیهای بار کاری تکنیکهای مهمی برای درک ویژگیهای عملکردی برنامهها هستند. این تکنیکها شامل جمعآوری و تحلیل دادههای مربوط به رفتار برنامه و استفاده از منابع آن برای شناسایی گلوگاهها، بهینهسازی استفاده از منابع و بهبود عملکرد کلی میشوند.
هر برنامهای که میخواهیم سرعت آن را افزایش دهیم، از روشهای قطعی، مختصر و سیستماتیک برای نظارت و تجزیه و تحلیل عملکرد استفاده میکنیم. برای انجام این کار، میتوانید از هر یک از روششناسیهای عملکرد موجود استفاده کنید، که بسته به نوع مسئله و تحلیلی که میخواهید انجام دهید، برخی مناسبتر از دیگران هستند.
بهصورت کلی، وقتی میخواهید کارایی یک برنامه را بهبود بخشید، این چکلیست عمومی برای بیشتر موقعیتها اعمال میشود:
- تعیین اهداف عملکرد: پیش از شروع، باید درک واضحی از آنچه میخواهید دست یابید داشته باشید. اهداف ممکن است شامل بهبود زمان پاسخ، کاهش استفاده از منابع، یا افزایش توان پردازشی باشد. در این مورد، ما میخواهیم هم زمان پاسخ هر عملیات فردی را بهبود دهیم و از این رو، توان پردازشی قابل دستیابی را افزایش دهیم.
- شناسایی بار کاری: سپس، بار کاری که میخواهید تجزیه و تحلیل کنید را تعیین کنید. این ممکن است شامل شناسایی وظایف یا اقداماتی باشد که برنامه اجرا میکند، به همراه الگوهای بار و استفاده مورد انتظار. برای مورد استفاده دستورات GEO، ما از یک مجموعه داده شامل ۶۰ میلیون نقطه بر پایه دادههای OpenStreetMap (PlanetOSM) و مجموعهای از پرسوجوهای جغرافیایی برای بنچمارک استفاده کردیم.
- جمعآوری دادهها: پس از شناسایی بار کاری، دادههای مربوط به عملکرد برنامه و استفاده از منابع آن را برای هر مورد جمعآوری کنید. ممکن است از پروفایلرها، دیباگرها یا ابزارهای تجزیه و تحلیل عملکرد استفاده کنید. دادههای مربوط به استفاده از حافظه برنامه، استفاده از CPU و سایر معیارها را جمعآوری نمایید. پروفایلکردن استفاده از CPU با نمونهگیری از ردهای پشته در فواصل زمانی، روشی سریع و آسان برای شناسایی بخشهای بحرانی کد است (که بهعنوان نقاط داغ نیز شناخته میشوند). نتایج ما دقیقاً مبتنی بر استفاده از ابزار perf برای آن هدف بوده است. مستندات ما درباره شناسایی افت عملکرد درباره شناسایی افت عملکرد و بهبودهای احتمالی روی CPU شامل فهرست کامل ابزارها و روششناسیهای عمیقتر میشود.
- تحلیل دادهها: پس از جمعآوری دادهها، میتوانید از تکنیکهای مختلف برای تجزیه و تحلیل و شناسایی نواحی برنامه که ممکن است بر عملکرد تأثیر بگذارند، استفاده کنید. برخی از این تکنیکها شامل تحلیل عملکرد در طول زمان، مقایسه بارهای کاری مختلف و جستجوی الگوها در دادهها میباشد. ما متوجه شدیم که با تجزیه و تحلیل پروفایل ثبت شده با استفاده از perf report، بهبودهای چشمگیری در موارد استفاده مرتبط با CPU به دست میآید، بهویژه وقتی که زمینه کدنویسی برنامه مورد پروفایلگذاری را میدانید. هر چه تجربه بیشتری با کد برنامه داشته باشید، بهینهسازی آن آسانتر میشود.
- بهینهسازی برنامه: بر اساس تحلیل شما، میتوانید نواحی برنامه که ممکن است باعث مشکلات عملکردی شوند شناسایی کنید. سپس اقداماتی برای بهینهسازی کد انجام دهید، مانند تغییر به الگوریتم کارآمدتر، کاهش مقدار حافظه مصرفی یا اعمال تنظیمات دیگر کد. در سناریوهای بعدی که نشان میدهیم، ما بر کارایی الگوریتمها و کاهش محاسبات تکراری متمرکز میشویم.
- تکرار فرآیند: تحلیل عملکرد و شناسایی بار کاری فرآیندهای مستمری هستند، بنابراین مهم است که بهصورت منظم عملکرد برنامه را مرور و تجزیه و تحلیل کنید. این کار به شما امکان میدهد تا گلوگاهها یا مشکلات جدیدی که در بهروزرسانیها یا شرایط استفاده ممکن است بروز کنند، شناسایی و برطرف کنید.
زمینه محاسبه فاصله شاخصهای جغرافیایی Redis
نمیتوانید نرمافزار را سریعتر کنید اگر ندانید که چه کاری انجام میدهد. در این مورد، به معنای یک معرفی کوتاه به فرایند کار با دادههای جغرافیایی است.
اکثر دستورات برای پرسوجوی شاخصهای جغرافیایی Redis فاصله بین دو مختصات را محاسبه میکنند، بنابراین معقول است که بررسی کنیم این محاسبه الگوریتمی چگونه انجام میشود. فاصله هاورسین معیار مفیدی است، زیرا انحنا زمین را در نظر میگیرد و نتایج دقیقتری نسبت به فاصله اقلیدسی ارائه میدهد.
برای محاسبه فاصله هاورسین بر روی یک کره (مانند زمین)، نیاز به عرض و طول جغرافیایی دو نقطه و همچنین شعاع کره دارید. فرمول هاورسین فاصله بین نقاط را بهصورت خط مستقیم، در کوتاهترین مسیر بر سطح کره، محاسبه میکند.
این محاسبات به شدت وابسته به توابع مثلثاتی برای محاسبه فاصله هاورسین هستند، و فراخوانی توابع مثلثاتی هزینهبر از نظر سیکلهای CPU میباشد. در تجزیه و تحلیل گلوگاه یک دستور ساده GEOSEARCH، حدود ۵۵٪ از سیکلهای CPU صرف این توابع میشود، همانطور که در شکل ۱ نشان داده شده است. این بدان معنی است که بهینهسازی این بلوکهای کد ارزشمند است، یا همانطور که آمدال میگوید، «بهبود کلی عملکرد حاصل از بهینهسازی یک بخش از سیستم، به نسبتی از زمان که آن بخش بهکار گرفته میشود محدود میشود.»
پس، بیایید بر بزرگترین بهینهسازی ممکن تمرکز کنیم.

شکل ۱: اطلاعات پروفایل اولیه برای یک دستور ساده GEOSEARCH که ۵۵٪ از سیکلهای CPU را در توابع مثلثاتی نشان میدهد.
مرحله اول بهینهسازی: کاهش محاسبههای زائد
همانطور که دادههای پروفایل بالا نشان میدهند، ۵۴.۷۸٪ از سیکلهای CPU توسط تابع
geohashGetDistanceIfInRectangle
ایجاد میشود. در این تابع، سه بار
geohashGetDistance
فراخوانی میشود. دو اولین بار، این روال برای تولید نتایج میانی (مانند بررسی اینکه آیا نقطهای از محدوده طول یا عرض خارج است) فراخوانی میشود. این کار از محاسبههای هزینهبر فاصله جلوگیری میکند اگر شرایط نادرست باشد. منطقی است که دادهها در محدوده باشند، اما نیازی نیست که این کار را بهصورت تکراری انجام دهیم.
اولین تلاش ما برای بهینهسازی و کاهش محاسبههای زائد نتایج میانی در دو مرحله (که بهصورت جزئی در PR #11535 توصیف شده است):
- کاهش محاسبه هزینهبر در محاسبات میانی
geohashGetDistance
.
- اجتناب از محاسبه هزینهبر فاصله طول جغرافیایی اگر شرط فاصله عرض جغرافیایی برقرار نباشد.
این بهینهسازی تفاوت قابلتوجهی ایجاد کرد. برای آن پرس و جوی GEOSEARCH، با استفاده از یک مشتری بنچمارک بدون پایپلاین، زمان تاخیر متوسط (از جمله زمان رفت و برگشت) را از ۹۳.۵۹۸ میلیثانیه به ۷۳.۰۴۶ میلیثانیه کاهش دادیم، که نشاندهندهٔ کاهش حدود ۲۲٪ زمان تاخیر است.
مرحله دوم: محاسبههای زائد
تحلیل عملکرد مشابه برای درخواستهای GEOSEARCH نیز نشان داد که در برخی موارد، Redis تماسهای بیمورد به
sdsdup
و
sdsfree
را انجام میدهد. این دستورات به ترتیب حافظهٔ رشتهها را اختصاص و آزاد میکنند. این اتفاق در مجموعه دادههای بزرگ، جایی که بسیاری از عناصر خارج از محدوده جستجو هستند، رخ میدهد.

شکل ۲: در این فرآیند، بیش از ۲۸٪ از توجه CPU به دستور
sdsdup
صرف شد. هر کاری که بتوانیم برای کاهش این تراکنش انجام دهیم، سرعت نتایج جستجوی جغرافیایی را افزایش میدهد.
PR 11522 بهبود عملکردی که در آن پیشنهاد دادیم، ساده بود: بهجای پیشاختصاص حافظهٔ رشته، نقش
geoAppendIfWithinShape
را تغییر دادیم تا فراخواننده رشته را تنها زمانی ایجاد کند که مورد نیاز باشد. این منجر به کاهش تقریباً ۱۴٪ زمان تاخیر و ۲۵٪ بهبود در عملیات بر ثانیهٔ قابل دستیابی شد.
مرحله سوم: سادهسازی الگوریتمها
برای بهینهسازی پرسوجوی شاخص جغرافیایی، بر اطلاعات الگوی دادهها تمرکز کردیم. هدف سادهسازی تعداد محاسبات مورد نیاز برای فاصله هاورسین بود. این صرفاً یک تمرین ریاضی است.
زمانی که اختلاف طول جغرافیایی صفر باشد:
- در صورتی که اختلاف طولی صفر باشد، تابع asin(sqrt(a)) در فرمول هاورسین برابر با asin(sin(abs(u))) میشود.
- تابع arcsin(sin(x)) را برابر با x در بازهٔ x ∈[−𝜋/۲,𝜋/۲] در نظر بگیرید.
- در صورتی که عرض جغرافیایی در بازهٔ [−𝜋/۲,𝜋/۲] باشد، میتوانیم arcsin(sin(x)) را به abs(x) ساده کنیم.
PR #11579 بهینهسازی را توصیف میکند و بهبود عملکرد حاصل از این سادهسازی را نشان میدهد. نکتهٔ کلیدی این است که باعث افزایش ۵۵٪ در عملکرد عملیات بر ثانیهٔ قابل دستیابی برای دستور GEOSEARCH در Redis شد.
مرحله چهارم: مسألهٔ نمایش
تمام موارد استفادهای که به شدت به تبدیل عدد اعشاری به رشته متنی وابستهاند (مانند تبدیل عدد شناور با دقت دو برابر (۱.۵) به رشته (“۱.۵”)) میتوانند با جایگزینی فراخوانی
snprintf(buf,len,"%.4f",value)
با نسخهٔ بهینهتری از تبدیل نقطهای ثابت به رشته سود ببینند.
دستور GEODIST، که در شکل ۳ نشان داده شده است، مثال خوبی است. حدود یکچهارم زمان CPU به تبدیل نوع اختصاص دارد.

شکل ۳: اطلاعات پروفایل برای دستور GEODIST که ۲۶٪ از سیکلهای CPU را به تبدیل عدد اعشاری به رشته میسپارد.
PR 11552 بهطور جزئی بهینهسازی پیشنهادی ما را توصیف میکند که منجر به افزایش ۳۵٪ در تعداد عملیات بر ثانیهٔ قابل دستیابی برای دستور GEODIST شد.
جمعبندی در Redis 7.0
دلیل اصلی محبوبیت Redis به عنوان یک پایگاه داده، عملکرد آن است. ما عموماً پرسوجوها را با زمان پاسخ زیر میلیثانیه اندازهگیری میکنیم – و میخواهیم همچنان آن را بهبود دهیم.
اثر تجمعی بهینهسازیهای توصیفشده در این پست بلاگ: ما عملکرد دستورات جغرافیایی Redis را تا چهار برابر سرعت قبلی افزایش دادیم. شما میتوانید هماکنون از این بهبودها بهرهمند شوید، زیرا بخشی از Redis 7.0.7 هستند. و این باید شما را سریعتر از قبل به هدفتان برساند.
|
دستور |
مورد تست |
عملیات/ثانیه قابل دستیابی Redis 7.0.5 |
عملیات/ثانیه قابل دستیابی Redis 7.0.7 |
ضریب بهبود |
|
GEODIST key … |
geo-60M-elements‑geodist‑pipeline‑۱۰ |
۷۷۵۵۲۴ |
۹۹۳۶۳۲ |
۱.۳ X |
|
GEOSEARCH … FROMLONLAT … BYRADIUS |
geo-60M-elements‑geosearch‑fromlonlat |
۱۱.۸ |
۱۳.۸ |
۱.۲ X |
|
GEOSEARCH … FROMLONLAT … BYBOX |
geo-60M-elements‑geosearch‑fromlonlat‑bybox |
۱۳.۲ |
۴۹.۶ |
۳.۸ X |
دستور
مورد تست
عملیات/ثانیه قابل دستیابی Redis 7.0.5
عملیات/ثانیه قابل دستیابی Redis 7.0.7
ضریب بهبود
GEODIST key …
geo-60M-elements‑geodist‑pipeline‑۱۰
۷۷۵۵۲۴
۹۹۳۶۳۲
۱.۳ X
GEOSEARCH … FROMLONLAT … BYRADIUS
geo-60M-elements‑geosearch‑fromlonlat
۱۱.۸
۱۳.۸
۱.۲ X
GEOSEARCH … FROMLONLAT … BYBOX
geo-60M-elements‑geosearch‑fromlonlat‑bybox
۱۳.۲
۴۹.۶
۳.۸ X
بهبودهای کلی GEO در توان پردازشی قابل دستیابی بین Redis 7.0.5 و Redis 7.0.7 بر روی سرور مبتنی بر پردازنده Intel Xeon Platinum 8360Y.
|
دستور |
مورد تست |
تاخیر p50 کلی شامل RTT (ms) Redis 7.0.5 |
تاخیر p50 کلی شامل RTT (ms) Redis 7.0.7 |
ضریب بهبود |
|
GEODIST key … |
geo-60M-elements‑geodist‑pipeline‑۱۰ |
۲.۵۷۵ |
۲.۰۰۷ |
۱.۳ X |
|
GEOSEARCH … FROMLONLAT … BYRADIUS |
geo-60M-elements‑geosearch‑fromlonlat |
۶۷۹.۹۳۵ |
۵۹۸.۰۹۷ |
۱.۱ X |
|
GEOSEARCH … FROMLONLAT … BYBOX |
geo-60M-elements‑geosearch‑fromlonlat‑bybox |
۶۰۵.۷۳۹ |
۱۶۱.۷۹۱ |
۳.۷ X |
دستور
مورد تست
تاخیر p50 کلی شامل RTT (ms) Redis 7.0.5
تاخیر p50 کلی شامل RTT (ms) Redis 7.0.7
ضریب بهبود
GEODIST key …
geo-60M-elements‑geodist‑pipeline‑۱۰
۲.۵۷۵
۲.۰۰۷
۱.۳ X
GEOSEARCH … FROMLONLAT … BYRADIUS
geo-60M-elements‑geosearch‑fromlonlat
۶۷۹.۹۳۵
۵۹۸.۰۹۷
۱.۱ X
GEOSEARCH … FROMLONLAT … BYBOX
geo-60M-elements‑geosearch‑fromlonlat‑bybox
۶۰۵.۷۳۹
۱۶۱.۷۹۱
۳.۷ X
بهبودهای کلی GEO در تاخیر p50 کلی شامل RTT به ازای هر دستور بین Redis 7.0.5 و Redis 7.0.7 بر روی سرور مبتنی بر پردازنده Intel Xeon Platinum 8360Y.
توجه داشته باشید که این یک بهبود عملکرد ایزوله نیست – بلکه برعکس. این مجموعه از بهبودها مثال واقعی از تأثیر تلاشهای عملکردی است که ما «مشخصات بنچمارکهای Redis» مینامیم. ما بهصورت مداوم در پی افزایش شفافیت و بهبود عملکرد در تمام APIهای Redis هستیم.
پیشروی به سمت هدف
آیا میخواهید بیشتر در مورد محاسبات جغرافیایی بیاموزید؟ به سایر بلاگهای عملکردی این سری نگاهی بیندازید، که بیشترشان بهصورت مشترک با Intel نوشته شدهاند:
- سریع را سریعتر کنید! بهصورت روشمند عملکرد Redis را بهبود میدهیم، توصیف نحوهٔ بهبود عملکرد ورودی جریان حدود ۲۰٪.
- آزمون عملکرد، پروفایلگیری و تجزیه و تحلیل، توصیف خودکارسازی عملکرد و پروفایلگیری بدون تماس.
- گرگوریل در اتاق: بررسی بهینهسازیهای عملکردی RedisTimeSeries، بررسی بهینهسازیهای ممکن برای الگوریتم فشردهسازی/فشردهبرداری RedisTimeSeries.
- بهینهسازی پرچمهای پیشفرض کامپایلر Redis، درباره تغییر رفتار کامپایلر در Redis OSS.
*اینتل، لوگوی اینتل، و سایر علامتهای اینتل علائم تجاری شرکت اینتل یا شرکتمشتقهای آن هستند.

پست های مرتبط
شتاببخشی به دستورات جغرافیایی در Redis 7
شتاببخشی به دستورات جغرافیایی در Redis 7
شتاببخشی به دستورات جغرافیایی در Redis 7