هناك مثل هذه الفئة الشائعة من المهام التي من الضروري فيها إجراء تحليل متعمق بما فيه الكفاية لكامل حجم سلاسل العمل المسجلة بواسطة أي نظام معلومات (IS). كعنوان IP ، يمكن أن يكون هناك تدفق للوثائق ، ومكتب خدمات ، و bugtracker ، ومجلة إلكترونية ، ومحاسبة المستودعات ، وما إلى ذلك. تتجلى الفروق الدقيقة في نماذج البيانات وواجهات برمجة التطبيقات وأحجام البيانات والجوانب الأخرى ، ولكن مبادئ حل هذه المشكلات هي نفسها تقريبًا. كما أن أشعل النار الذي يمكنك السير عليه مشابه جدًا.
لحل هذه الفئة من المشاكل ، يناسب R تمامًا. ولكن ، حتى لا تهمل بشكل مخيب للآمال ، قد يكون R جيدًا ، ولكن أوه ، بطيء جدًا ، من المهم الانتباه إلى أداء طرق معالجة البيانات المحددة.
إنه استمرار للمنشورات السابقة .
عادة ، لا يكون نهج "الجبين" السطحي هو الأكثر فعالية. تبدأ 99٪ من المهام المرتبطة بتحليل البيانات ومعالجتها باستيرادها. في هذا المقال الموجز ، سننظر في المشكلات التي تنشأ في المرحلة الأساسية لاستيراد البيانات مع البيانات بتنسيق json
، باستخدام مثال المهمة النموذجية للتحليل "العميق" لبيانات تثبيت Jira. يدعم json
نموذج كائن معقد ، على عكس csv
، لذا فإن json
في حالة الهياكل المعقدة يمكن أن يصبح صعبًا وطويلًا جدًا.
بيان المشكلة
معطى:
- يتم تنفيذ jira واستخدامها في عملية تطوير البرامج كنظام لإدارة المهام ومتعقب الأخطاء.
- لا يوجد وصول مباشر إلى قاعدة بيانات jira ، والتفاعل عبر REST API (العزلة الجلفانية).
- تحتوي ملفات json التي سيتم أخذها على بنية شجرة معقدة للغاية مع الصفوف المتداخلة المطلوبة لتحميل سجل الإجراءات بأكمله. يتطلب حساب المقاييس عددًا صغيرًا نسبيًا من المعلمات المنتشرة عبر مستويات مختلفة من التسلسل الهرمي.
مثال على jira json عادي في الشكل.

