Ruby различает два хэша и объединяет их в цикле с кумулятивной суммой

нужна помощь с рубином!

У меня есть цикл, когда я собираю данные о процессах PHP (PID, utimes). У меня есть два хеша. Первый «h1» выглядит так:

"domain1" => { :utime => 0, :last_seen => 0, :process_count => 0, :process_count_avg => 0 },
"domain2" => { :utime => 0, :last_seen => 0, :process_count => 0, :process_count_avg => 0 }

Это код для него:

h1[vhostname] ||= { :utime => 0, :last_seen => 0, :process_count => 0, :process_count_avg => 0 }
h1[vhostname][:utime] += utime_proc 
h1[vhostname][:last_seen] = 0

'vhostname' — это строка, содержащая имя домена. utime_proc — это значение utime.

В каждом цикле я суммирую все utime для всех процессов определенного домена, и на выходе получается домен и его суммарное utime. Но это искажает реальное состояние.

Что мне нужно сделать, так это сделать совокупную сумму utimes для определенного домена. Быть суммой utime для всех текущих процессов, но добавлять сумму utime для всех уже завершившихся процессов. Вероятно, мне придется хранить процессы pid для каждого utime поддомена, и если этот процесс исчезнет, ​​его последнее utime будет добавлено к значению по умолчанию (хэш «h1»): utime в этом домене.

Итак, я создаю еще два хэша: «h2» и «h3». Значение «h3» сбрасывается в каждом раунде цикла, и в нем хранятся все PID для (под)домена с его utimes следующим образом:

h3[vhostname] = []
h3[vhostname] << {:pid => pid, :utime => utime_proc}

хэш «h2» хранит PID всех предыдущих циклов, так же, как «h3», но не сбрасывается:

if not h2.key?(vhostname)
h2[vhostname] = []
h2[vhostname] << {:pid => pid, :utime => utime_proc}
end

Выходной хеш должен выглядеть так:

{"domain1"=>[{:pid=>2, :utime=>20}, {:pid=>1, :utime=>10}], "domain2"=>[{:pid=>1, :utime=>10}, {:pid=>3, :utime=>30}]}

Теперь мне нужно помочь с: 1. возможно, сравните эти два хэша, и если PID для disseapear, мне нужно удалить их из хэша «h2», а его последнее значение utime суммируется со значением utime, хранящимся в «h1». 2. Если для домена появился новый PID (в 'h3' новый pid, а в 'h2' еще нет), добавьте этот PID в 'h2' с его utime для конкретного домена.

И это пункты, которые я не могу сделать. Я знаю, что могу просто сделать:

'h2-h3' или 'h3-h2', но я не знаю, что делать с результатом и как с ним обращаться.

Ребята, вы можете мне помочь, пожалуйста? Короткая версия моего кода ниже. Я все еще рубиновый новичок.

h1 = {}
# Hash to collect PID and its utimes
h2 = {}

loop do  

# Hash to temporarly store PID and its utimes - in each cycle is reseting
h3 = {}

# Here I collect processes
#############
#############

# Collect PIDs and its utimes
# Store PIDs and its utimes temporarly - only for this loop round
h3[vhostname] = []
h3[vhostname] << {:pid => pid, :utime => utime_proc}

# is h2 empty? if so, this is probably first loop round
if not h2.key?(vhostname)
h2[vhostname] = []
h2[vhostname] << {:pid => pid, :utime => utime_proc}
else
# h2 is not empty, we can diff and sum
# PROBABLY PLACE I NEED TO HELP WITH

end
# Here I do some more magic with h1 and output the result with some delay
end

ОБНОВЛЕНИЕ

Я изменил хеш-структуру h2 и h3 на:

{:domain => "domain1.com", :pid => XXXX, :utime => YYYYY}

person Brian    schedule 17.09.2018    source источник
comment
Как я уже говорил, ожидаемый результат — это имя домена и его совокупное время использования, другими словами: сколько процессоров utime потребляют все процессы PHP для определенного домена во время выполнения этого скрипта.   -  person Brian    schedule 17.09.2018


