Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]
Groups > linux.kernel > #1730544 > unrolled thread
| Started by | David Rientjes <rientjes@google.com> |
|---|---|
| First post | 2017-09-11 22:50 +0200 |
| Last post | 2017-09-23 10:20 +0200 |
| Articles | 20 on this page of 30 — 4 participants |
Back to article view | Back to linux.kernel
This discussion starts older than the indexed window; earlier articles aren't shown. The article labeled Started by
below is the oldest one visible, not the original post.
Re: [v8 0/4] cgroup-aware OOM killer David Rientjes <rientjes@google.com> - 2017-09-11 22:50 +0200
Re: [v8 0/4] cgroup-aware OOM killer Michal Hocko <mhocko@kernel.org> - 2017-09-13 14:30 +0200
Re: [v8 0/4] cgroup-aware OOM killer David Rientjes <rientjes@google.com> - 2017-09-13 22:50 +0200
Re: [v8 0/4] cgroup-aware OOM killer Michal Hocko <mhocko@kernel.org> - 2017-09-14 15:40 +0200
Re: [v8 0/4] cgroup-aware OOM killer David Rientjes <rientjes@google.com> - 2017-09-14 22:10 +0200
Re: [v8 0/4] cgroup-aware OOM killer Michal Hocko <mhocko@kernel.org> - 2017-09-14 15:50 +0200
Re: [v8 0/4] cgroup-aware OOM killer Michal Hocko <mhocko@kernel.org> - 2017-09-15 13:00 +0200
Re: [v8 0/4] cgroup-aware OOM killer David Rientjes <rientjes@google.com> - 2017-09-15 22:00 +0200
Re: [v8 0/4] cgroup-aware OOM killer Michal Hocko <mhocko@kernel.org> - 2017-09-18 08:20 +0200
Re: [v8 0/4] cgroup-aware OOM killer David Rientjes <rientjes@google.com> - 2017-09-19 23:00 +0200
Re: [v8 0/4] cgroup-aware OOM killer Michal Hocko <mhocko@kernel.org> - 2017-09-18 08:30 +0200
Re: [v8 0/4] cgroup-aware OOM killer David Rientjes <rientjes@google.com> - 2017-09-21 10:40 +0200
Re: [v8 0/4] cgroup-aware OOM killer David Rientjes <rientjes@google.com> - 2017-09-19 23:00 +0200
Re: [v8 0/4] cgroup-aware OOM killer David Rientjes <rientjes@google.com> - 2017-09-21 10:30 +0200
Re: [v8 0/4] cgroup-aware OOM killer Michal Hocko <mhocko@kernel.org> - 2017-09-18 08:20 +0200
Re: [v8 0/4] cgroup-aware OOM killer Michal Hocko <mhocko@kernel.org> - 2017-09-25 14:30 +0200
Re: [v8 0/4] cgroup-aware OOM killer Johannes Weiner <hannes@cmpxchg.org> - 2017-09-25 19:10 +0200
Re: [v8 0/4] cgroup-aware OOM killer Michal Hocko <mhocko@kernel.org> - 2017-09-25 22:30 +0200
Re: [v8 0/4] cgroup-aware OOM killer Michal Hocko <mhocko@kernel.org> - 2017-09-26 13:30 +0200
Re: [v8 0/4] cgroup-aware OOM killer Michal Hocko <mhocko@kernel.org> - 2017-09-26 15:40 +0200
Re: [v8 0/4] cgroup-aware OOM killer David Rientjes <rientjes@google.com> - 2017-09-26 00:30 +0200
Re: [v8 0/4] cgroup-aware OOM killer Michal Hocko <mhocko@kernel.org> - 2017-09-26 10:50 +0200
Re: [v8 0/4] cgroup-aware OOM killer Johannes Weiner <hannes@cmpxchg.org> - 2017-09-21 16:30 +0200
Re: [v8 0/4] cgroup-aware OOM killer David Rientjes <rientjes@google.com> - 2017-09-21 23:20 +0200
Re: [v8 0/4] cgroup-aware OOM killer Johannes Weiner <hannes@cmpxchg.org> - 2017-09-22 00:00 +0200
Re: [v8 0/4] cgroup-aware OOM killer David Rientjes <rientjes@google.com> - 2017-09-22 23:00 +0200
Re: [v8 0/4] cgroup-aware OOM killer Tejun Heo <tj@kernel.org> - 2017-09-22 17:50 +0200
Re: [v8 0/4] cgroup-aware OOM killer David Rientjes <rientjes@google.com> - 2017-09-22 22:50 +0200
Re: [v8 0/4] cgroup-aware OOM killer Tejun Heo <tj@kernel.org> - 2017-09-22 23:10 +0200
Re: [v8 0/4] cgroup-aware OOM killer David Rientjes <rientjes@google.com> - 2017-09-23 10:20 +0200
Page 1 of 2 [1] 2 Next page →
| From | David Rientjes <rientjes@google.com> |
|---|---|
| Date | 2017-09-11 22:50 +0200 |
| Subject | Re: [v8 0/4] cgroup-aware OOM killer |
| Message-ID | <uoDOy-8jm-9@gated-at.bofh.it> |
On Mon, 11 Sep 2017, Roman Gushchin wrote: > This patchset makes the OOM killer cgroup-aware. > > v8: > - Do not kill tasks with OOM_SCORE_ADJ -1000 > - Make the whole thing opt-in with cgroup mount option control > - Drop oom_priority for further discussions Nack, we specifically require oom_priority for this to function correctly, otherwise we cannot prefer to kill from low priority leaf memcgs as required. v8 appears to implement new functionality that we want, to compare two memcgs based on usage, but without the ability to influence that decision to protect important userspace, so now I'm in a position where (1) nothing has changed if I don't use the new mount option or (2) I get completely different oom kill selection with the new mount option but not the ability to influence it. I was much happier with the direction that v7 was taking, but since v8 causes us to regress without the ability to change memcg priority, this has to be nacked. > - Kill the whole cgroup if oom_group is set and it's > memory.max is reached > - Update docs and commit messages
[toc] | [next] | [standalone]
| From | Michal Hocko <mhocko@kernel.org> |
|---|---|
| Date | 2017-09-13 14:30 +0200 |
| Message-ID | <upeXN-7iZ-17@gated-at.bofh.it> |
| In reply to | #1730544 |
On Mon 11-09-17 13:44:39, David Rientjes wrote: > On Mon, 11 Sep 2017, Roman Gushchin wrote: > > > This patchset makes the OOM killer cgroup-aware. > > > > v8: > > - Do not kill tasks with OOM_SCORE_ADJ -1000 > > - Make the whole thing opt-in with cgroup mount option control > > - Drop oom_priority for further discussions > > Nack, we specifically require oom_priority for this to function correctly, > otherwise we cannot prefer to kill from low priority leaf memcgs as > required. While I understand that your usecase might require priorities I do not think this part missing is a reason to nack the cgroup based selection and kill-all parts. This can be done on top. The only important part right now is the current selection semantic - only leaf memcgs vs. size of the hierarchy). I strongly believe that comparing only leaf memcgs is more straightforward and it doesn't lead to unexpected results as mentioned before (kill a small memcg which is a part of the larger sub-hierarchy). I didn't get to read the new version of this series yet and hope to get to it soon. -- Michal Hocko SUSE Labs
[toc] | [prev] | [next] | [standalone]
| From | David Rientjes <rientjes@google.com> |
|---|---|
| Date | 2017-09-13 22:50 +0200 |
| Message-ID | <upmLE-3Lv-21@gated-at.bofh.it> |
| In reply to | #1731588 |
On Wed, 13 Sep 2017, Michal Hocko wrote: > > > This patchset makes the OOM killer cgroup-aware. > > > > > > v8: > > > - Do not kill tasks with OOM_SCORE_ADJ -1000 > > > - Make the whole thing opt-in with cgroup mount option control > > > - Drop oom_priority for further discussions > > > > Nack, we specifically require oom_priority for this to function correctly, > > otherwise we cannot prefer to kill from low priority leaf memcgs as > > required. > > While I understand that your usecase might require priorities I do not > think this part missing is a reason to nack the cgroup based selection > and kill-all parts. This can be done on top. The only important part > right now is the current selection semantic - only leaf memcgs vs. size > of the hierarchy). I strongly believe that comparing only leaf memcgs > is more straightforward and it doesn't lead to unexpected results as > mentioned before (kill a small memcg which is a part of the larger > sub-hierarchy). > The problem is that we cannot enable the cgroup-aware oom killer and oom_group behavior because, without oom priorities, we have no ability to influence the cgroup that it chooses. It is doing two things: providing more fairness amongst cgroups by selecting based on cumulative usage rather than single large process (good!), and effectively is removing all userspace control of oom selection (bad). We want the former, but it needs to be coupled with support so that we can protect vital cgroups, regardless of their usage. It is certainly possible to add oom priorities on top before it is merged, but I don't see why it isn't part of the patchset. We need it before its merged to avoid users playing with /proc/pid/oom_score_adj to prevent any killing in the most preferable memcg when they could have simply changed the oom priority.
[toc] | [prev] | [next] | [standalone]
| From | Michal Hocko <mhocko@kernel.org> |
|---|---|
| Date | 2017-09-14 15:40 +0200 |
| Message-ID | <upCx4-5BF-17@gated-at.bofh.it> |
| In reply to | #1731853 |
On Wed 13-09-17 13:46:08, David Rientjes wrote: > On Wed, 13 Sep 2017, Michal Hocko wrote: > > > > > This patchset makes the OOM killer cgroup-aware. > > > > > > > > v8: > > > > - Do not kill tasks with OOM_SCORE_ADJ -1000 > > > > - Make the whole thing opt-in with cgroup mount option control > > > > - Drop oom_priority for further discussions > > > > > > Nack, we specifically require oom_priority for this to function correctly, > > > otherwise we cannot prefer to kill from low priority leaf memcgs as > > > required. > > > > While I understand that your usecase might require priorities I do not > > think this part missing is a reason to nack the cgroup based selection > > and kill-all parts. This can be done on top. The only important part > > right now is the current selection semantic - only leaf memcgs vs. size > > of the hierarchy). I strongly believe that comparing only leaf memcgs > > is more straightforward and it doesn't lead to unexpected results as > > mentioned before (kill a small memcg which is a part of the larger > > sub-hierarchy). > > > > The problem is that we cannot enable the cgroup-aware oom killer and > oom_group behavior because, without oom priorities, we have no ability to > influence the cgroup that it chooses. It is doing two things: providing > more fairness amongst cgroups by selecting based on cumulative usage > rather than single large process (good!), and effectively is removing all > userspace control of oom selection (bad). We want the former, but it > needs to be coupled with support so that we can protect vital cgroups, > regardless of their usage. I understand that your usecase needs a more fine grained control over the selection but that alone is not a reason to nack the implementation which doesn't provide it (yet). > It is certainly possible to add oom priorities on top before it is merged, > but I don't see why it isn't part of the patchset. Because the semantic of the priority for non-leaf memcgs is not fully clear and I would rather have the core of the functionality merged before this is sorted out. > We need it before its > merged to avoid users playing with /proc/pid/oom_score_adj to prevent any > killing in the most preferable memcg when they could have simply changed > the oom priority. I am sorry but I do not really understand your concern. Are you suggesting that users would start oom disable all tasks in a memcg to give it a higher priority? Even if that was the case why should such an abuse be a blocker for generic memcg aware oom killer being merged? -- Michal Hocko SUSE Labs
[toc] | [prev] | [next] | [standalone]
| From | David Rientjes <rientjes@google.com> |
|---|---|
| Date | 2017-09-14 22:10 +0200 |
| Message-ID | <upICt-19d-11@gated-at.bofh.it> |
| In reply to | #1732277 |
On Thu, 14 Sep 2017, Michal Hocko wrote: > > It is certainly possible to add oom priorities on top before it is merged, > > but I don't see why it isn't part of the patchset. > > Because the semantic of the priority for non-leaf memcgs is not fully > clear and I would rather have the core of the functionality merged > before this is sorted out. > We can't merge the core of the feature before this is sorted out because then users start to depend on behavior and we must be backwards compatible. We need a full patchset that introduces the new selection heuristic and a way for userspace to control it to either bias or prefer one cgroup over another. The kill-all mechanism is a more orthogonal feature for the cgroup-aware oom killer than oom priorities. I have a usecase for both the cgroup-aware oom killer and its oom priorities from previous versions of this patchset, I assume that Roman does as well, and would like to see it merged bacause there are real-world usecases for it rather than hypothetical usecases that would want to do something different. > > We need it before its > > merged to avoid users playing with /proc/pid/oom_score_adj to prevent any > > killing in the most preferable memcg when they could have simply changed > > the oom priority. > > I am sorry but I do not really understand your concern. Are you > suggesting that users would start oom disable all tasks in a memcg to > give it a higher priority? Even if that was the case why should such an > abuse be a blocker for generic memcg aware oom killer being merged? If users do not have any way to control victim selection because of a shortcoming in the kernel implementation, they will be required to oom disable processes and let that be inherited by children they fork in the memcg hierarchy to protect cgroups that they do not want to be oom killed, regardless of their size. They simply are left with no other alternative if they want to use the cgroup-aware oom killer and/or the kill-all mechanism.
[toc] | [prev] | [next] | [standalone]
| From | Michal Hocko <mhocko@kernel.org> |
|---|---|
| Date | 2017-09-14 15:50 +0200 |
| Message-ID | <upCGK-5GI-29@gated-at.bofh.it> |
| In reply to | #1731588 |
On Wed 13-09-17 14:56:07, Roman Gushchin wrote: > On Wed, Sep 13, 2017 at 02:29:14PM +0200, Michal Hocko wrote: [...] > > I strongly believe that comparing only leaf memcgs > > is more straightforward and it doesn't lead to unexpected results as > > mentioned before (kill a small memcg which is a part of the larger > > sub-hierarchy). > > One of two main goals of this patchset is to introduce cgroup-level > fairness: bigger cgroups should be affected more than smaller, > despite the size of tasks inside. I believe the same principle > should be used for cgroups. Yes bigger cgroups should be preferred but I fail to see why bigger hierarchies should be considered as well if they are not kill-all. And whether non-leaf memcgs should allow kill-all is not entirely clear to me. What would be the usecase? Consider that it might be not your choice (as a user) how deep is your leaf memcg. I can already see how people complain that their memcg has been killed just because it was one level deeper in the hierarchy... I would really start simple and only allow kill-all on leaf memcgs and only compare leaf memcgs & root. If we ever need to kill whole hierarchies then allow kill-all on intermediate memcgs as well and then consider cumulative consumptions only on those that have kill-all enabled. Or do I miss any reasonable usecase that would suffer from such a semantic? -- Michal Hocko SUSE Labs
[toc] | [prev] | [next] | [standalone]
| From | Michal Hocko <mhocko@kernel.org> |
|---|---|
| Date | 2017-09-15 13:00 +0200 |
| Message-ID | <upWvL-1En-5@gated-at.bofh.it> |
| In reply to | #1732281 |
On Thu 14-09-17 09:05:48, Roman Gushchin wrote:
> On Thu, Sep 14, 2017 at 03:40:14PM +0200, Michal Hocko wrote:
> > On Wed 13-09-17 14:56:07, Roman Gushchin wrote:
> > > On Wed, Sep 13, 2017 at 02:29:14PM +0200, Michal Hocko wrote:
> > [...]
> > > > I strongly believe that comparing only leaf memcgs
> > > > is more straightforward and it doesn't lead to unexpected results as
> > > > mentioned before (kill a small memcg which is a part of the larger
> > > > sub-hierarchy).
> > >
> > > One of two main goals of this patchset is to introduce cgroup-level
> > > fairness: bigger cgroups should be affected more than smaller,
> > > despite the size of tasks inside. I believe the same principle
> > > should be used for cgroups.
> >
> > Yes bigger cgroups should be preferred but I fail to see why bigger
> > hierarchies should be considered as well if they are not kill-all. And
> > whether non-leaf memcgs should allow kill-all is not entirely clear to
> > me. What would be the usecase?
>
> We definitely want to support kill-all for non-leaf cgroups.
> A workload can consist of several cgroups and we want to clean up
> the whole thing on OOM.
Could you be more specific about such a workload? E.g. how can be such a
hierarchy handled consistently when its sub-tree gets killed due to
internal memory pressure? Or do you expect that none of the subtree will
have hard limit configured?
> I don't see any reasons to limit this functionality to leaf cgroups
> only.
Well, I wanted to start simple first and extend on top. Memcg v1 is full
of seemingly interesting and very generic concepts which turned out
being a headache long term.
> Hierarchies are memory consumers, we do account their usage,
> we do apply limits and guarantees for the hierarchies. The same is
> with OOM victim selection: we are reclaiming memory from the
> biggest consumer. Kill-all knob only defines the way _how_ we do that:
> by killing one or all processes.
But then you just enforce a structural restriction on your configuration
because
root
/ \
A D
/\
B C
is a different thing than
root
/ | \
B C D
And consider that the sole purpose of A might be a control over
a non-memory resource (e.g. a cpu share distribution). Why should we
discriminate B and C in such a case?
> Just for example, we might want to take memory.low into account at
> some point: prefer cgroups which are above their guarantees, avoid
> killing those who fit. It would be hard if we're comparing cgroups
> from different hierarchies.
This can be reflected in the memcg oom score calculation I believe. We
already do something similar during the reclaim.
> The same will be with introducing oom_priorities, which is much more
> required functionality.
More on that below.
> > Consider that it might be not your choice (as a user) how deep is your
> > leaf memcg. I can already see how people complain that their memcg has
> > been killed just because it was one level deeper in the hierarchy...
>
> The kill-all functionality is enforced by parent, and it seems to be
> following the overall memcg design. The parent cgroup enforces memory
> limit, memory low limit, etc.
And the same is true for the memcg oom killer. It enforces the selection
to the out-of-memory subtree. We are trying to be proportional on the
size of the _reclaimable_ memory in that scope. Same way as with the
LRU reclaim. We do not prefer larger hierarchies over smaller. We just
iterate over those that have pages on LRUs (leaf memcgs with v2) and
scan/reclaim proportionally to their size. Why should the oom killer
decision be any different in that regards?
> I don't know why OOM control should be different.
I am not arguing that kill-all functionality on non-leaf is wrong. I
just haven't heard the usecase for it yet. I am also not opposed to
consider the cumulative size of non-leaf memcg if it is kill-all as the
cumulative size will be reclaimed then. But I fail to see why we should
prefer larger hierarchies when the resulting memcg victim is much
smaller in the end.
> > I would really start simple and only allow kill-all on leaf memcgs and
> > only compare leaf memcgs & root. If we ever need to kill whole
> > hierarchies then allow kill-all on intermediate memcgs as well and then
> > consider cumulative consumptions only on those that have kill-all
> > enabled.
>
> This sounds hacky to me: the whole thing is depending on cgroup v2 and
> is additionally explicitly opt-in.
>
> Why do we need to introduce such incomplete functionality first,
> and then suffer trying to extend it and provide backward compatibility?
Why would a backward compatibility be a problem? kill-all on non-leaf
memcgs should be seamless. We would simply allow setting the knob. Adding
a priority shouldn't be a problem either. A new knob would be added. Any
memcg with a non-zero priority would be considered during selection for
example (cumulative size would be considered as a tie-breaker for
non-leaf memcgs and a victim selected from the largest hierarchy/leaf
memcg - but that really needs to be thought through and hear about
specific usecases).
> Also, I think we should compare root cgroup with top-level cgroups,
> rather than leaf cgroups. A process in the root cgroup is definitely
> system-level entity, and we should compare it with other top-level
> entities (other containerized workloads), rather then some random
> leaf cgroup deep inside the tree. If we decided, that we're not comparing
> random tasks from different cgroups, why should we do this for leaf
> cgroups? Is sounds like making only one step towards right direction,
> while we can do more.
The main problem I have with that is mentioned above. A single hierarchy
enforces some structural constrains when multiple controllers are in
place.
--
Michal Hocko
SUSE Labs
[toc] | [prev] | [next] | [standalone]
| From | David Rientjes <rientjes@google.com> |
|---|---|
| Date | 2017-09-15 22:00 +0200 |
| Message-ID | <uq4Wm-7vc-5@gated-at.bofh.it> |
| In reply to | #1732817 |
On Fri, 15 Sep 2017, Roman Gushchin wrote: > > But then you just enforce a structural restriction on your configuration > > because > > root > > / \ > > A D > > /\ > > B C > > > > is a different thing than > > root > > / | \ > > B C D > > > > I actually don't have a strong argument against an approach to select > largest leaf or kill-all-set memcg. I think, in practice there will be > no much difference. > > The only real concern I have is that then we have to do the same with > oom_priorities (select largest priority tree-wide), and this will limit > an ability to enforce the priority by parent cgroup. > Yes, oom_priority cannot select the largest priority tree-wide for exactly that reason. We need the ability to control from which subtree the kill occurs in ancestor cgroups. If multiple jobs are allocated their own cgroups and they can own memory.oom_priority for their own subcontainers, this becomes quite powerful so they can define their own oom priorities. Otherwise, they can easily override the oom priorities of other cgroups.
[toc] | [prev] | [next] | [standalone]
| From | Michal Hocko <mhocko@kernel.org> |
|---|---|
| Date | 2017-09-18 08:20 +0200 |
| Message-ID | <uqXzr-257-5@gated-at.bofh.it> |
| In reply to | #1733063 |
On Fri 15-09-17 12:55:55, David Rientjes wrote: > On Fri, 15 Sep 2017, Roman Gushchin wrote: > > > > But then you just enforce a structural restriction on your configuration > > > because > > > root > > > / \ > > > A D > > > /\ > > > B C > > > > > > is a different thing than > > > root > > > / | \ > > > B C D > > > > > > > I actually don't have a strong argument against an approach to select > > largest leaf or kill-all-set memcg. I think, in practice there will be > > no much difference. > > > > The only real concern I have is that then we have to do the same with > > oom_priorities (select largest priority tree-wide), and this will limit > > an ability to enforce the priority by parent cgroup. > > > > Yes, oom_priority cannot select the largest priority tree-wide for exactly > that reason. We need the ability to control from which subtree the kill > occurs in ancestor cgroups. If multiple jobs are allocated their own > cgroups and they can own memory.oom_priority for their own subcontainers, > this becomes quite powerful so they can define their own oom priorities. > Otherwise, they can easily override the oom priorities of other cgroups. Could you be more speicific about your usecase? What would be a problem If we allow to only increase priority in children (like other hierarchical controls). -- Michal Hocko SUSE Labs
[toc] | [prev] | [next] | [standalone]
| From | David Rientjes <rientjes@google.com> |
|---|---|
| Date | 2017-09-19 23:00 +0200 |
| Message-ID | <urxMB-1ME-7@gated-at.bofh.it> |
| In reply to | #1733663 |
On Mon, 18 Sep 2017, Michal Hocko wrote:
> > > > But then you just enforce a structural restriction on your configuration
> > > > because
> > > > root
> > > > / \
> > > > A D
> > > > /\
> > > > B C
> > > >
> > > > is a different thing than
> > > > root
> > > > / | \
> > > > B C D
> > > >
> > >
> > > I actually don't have a strong argument against an approach to select
> > > largest leaf or kill-all-set memcg. I think, in practice there will be
> > > no much difference.
> > >
> > > The only real concern I have is that then we have to do the same with
> > > oom_priorities (select largest priority tree-wide), and this will limit
> > > an ability to enforce the priority by parent cgroup.
> > >
> >
> > Yes, oom_priority cannot select the largest priority tree-wide for exactly
> > that reason. We need the ability to control from which subtree the kill
> > occurs in ancestor cgroups. If multiple jobs are allocated their own
> > cgroups and they can own memory.oom_priority for their own subcontainers,
> > this becomes quite powerful so they can define their own oom priorities.
> > Otherwise, they can easily override the oom priorities of other cgroups.
>
> Could you be more speicific about your usecase? What would be a
> problem If we allow to only increase priority in children (like other
> hierarchical controls).
>
For memcg constrained oom conditions, there is only a theoretical issue if
the subtree is not under the control of a single user and various users
can alter their priorities without knowledge of the priorities of other
children in the same subtree that is oom, or those values change without
knowledge of a child. I don't know of anybody that configures memory
cgroup hierarchies that way, though.
The problem is more obvious in system oom conditions. If we have two
top-level memory cgroups with the same "job" priority, they get the same
oom priority. The user who configures subcontainers is now always
targeted for oom kill in an "increase priority in children" policy.
The hierarchy becomes this:
root
/ \
A D
/ \ / | \
B C E F G
where A/memory.oom_priority == D/memory.oom_priority.
D wants to kill in order of E -> F -> G, but can't configure that if
B = A - 1 and C = B - 1. It also shouldn't need to adjust its own oom
priorities based on a hierarchy outside its control and which can change
at any time at the discretion of the user (with namespaces you may not
even be able to access it).
But also if A/memory.oom_priority = D/memory.oom_priority - 100, A is
preferred unless its subcontainers configure themselves in a way where
they have higher oom priority values than E, F, and G. That may yield
very different results when additional jobs get scheduled on the system
(and H tree) where the user has full control over their own oom
priorities, even when the value must only increase.
[toc] | [prev] | [next] | [standalone]
| From | Michal Hocko <mhocko@kernel.org> |
|---|---|
| Date | 2017-09-18 08:30 +0200 |
| Message-ID | <uqXJ8-29z-3@gated-at.bofh.it> |
| In reply to | #1733063 |
On Fri 15-09-17 14:08:07, Roman Gushchin wrote: > On Fri, Sep 15, 2017 at 12:55:55PM -0700, David Rientjes wrote: > > On Fri, 15 Sep 2017, Roman Gushchin wrote: > > > > > > But then you just enforce a structural restriction on your configuration > > > > because > > > > root > > > > / \ > > > > A D > > > > /\ > > > > B C > > > > > > > > is a different thing than > > > > root > > > > / | \ > > > > B C D > > > > > > > > > > I actually don't have a strong argument against an approach to select > > > largest leaf or kill-all-set memcg. I think, in practice there will be > > > no much difference. > > > > > > The only real concern I have is that then we have to do the same with > > > oom_priorities (select largest priority tree-wide), and this will limit > > > an ability to enforce the priority by parent cgroup. > > > > > > > Yes, oom_priority cannot select the largest priority tree-wide for exactly > > that reason. We need the ability to control from which subtree the kill > > occurs in ancestor cgroups. If multiple jobs are allocated their own > > cgroups and they can own memory.oom_priority for their own subcontainers, > > this becomes quite powerful so they can define their own oom priorities. > > Otherwise, they can easily override the oom priorities of other cgroups. > > I believe, it's a solvable problem: we can require CAP_SYS_RESOURCE to set > the oom_priority below parent's value, or something like this. As said in other email. We can make priorities hierarchical (in the same sense as hard limit or others) so that children cannot override their parent. > But it looks more complex, and I'm not sure there are real examples, > when we have to compare memcgs, which are on different levels > (or in different subtrees). Well, I have given you one that doesn't sounds completely insane to me in other email. You may need an intermediate level for other than memcg controller. The whole concept of significance of the hierarchy level seems really odd to me. Or am I wrong here? -- Michal Hocko SUSE Labs
[toc] | [prev] | [next] | [standalone]
| From | David Rientjes <rientjes@google.com> |
|---|---|
| Date | 2017-09-21 10:40 +0200 |
| Message-ID | <us5bz-6U3-5@gated-at.bofh.it> |
| In reply to | #1733666 |
On Mon, 18 Sep 2017, Roman Gushchin wrote: > > As said in other email. We can make priorities hierarchical (in the same > > sense as hard limit or others) so that children cannot override their > > parent. > > You mean they can set the knob to any value, but parent's value is enforced, > if it's greater than child's value? > > If so, this sounds logical to me. Then we have size-based comparison and > priority-based comparison with similar rules, and all use cases are covered. > > Ok, can we stick with this design? > Then I'll return oom_priorities in place, and post a (hopefully) final version. > I just want to make sure that we are going with your original implementation here: that oom_priority is only effective for compare sibling memory cgroups and nothing beyond that. The value alone has no relationship to any ancestor. We can't set oom_priority based on the priorities of any other memory cgroups other than our own siblings because we have no control over how those change.
[toc] | [prev] | [next] | [standalone]
| From | David Rientjes <rientjes@google.com> |
|---|---|
| Date | 2017-09-19 23:00 +0200 |
| Message-ID | <urxMC-1ME-11@gated-at.bofh.it> |
| In reply to | #1733063 |
On Fri, 15 Sep 2017, Roman Gushchin wrote: > > > > But then you just enforce a structural restriction on your configuration > > > > because > > > > root > > > > / \ > > > > A D > > > > /\ > > > > B C > > > > > > > > is a different thing than > > > > root > > > > / | \ > > > > B C D > > > > > > > > > > I actually don't have a strong argument against an approach to select > > > largest leaf or kill-all-set memcg. I think, in practice there will be > > > no much difference. > > > > > > The only real concern I have is that then we have to do the same with > > > oom_priorities (select largest priority tree-wide), and this will limit > > > an ability to enforce the priority by parent cgroup. > > > > > > > Yes, oom_priority cannot select the largest priority tree-wide for exactly > > that reason. We need the ability to control from which subtree the kill > > occurs in ancestor cgroups. If multiple jobs are allocated their own > > cgroups and they can own memory.oom_priority for their own subcontainers, > > this becomes quite powerful so they can define their own oom priorities. > > Otherwise, they can easily override the oom priorities of other cgroups. > > I believe, it's a solvable problem: we can require CAP_SYS_RESOURCE to set > the oom_priority below parent's value, or something like this. > > But it looks more complex, and I'm not sure there are real examples, > when we have to compare memcgs, which are on different levels > (or in different subtrees). > It's actually much more complex because in our environment we'd need an "activity manager" with CAP_SYS_RESOURCE to control oom priorities of user subcontainers when today it need only be concerned with top-level memory cgroups. Users can create their own hierarchies with their own oom priorities at will, it doesn't alter the selection heuristic for another other user running on the same system and gives them full control over the selection in their own subtree. We shouldn't need to have a system-wide daemon with CAP_SYS_RESOURCE be required to manage subcontainers when nothing else requires it. I believe it's also much easier to document: oom_priority is considered for all sibling cgroups at each level of the hierarchy and the cgroup with the lowest priority value gets iterated.
[toc] | [prev] | [next] | [standalone]
| From | David Rientjes <rientjes@google.com> |
|---|---|
| Date | 2017-09-21 10:30 +0200 |
| Message-ID | <us51V-6Qs-27@gated-at.bofh.it> |
| In reply to | #1735257 |
On Wed, 20 Sep 2017, Roman Gushchin wrote: > > It's actually much more complex because in our environment we'd need an > > "activity manager" with CAP_SYS_RESOURCE to control oom priorities of user > > subcontainers when today it need only be concerned with top-level memory > > cgroups. Users can create their own hierarchies with their own oom > > priorities at will, it doesn't alter the selection heuristic for another > > other user running on the same system and gives them full control over the > > selection in their own subtree. We shouldn't need to have a system-wide > > daemon with CAP_SYS_RESOURCE be required to manage subcontainers when > > nothing else requires it. I believe it's also much easier to document: > > oom_priority is considered for all sibling cgroups at each level of the > > hierarchy and the cgroup with the lowest priority value gets iterated. > > I do agree actually. System-wide OOM priorities make no sense. > > Always compare sibling cgroups, either by priority or size, seems to be > simple, clear and powerful enough for all reasonable use cases. Am I right, > that it's exactly what you've used internally? This is a perfect confirmation, > I believe. > We've used it for at least four years, I added my Tested-by to your patch, we would convert to your implementation if it is merged upstream, and I would enthusiastically support your patch if you would integrate it back into your series.
[toc] | [prev] | [next] | [standalone]
| From | Michal Hocko <mhocko@kernel.org> |
|---|---|
| Date | 2017-09-18 08:20 +0200 |
| Message-ID | <uqXzs-257-9@gated-at.bofh.it> |
| In reply to | #1732817 |
On Fri 15-09-17 08:23:01, Roman Gushchin wrote: > On Fri, Sep 15, 2017 at 12:58:26PM +0200, Michal Hocko wrote: > > On Thu 14-09-17 09:05:48, Roman Gushchin wrote: > > > On Thu, Sep 14, 2017 at 03:40:14PM +0200, Michal Hocko wrote: > > > > On Wed 13-09-17 14:56:07, Roman Gushchin wrote: > > > > > On Wed, Sep 13, 2017 at 02:29:14PM +0200, Michal Hocko wrote: > > > > [...] > > > > > > I strongly believe that comparing only leaf memcgs > > > > > > is more straightforward and it doesn't lead to unexpected results as > > > > > > mentioned before (kill a small memcg which is a part of the larger > > > > > > sub-hierarchy). > > > > > > > > > > One of two main goals of this patchset is to introduce cgroup-level > > > > > fairness: bigger cgroups should be affected more than smaller, > > > > > despite the size of tasks inside. I believe the same principle > > > > > should be used for cgroups. > > > > > > > > Yes bigger cgroups should be preferred but I fail to see why bigger > > > > hierarchies should be considered as well if they are not kill-all. And > > > > whether non-leaf memcgs should allow kill-all is not entirely clear to > > > > me. What would be the usecase? > > > > > > We definitely want to support kill-all for non-leaf cgroups. > > > A workload can consist of several cgroups and we want to clean up > > > the whole thing on OOM. > > > > Could you be more specific about such a workload? E.g. how can be such a > > hierarchy handled consistently when its sub-tree gets killed due to > > internal memory pressure? > > Or just system-wide OOM. > > > Or do you expect that none of the subtree will > > have hard limit configured? > > And this can also be a case: the whole workload may have hard limit > configured, while internal memcgs have only memory.low set for "soft" > prioritization. > > > > > But then you just enforce a structural restriction on your configuration > > because > > root > > / \ > > A D > > /\ > > B C > > > > is a different thing than > > root > > / | \ > > B C D > > > > I actually don't have a strong argument against an approach to select > largest leaf or kill-all-set memcg. I think, in practice there will be > no much difference. Well, I am worried that the difference will come unexpected when a deeper hierarchy is needed because of the structural needs. -- Michal Hocko SUSE Labs
[toc] | [prev] | [next] | [standalone]
| From | Michal Hocko <mhocko@kernel.org> |
|---|---|
| Date | 2017-09-25 14:30 +0200 |
| Message-ID | <utAGm-6ix-17@gated-at.bofh.it> |
| In reply to | #1733664 |
I would really appreciate some feedback from Tejun, Johannes here. On Wed 20-09-17 14:53:41, Roman Gushchin wrote: > On Mon, Sep 18, 2017 at 08:14:05AM +0200, Michal Hocko wrote: > > On Fri 15-09-17 08:23:01, Roman Gushchin wrote: > > > On Fri, Sep 15, 2017 at 12:58:26PM +0200, Michal Hocko wrote: [...] > > > > But then you just enforce a structural restriction on your configuration > > > > because > > > > root > > > > / \ > > > > A D > > > > /\ > > > > B C > > > > > > > > is a different thing than > > > > root > > > > / | \ > > > > B C D > > > > > > > > > > I actually don't have a strong argument against an approach to select > > > largest leaf or kill-all-set memcg. I think, in practice there will be > > > no much difference. > > I've tried to implement this approach, and it's really arguable. > Although your example looks reasonable, the opposite example is also valid: > you might want to compare whole hierarchies, and it's a quite typical usecase. > > Assume, you have several containerized workloads on a machine (probably, > each will be contained in a memcg with memory.max set), with some hierarchy > of cgroups inside. Then in case of global memory shortage we want to reclaim > some memory from the biggest workload, and the selection should not depend > on group_oom settings. It would be really strange, if setting group_oom will > higher the chances to be killed. > > In other words, let's imagine processes as leaf nodes in memcg tree. We decided > to select the biggest memcg and kill one or more processes inside (depending > on group_oom setting), but the memcg selection doesn't depend on it. > We do not compare processes from different cgroups, as well as cgroups with > processes. The same should apply to cgroups: why do we want to compare cgroups > from different sub-trees? > > While size-based comparison can be implemented with this approach, > the priority-based is really weird (as David mentioned). > If priorities have no hierarchical meaning at all, we lack the very important > ability to enforce hierarchy oom_priority. Otherwise we have to invent some > complex rules of oom_priority propagation (e.g. is someone is raising > the oom_priority in parent, should it be applied to children immediately, etc). I would really forget about the priority at this stage. This needs really much more thinking and I consider the David's usecase very specialized to use it as a template for a general purpose oom prioritization. I might be wrong here of course... > The oom_group knob meaning also becoms more complex. It affects both > the victim selection and OOM action. _ANY_ mechanism which allows to affect > OOM victim selection (either priorities, either bpf-based approach) should > not have global system-wide meaning, it breaks everything. > > I do understand your point, but the same is true for other stuff, right? > E.g. cpu time distribution (and io, etc) depends on hierarchy configuration. > It's a limitation, but it's ok, as user should create a hierarchy which > reflects some logical relations between processes and groups of processes. > Otherwise we're going to the configuration hell. And that is _exactly_ my concern. We surely do not want tell people that they have to consider their cgroup tree structure to control the global oom behavior. You simply do not have that constrain with leaf-only semantic and if kill-all intermediate nodes are used then there is an explicit opt-in for the hierarchy considerations. > In any case, OOM is a last resort mechanism. The goal is to reclaim some memory > and do not crash the system or do not leave it in totally broken state. > Any really complex mm in userspace should be applied _before_ OOM happens. > So, I don't think we have to support all possible configurations here, > if we're able to achieve the main goal (kill some processes and do not leave > broken systems/containers). True but we want to have the semantic reasonably understandable. And it is quite hard to explain that the oom killer hasn't selected the largest memcg just because it happened to be in a deeper hierarchy which has been configured to cover a different resource. I am sorry to repeat my self and I will not argue if there is a prevalent agreement that level-by-level comparison is considered desirable and documented behavior but, by all means, do not define this semantic based on a priority requirements and/or implementation details. -- Michal Hocko SUSE Labs
[toc] | [prev] | [next] | [standalone]
| From | Johannes Weiner <hannes@cmpxchg.org> |
|---|---|
| Date | 2017-09-25 19:10 +0200 |
| Message-ID | <utF3j-So-5@gated-at.bofh.it> |
| In reply to | #1738990 |
On Mon, Sep 25, 2017 at 02:24:00PM +0200, Michal Hocko wrote:
> I would really appreciate some feedback from Tejun, Johannes here.
>
> On Wed 20-09-17 14:53:41, Roman Gushchin wrote:
> > On Mon, Sep 18, 2017 at 08:14:05AM +0200, Michal Hocko wrote:
> > > On Fri 15-09-17 08:23:01, Roman Gushchin wrote:
> > > > On Fri, Sep 15, 2017 at 12:58:26PM +0200, Michal Hocko wrote:
> [...]
> > > > > But then you just enforce a structural restriction on your configuration
> > > > > because
> > > > > root
> > > > > / \
> > > > > A D
> > > > > /\
> > > > > B C
> > > > >
> > > > > is a different thing than
> > > > > root
> > > > > / | \
> > > > > B C D
> > > > >
> > > >
> > > > I actually don't have a strong argument against an approach to select
> > > > largest leaf or kill-all-set memcg. I think, in practice there will be
> > > > no much difference.
> >
> > I've tried to implement this approach, and it's really arguable.
> > Although your example looks reasonable, the opposite example is also valid:
> > you might want to compare whole hierarchies, and it's a quite typical usecase.
> >
> > Assume, you have several containerized workloads on a machine (probably,
> > each will be contained in a memcg with memory.max set), with some hierarchy
> > of cgroups inside. Then in case of global memory shortage we want to reclaim
> > some memory from the biggest workload, and the selection should not depend
> > on group_oom settings. It would be really strange, if setting group_oom will
> > higher the chances to be killed.
> >
> > In other words, let's imagine processes as leaf nodes in memcg tree. We decided
> > to select the biggest memcg and kill one or more processes inside (depending
> > on group_oom setting), but the memcg selection doesn't depend on it.
> > We do not compare processes from different cgroups, as well as cgroups with
> > processes. The same should apply to cgroups: why do we want to compare cgroups
> > from different sub-trees?
> >
> > While size-based comparison can be implemented with this approach,
> > the priority-based is really weird (as David mentioned).
> > If priorities have no hierarchical meaning at all, we lack the very important
> > ability to enforce hierarchy oom_priority. Otherwise we have to invent some
> > complex rules of oom_priority propagation (e.g. is someone is raising
> > the oom_priority in parent, should it be applied to children immediately, etc).
>
> I would really forget about the priority at this stage. This needs
> really much more thinking and I consider the David's usecase very
> specialized to use it as a template for a general purpose oom
> prioritization. I might be wrong here of course...
No, I agree.
> > In any case, OOM is a last resort mechanism. The goal is to reclaim some memory
> > and do not crash the system or do not leave it in totally broken state.
> > Any really complex mm in userspace should be applied _before_ OOM happens.
> > So, I don't think we have to support all possible configurations here,
> > if we're able to achieve the main goal (kill some processes and do not leave
> > broken systems/containers).
>
> True but we want to have the semantic reasonably understandable. And it
> is quite hard to explain that the oom killer hasn't selected the largest
> memcg just because it happened to be in a deeper hierarchy which has
> been configured to cover a different resource.
Going back to Michal's example, say the user configured the following:
root
/ \
A D
/ \
B C
A global OOM event happens and we find this:
- A > D
- B, C, D are oomgroups
What the user is telling us is that B, C, and D are compound memory
consumers. They cannot be divided into their task parts from a memory
point of view.
However, the user doesn't say the same for A: the A subtree summarizes
and controls aggregate consumption of B and C, but without groupoom
set on A, the user says that A is in fact divisible into independent
memory consumers B and C.
If we don't have to kill all of A, but we'd have to kill all of D,
does it make sense to compare the two?
Let's consider an extreme case of this conundrum:
root
/ \
A B
/|\ |
A1-A1000 B1
Again we find:
- A > B
- A1 to A1000 and B1 are oomgroups
But:
- A1 to A1000 individually are tiny, B1 is huge
Going level by level, we'd pick A as the bigger hierarchy in the
system, and then kill off one of the tiny groups A1 to A1000.
Conversely, going for biggest consumer regardless of hierarchy, we'd
compare A1 to A1000 and B1, then pick B1 as the biggest single atomic
memory consumer in the system and kill all its tasks.
Which one of these two fits both the purpose and our historic approach
to OOM killing better?
As was noted in this thread, OOM is the last resort to avoid a memory
deadlock. Killing the biggest consumer is most likely to resolve this
precarious situation. It is also most likely to catch buggy software
with memory leaks or runaway allocations, which is a nice bonus.
Killing a potentially tiny consumer inside the biggest top-level
hierarchy doesn't achieve this. I think we can all agree on this.
But also, global OOM in particular means that the hierarchical
approach to allocating the system's memory among cgroups has
failed. The user expressed control over memory in a way that wasn't
sufficient to isolate memory consumption between the different
hierarchies. IMO what follows from that is that the hierarchy itself
is a questionable guide to finding a culprit.
So I'm leaning toward the second model: compare all oomgroups and
standalone tasks in the system with each other, independent of the
failed hierarchical control structure. Then kill the biggest of them.
[toc] | [prev] | [next] | [standalone]
| From | Michal Hocko <mhocko@kernel.org> |
|---|---|
| Date | 2017-09-25 22:30 +0200 |
| Message-ID | <utIaR-2VS-1@gated-at.bofh.it> |
| In reply to | #1739183 |
On Mon 25-09-17 19:15:33, Roman Gushchin wrote: [...] > I'm not against this model, as I've said before. It feels logical, > and will work fine in most cases. > > In this case we can drop any mount/boot options, because it preserves > the existing behavior in the default configuration. A big advantage. I am not sure about this. We still need an opt-in, ragardless, because selecting the largest process from the largest memcg != selecting the largest task (just consider memcgs with many processes example). > The only thing, I'm slightly concerned, that due to the way how we calculate > the memory footprint for tasks and memory cgroups, we will have a number > of weird edge cases. For instance, when putting a single process into > the group_oom memcg will alter the oom_score significantly and result > in significantly different chances to be killed. An obvious example will > be a task with oom_score_adj set to any non-extreme (other than 0 and -1000) > value, but it can also happen in case of constrained alloc, for instance. I am not sure I understand. Are you talking about root memcg comparing to other memcgs? -- Michal Hocko SUSE Labs
[toc] | [prev] | [next] | [standalone]
| From | Michal Hocko <mhocko@kernel.org> |
|---|---|
| Date | 2017-09-26 13:30 +0200 |
| Message-ID | <utWdQ-46A-17@gated-at.bofh.it> |
| In reply to | #1739265 |
On Tue 26-09-17 11:59:25, Roman Gushchin wrote: > On Mon, Sep 25, 2017 at 10:25:21PM +0200, Michal Hocko wrote: > > On Mon 25-09-17 19:15:33, Roman Gushchin wrote: > > [...] > > > I'm not against this model, as I've said before. It feels logical, > > > and will work fine in most cases. > > > > > > In this case we can drop any mount/boot options, because it preserves > > > the existing behavior in the default configuration. A big advantage. > > > > I am not sure about this. We still need an opt-in, ragardless, because > > selecting the largest process from the largest memcg != selecting the > > largest task (just consider memcgs with many processes example). > > As I understand Johannes, he suggested to compare individual processes with > group_oom mem cgroups. In other words, always select a killable entity with > the biggest memory footprint. > > This is slightly different from my v8 approach, where I treat leaf memcgs > as indivisible memory consumers independent on group_oom setting, so > by default I'm selecting the biggest task in the biggest memcg. My reading is that he is actually proposing the same thing I've been mentioning. Simply select the biggest killable entity (leaf memcg or group_oom hierarchy) and either kill the largest task in that entity (for !group_oom) or the whole memcg/hierarchy otherwise. > While the approach suggested by Johannes looks clear and reasonable, > I'm slightly concerned about possible implementation issues, > which I've described below: > > > > > > The only thing, I'm slightly concerned, that due to the way how we calculate > > > the memory footprint for tasks and memory cgroups, we will have a number > > > of weird edge cases. For instance, when putting a single process into > > > the group_oom memcg will alter the oom_score significantly and result > > > in significantly different chances to be killed. An obvious example will > > > be a task with oom_score_adj set to any non-extreme (other than 0 and -1000) > > > value, but it can also happen in case of constrained alloc, for instance. > > > > I am not sure I understand. Are you talking about root memcg comparing > > to other memcgs? > > Not only, but root memcg in this case will be another complication. We can > also use the same trick for all memcg (define memcg oom_score as maximum oom_score > of the belonging tasks), it will turn group_oom into pure container cleanup > solution, without changing victim selection algorithm I fail to see the problem to be honest. Simply evaluate the memcg_score you have so far with one minor detail. You only check memcgs which have tasks (rather than check for leaf node check) or it is group_oom. An intermediate memcg will get a cumulative size of the whole subhierarchy and then you know you can skip the subtree because any subtree can be larger. > But, again, I'm not against approach suggested by Johannes. I think that overall > it's the best possible semantics, if we're not taking some implementation details > into account. I do not see those implementation details issues and let me repeat do not develop a semantic based on implementation details. -- Michal Hocko SUSE Labs
[toc] | [prev] | [next] | [standalone]
| From | Michal Hocko <mhocko@kernel.org> |
|---|---|
| Date | 2017-09-26 15:40 +0200 |
| Message-ID | <utYfE-5n5-13@gated-at.bofh.it> |
| In reply to | #1739789 |
On Tue 26-09-17 13:13:00, Roman Gushchin wrote: > On Tue, Sep 26, 2017 at 01:21:34PM +0200, Michal Hocko wrote: > > On Tue 26-09-17 11:59:25, Roman Gushchin wrote: > > > On Mon, Sep 25, 2017 at 10:25:21PM +0200, Michal Hocko wrote: > > > > On Mon 25-09-17 19:15:33, Roman Gushchin wrote: > > > > [...] > > > > > I'm not against this model, as I've said before. It feels logical, > > > > > and will work fine in most cases. > > > > > > > > > > In this case we can drop any mount/boot options, because it preserves > > > > > the existing behavior in the default configuration. A big advantage. > > > > > > > > I am not sure about this. We still need an opt-in, ragardless, because > > > > selecting the largest process from the largest memcg != selecting the > > > > largest task (just consider memcgs with many processes example). > > > > > > As I understand Johannes, he suggested to compare individual processes with > > > group_oom mem cgroups. In other words, always select a killable entity with > > > the biggest memory footprint. > > > > > > This is slightly different from my v8 approach, where I treat leaf memcgs > > > as indivisible memory consumers independent on group_oom setting, so > > > by default I'm selecting the biggest task in the biggest memcg. > > > > My reading is that he is actually proposing the same thing I've been > > mentioning. Simply select the biggest killable entity (leaf memcg or > > group_oom hierarchy) and either kill the largest task in that entity > > (for !group_oom) or the whole memcg/hierarchy otherwise. > > He wrote the following: > "So I'm leaning toward the second model: compare all oomgroups and > standalone tasks in the system with each other, independent of the > failed hierarchical control structure. Then kill the biggest of them." I will let Johannes to comment but I believe this is just a misunderstanding. If we compared only the biggest task from each memcg then we are basically losing our fairness objective, aren't we? -- Michal Hocko SUSE Labs
[toc] | [prev] | [next] | [standalone]
Page 1 of 2 [1] 2 Next page →
Back to top | Article view | linux.kernel
csiph-web