مطلوب:
- استنادًا إلى بيانات jira ، من الضروري العثور على الاختناقات ونقاط الزيادة المحتملة في كفاءة عمليات التطوير وتحسين جودة المنتج الناتج بناءً على تحليل جميع الإجراءات المسجلة.
الحل
من الناحية النظرية ، هناك العديد من الحزم المختلفة في R لتحميل json وتحويلها إلى data.frame
. الحزمة الأكثر ملاءمة هي jsonlite
. ومع ذلك ، فإن التحويل المباشر لهرمية json إلى data.frame
صعب بسبب التداخل متعدد المستويات والمعلمات القوية لهيكل السجل. قد يتطلب التمسك بمعلمات محددة تتعلق ، على سبيل المثال ، بتاريخ الإجراءات ، تحويلات مختلفة. الشيكات والحلقات. أي يمكن حل المشكلة ، ولكن بالنسبة لملف json من 32 مهمة (بما في ذلك جميع القطع الأثرية وتاريخ المهام بأكمله) ، فإن هذا التحليل غير الخطي باستخدام jsonlite و tidyverse يستغرق حوالي 10 ثوانٍ على كمبيوتر محمول متوسط الأداء.
10 ثوان فقط ليس كثيرا. ولكن بالضبط حتى اللحظة التي لا يوجد فيها الكثير من هذه الملفات. التقييم على عينة من التحليل والتحميل باستخدام طريقة "مباشرة" مماثلة ~ 4000 ملف (~ 4 جيجابايت) أعطت 8-9 ساعات من العمل.
ظهر مثل هذا العدد الكبير من الملفات لسبب ما. أولاً ، لدى jira حدود زمنية لجلسة REST ، فمن المستحيل سحب كل شيء باستخدام شعاع. ثانيًا ، نظرًا لكونها مدمجة في الدائرة الإنتاجية ، فمن المتوقع أن يتم التحميل اليومي للبيانات المتعلقة بالمهام المحدثة. ثالثًا ، وسيتم ذكر ذلك أدناه ، فإن المهمة جيدة جدًا للتحجيم الخطي وتحتاج إلى التفكير في التوازي من الخطوة الأولى.
حتى 10-15 تكرارات في مرحلة تحليل البيانات ، وتحديد الحد الأدنى المطلوب من المعلمات ، والكشف عن المواقف الاستثنائية أو الخاطئة ، وتطوير خوارزميات ما بعد المعالجة تعطي التكاليف في غضون 2-3 أسابيع (فقط حساب الوقت).
وبطبيعة الحال ، فإن هذا "الأداء" غير مناسب للتحليلات التشغيلية ، التي يتم تضمينها في الدائرة الإنتاجية ، وهو غير فعال للغاية في مرحلة تحليل البيانات الأولية وتطوير النموذج الأولي.
تخطي جميع التفاصيل الوسيطة ، أنتقل على الفور إلى الجواب. نحن نتذكر دونالد نوث ، نشمر عن سواعدنا ونبدأ في وضع microbenching جميع العمليات الرئيسية ، وقطع كل شيء ممكن بلا رحمة.
يتم تقليل الحل الناتج إلى الخطوط العشرة التالية (هذا هو هيكل عظمي مزيف ، دون مجموعة الجسم غير الوظيفية اللاحقة):
library(tidyverse) library(jsonlite) library(readtext) fnames <- fs::dir_ls(here::here("input_data"), glob = "*.txt") ff <- function(fname){ json_vec <- readtext(fname, text_field = "texts", encoding = "UTF-8") %>% .$text %>% jqr::jq('[. | {issues: .issues}[] | .[]', '{id: .id, key: .key, created: .fields.created, type: .fields.issuetype.name, summary: .fields.summary, descr: .fields.description}]') jsonlite::fromJSON(json_vec, flatten = TRUE) } tictoc::tic("Loading with jqr-jsonlite single-threaded technique") issues_df <- fnames %>% purrr::map(ff) %>% data.table::rbindlist(use.names = FALSE) tictoc::toc() system.time({fst::write_fst(issues_df, here::here("data", "issues.fst"))})
ما هو المثير للاهتمام هنا؟
- لتسريع عملية التحميل ، من الجيد استخدام الحزم المتخصصة
readtext
، مثل readtext
. - يتيح
jq
استخدام محلل تدفق jq
ترجمة جميع ربط السمات الضرورية إلى لغة وظيفية ، data.frame
إلى مستوى CPP وتقليل المعالجة اليدوية للقوائم المتداخلة أو القوائم في data.frame
. - ظهرت مجموعة
bench
الواعدة للغاية للمعايير الدقيقة. يسمح لك بدراسة ليس فقط وقت تنفيذ العمليات ، ولكن أيضًا التلاعب بالذاكرة. ليس سرا أنه يمكنك أن تفقد الكثير في نسخ البيانات في الذاكرة. - بالنسبة للكميات الكبيرة من البيانات والمعالجة البسيطة ، غالبًا ما يكون من الضروري في القرار النهائي التخلي عن
tidyverse
ونقل الأجزاء المستهلكة للوقت إلى data.table
، على وجه الخصوص ، يتم دمج الجداول باستخدام data.table
. وأيضًا جميع التحولات في مرحلة ما بعد المعالجة (والتي يتم تضمينها في الدورة من خلال وظيفة ff
يتم أيضًا باستخدام أدوات data.table
مع نهج تغيير البيانات حسب المرجع ، أو الحزم التي تم إنشاؤها باستخدام Rcpp
، على سبيل المثال ، في anytime
للعمل مع التواريخ والأوقات. - الحزمة
fst
جيدة جدًا لإلقاء البيانات في ملف ثم قراءته. على وجه الخصوص ، لا يستغرق الأمر سوى جزء من الثانية لحفظ جميع تحليلات سجل jira لمدة 4 سنوات ، ويتم حفظ البيانات تمامًا مثل أنواع بيانات R ، وهو أمر جيد لإعادة استخدامها لاحقًا.
أثناء الحل ، تم rjson
في نهج باستخدام حزمة rjson
. jsonlite::fromJSON
أبطأ مرتين تقريبًا من rjson = rjson::fromJSON(json_vec)
، ولكن كان من الضروري تركه ، نظرًا لوجود قيم NULL في البيانات ، وفي مرحلة تحويل NULL
إلى NA
في القوائم التي rjson
ميزة ، ويزداد الرمز.
الخلاصة
- أدت إعادة الهيكلة هذه إلى تغيير في وقت معالجة جميع ملفات json في وضع الخيوط المفردة على نفس الكمبيوتر المحمول من 8-9 ساعات إلى 10 دقائق.
- إضافة موازاة المهمة باستخدام
foreach
عمليا لم تثقل الكود (+ 5 أسطر) ولكنها قللت وقت التنفيذ إلى 5 دقائق. - نقل الحل إلى خادم لينكس ضعيف (4 نوى فقط) ، ولكن التشغيل على SSD في الوضع متعدد الخيوط قلل وقت التنفيذ إلى 40 ثانية.
- أدى النشر على دائرة إنتاجية (20 نواة ، 3 غيغاهرتز ، SSD) إلى تقليل وقت التنفيذ إلى 6-8 ثوانٍ ، وهو أكثر من مقبول لمهام التحليلات التشغيلية.
في المجموع ، وبقيت في إطار منصة R ، نجحت عملية إعادة هيكلة بسيطة للرمز في تقليل وقت التنفيذ من ~ 9 ساعات إلى ~ 9 ثوانٍ.
يمكن أن تكون القرارات بشأن R سريعة جدًا. إذا لم ينجح شيء بالنسبة لك ، فحاول النظر إليه من زاوية مختلفة واستخدام تقنيات جديدة.
المنشور السابق - "المظلة التحليلية للمدير" .