Ответы (1)


Я не буду пытаться реализовать вашу логику, но попытаюсь объяснить, что касается хэшей. Для простоты я не зацикливался, а просто имел дело с тестовыми данными

domains = ['domain1','domain2','domain3']

h1 = {}
h2 = {}
# generate blank template for each domain
domains.each { |vhostname|
  h1[vhostname] ||= { :utime => 0, :last_seen => 0, :process_count => 0, :process_count_avg => 0 }
  h2[vhostname] ||= {}
}

# dummy loop
1.upto(5) {
  h3={}
  # start collecting data for each domain
  domains.each { |vhostname|
    # TEST DATA
    h3[vhostname] ||= {}
    1.upto(5) {
      _pid = rand(1..10)
      h3[vhostname][:"#{_pid}"] ||= {:utime => rand(9999)}
    }
    # TEST DATA

    h2[vhostname].merge!(h3[vhostname])
    h2[vhostname].each { |proc, details|
      unless h3[vhostname].key?(proc)
        h1[vhostname][:utime] = h1[vhostname][:utime] + details[:utime]
      end
    }
    h2[vhostname] = h2[vhostname].keep_if { |proc| h3[vhostname].key?(proc)}
  }
}
person Chiranjib    schedule 17.09.2018
comment
Спасибо @Chiranjib, ваш код выглядит очень полезным. Могу я попросить вас изменить структуру хэшей в вашем коде, чтобы она была такой же, как у меня? Я обновил свой пост и немного уточнил, как выглядят хэши. Благодарю вас! - person Brian; 17.09.2018
comment
Эй, @Brian, немного изменил. Вы должны понять идею и попробовать реализовать логику самостоятельно. Кроме того, пожалуйста, примите ответ, если он поможет. - person Chiranjib; 17.09.2018
comment
Спасибо еще раз. Я имею в виду хеш-структуру, а не имена. Например, это мой хэш: domain1 =› [ {:pid =› XXX, :utime =› ZZZ }, {:pid =› XXX1, :utime =› ZZZ1 } ], domain2 =› [ {:pid =› XXX , :utime =› ZZZ }, {:pid =› XXX1, :utime =› ZZZ1 } ] и ваш выглядит немного иначе. Также мой хэш h1 выглядит немного иначе. Извините за это, я действительно рубиновый новичок. Я действительно ценю твою помощь. - person Brian; 17.09.2018
comment
Я думал, вам нужно кумулятивное время использования для домена, похоже, вы также хотите собирать информацию о pid для домена? Тут вопрос очень неясен. В комментарии выше «domain1» — это не хэш, а массив хэшей. Если это так, то h1 должен иметь такую ​​структуру, как h1 = {:domain1 =› [...], :domain2 =› [...]} - person Chiranjib; 17.09.2018
comment
Да, но для того, чтобы узнать совокупное время безотказной работы для домена, мне нужно также знать pids и его время безотказной работы, а также знать, является ли процесс новым или исчезнувшим, и на основе этого я могу суммировать его время безотказной работы с общим количеством времени безотказной работы. Ваш пример хорош, но не полностью соответствует моим хэшам и массиву хэшей. Я обновил свой пост еще раз. h2 и h3 должны иметь вид {domain1=›[{:pid=›2, :utime=›20}, {:pid=›1, :utime=›10}], domain2=›[{:pid=›1 , :utime=›10}, {:pid=›3, :utime=›30}]} Пожалуйста, проверьте пример кода в моем посте еще раз. Прошу прощения за нечеткое описание - person Brian; 17.09.2018
comment
Изменил свой ответ еще раз, похоже, сейчас я пишу ваш код для вас. Пожалуйста, закройте этот вопрос. Ваша проблема кажется более специфичной для логики приложения и не связана с Ruby (или любым другим языком в этом отношении). Надеюсь, это поможет! - person Chiranjib; 19.09.2018