CodeGuru Home VC++ / MFC / C++ .NET / C# Visual Basic VB Forums Developer.com
Results 1 to 3 of 3
  1. #1
    Arjay's Avatar
    Arjay is offline Moderator / EX MS MVP Power Poster
    Join Date
    Aug 2004
    Posts
    13,490

    Custom Performance Monitor Design

    TheGreatCthulhu, thanks for pointing to the Mediator pattern. Some of you may know I'm not quite good at design patterns, and this is one of those I didn't know yet. And the Mediator pattern seems to definitely be a candidate to consider for the one of my apps I'm currently dedicating most of my programming time to. And actually I already have considered a similar design, I just wouldn't have called the central coordinating instance "mediator", rather, by nature of the app, something like "hub" or "data pump". And of course I had no idea there's a related standard design pattern... (Also, it's currently the app itself that plays that role, and that was something I already was sure of that it needs to be changed.)
    To summarize what the app is about: Some of you may know I always wanted an alternative to the terrible Windows Performance Monitor, and recently I had some spare time, so I stated my own one. There currently are these categories of "colleagues":
    • Sample sources: Provide an (ideally but not necessarily) continuous stream of timestamped numerical sample values.
    • Event mark sources: Provide timestamped notification of instantaneous events. They don't carry sample values but may convey additional information like, for instance, the originator of the event.
    • Consumers: Simply do what the name suggests. Currently the only instance of this is the chart that displays the samples and events.
    • Triggers: Act as both consumers of sample streams and/or events and issue events based on some condition, for instance when a certain number of consecutive samples from a certain source exceed a certain value.

    I'm also envisioning another category ("operator", perhaps) that acts as a consumer and produces a sample stream as output, but that idea is rather abstract and by now I don't know any concrete scenario where that actally might be useful. And out of the bulleted list above, only the first three items have actually been implemented by now.
    Of course this scenario is way more complex than the simple examples of the Mediator pattern I found since reading your post, but actually I rather consider this an advantage: The minimalistic examples help to focus on the core aspects of the pattern and loosing the visible connection between my implementation and the pattern examples may be a warning to perhaps rethink parts of my design.
    There are, however, some aspects in which I definitely must deviate from the sample designs due to the naure of my app: My design must definitely support event-driven action and, at least to some extent, multithreading, so it can't be so strictly sequential. Also, it's probably a good idea to allow the colleagues to choose between communicating with the mediator in an event-driven manner or by polling. At least in the latter case, the mediator will probably need to provide buffering queues for the colleagues, so these don't need to implement the same thing over and over.
    Proper abstraction at a stage as early as possible is also desirable here since I plan to expose a plug-in interface so colleagues can be added externally.
    Any thoughts? Perhaps Mediator even is the wrong pattern for my scenario; as stated above: There's quite a bunch of them I don't even know yet...

    Moderator Comment: Note: this thread was split by request from this thread.
    Last edited by Arjay; November 16th, 2012 at 04:25 PM.

  2. #2
    Join Date
    Jan 2010
    Posts
    1,133

    Re: Custom Performance Monitor Design

    [Note to readers: this question was originally posted by Eri523, in another thread; the post preceding the question contained a link to a Wikipedia article about the Mediator pattern, which I've also included here for convenience.]

    OK, let me see if I have the right idea here. (You're developing this in C++/CLI?) Your sample sources are classes designed to obtain data, timestamp it, porhaps queue it, and (I'm not sure about this one) raise .NET events? On the other hand, what you classified as event mark sources simply convey information that something has occurred (possibly including a way to identify the sender), and the semantics of the event will be "embedded" in the type of the event itself - something that lends itself naturally to the .NET event model. Now, consumers are either UI (various Views in MVP terminology), or objects which essentially (on a very conceptual level) take in a stream of events, and transform it into an output stream of different events, depending on some internal logic (I guess this encompasses both the triggers and the "operators")?
    In this context, triggers are actually a special case of event mark sources, while the "operators" would be specialized sample sources. Correct?

    I guess that's an overview of the design, as it shows how different categories of classes interact, but I'd also like to know more about the interactions within the categories. Should various types of sample/event sources interact, and under what conditions? On the consumer side, how complicated is the UI, is there some tricky presentation logic involved, and how do you plan to sinc the UI with the data (are you maybe going for the MVP-based approach)? Is there a need to support sample/event source switching at runtime, or show data from several sources simultaneously? Basically, what features you target?

    For the triggers and the "operators", there's an opportunity to implement the Decorator pattern; a decorator wraps a source, adds a responsibility (filter/translate events), and passes the result along, itself becoming a source. Note that the wrapped object's function should remain unaffected by the presence of the decorator; observers of the original object still see the original events, while the observers of the decorator get a different set of events. And it's flexible, the decorator can be removed, or the sample/event source can be replaced, or new decorators can be added (even inserted) into the "decorator array", to call it that way (but don't go overboard with it). However, some care is required, as it is possible that some combinations do not make sense. The propagation of source data up the decorator chain can be achieved through .NET events, but as events require hooking/unhooking, it could be better to define a narrow interface instead (assembly access - internal).

    Also, depending on the circumstances, a decorator might be useful when it comes to data binding with the View(s), as it could be possible to provide a decorator which only adds the data binding capabilities, and then switch the wrapped object for another one, without the need to rebind. This is not the only way to achieve it, though, so some other setup based on object composition is possible. (If it sounds as if I'm pretty much suggesting the same thing - note that a number of patterns are structurally the same, or almost the same, but differ in intent, and this intent directs the way design is fine-tuned, and ultimately, implemented.)

    When it comes to multithreading, making the shared objects immutable would simplify things a lot, if that's applicable to this scenario. BTW, a comment to something you said: events are sequential in nature (for example, if you block inside an event handler in say, WinForms app, the whole thing freezes; only when the handler returns can the execution continue, and, eventually, can another event be fired). Can you say what do you intend to use multithreading for, specifically? Background processing tasks are good candidates, but if you're considering multiple threads for drawing, go instead for a game loop like, single threaded approach.
    Actually, maybe an update loop based approach is not a bad idea overall for this type of application (of course, you could exploit the underlying windows msg loop in some way).

    You also said you'd like both event-based notification and polling; what are your current ideas about approaching that?

    Finally, about the Mediator patten: basically, a mediator object is, as you said, a hub of sorts through which all interaction goes within a system; it encapsulates interaction rules for the (many) components of the system (contrast with Facade which provides an interface to a system; an interface for the client code to use). Introducing a mediator (which can be a somewhat ugly, complicated class) in turn enables the components of the system to be reused far more easily (as many dependencies are reduced to one (or few)). The other thing is that the system logic that would otherwise be distributed among all the components is now made more explicit, and moved into the mediator itself; this means that it is now possible to alter this behavior by subclassing only one class - the mediator, if something like that is required. (In a way, the Presenter in MVP acts like a mediator for the UI controls, implementing the presentation logic, but note that in MVP, in some variations more than in others, additional steps have been taken to further decouple the components of the View(s) from the Presenter; designs like MVP are often referred to as "architectural styles", since they incorporate more than one pattern, and sometimes different pattens can be emphasized in the design, depending on how you look at it).


    (Note that the Mediator hierarchy can be collapsed to a single, concrete class, in case that there's no need for more than one kind of mediator-defined behavior.)

    So, do you have such systems (or subsystems) with components that engage in complicated interactions, that are, although well-defined, difficult to make sense of? If so, could you describe them in more detail?
    Last edited by TheGreatCthulhu; November 17th, 2012 at 03:59 PM.

  3. #3
    Join Date
    Jun 2010
    Location
    Germany
    Posts
    2,675

    Re: Custom Performance Monitor Design

    Quote Originally Posted by TheGreatCthulhu View Post
    OK, let me see if I have the right idea here. (You're developing this in C++/CLI?)
    Thanks for your qualified (as anticipated ) response, and yes, this is in C++/CLI.

    For starters, I think, it may be helpful to see what we're talking about, to give some clarifying orientation. So here's an example screen shot of the tool we're talking about:

    Name:  2012-11-18_013758.png
Views: 513
Size:  55.1 KB

    It shows a recording taken of another one of my own apps, an as-I-always-wanted-it sort of backup/file sync program, tracking CPU and memory utilization as well as disk throughput. The vertical red dotted lines are event marks (placed manually and the text annotations to them were entered manually as well, however, a feature of the EPM, no image manipulation ). It's a feature planned for later on that the program under test can place this sort of comments itself by means of an EPM adapter DLL that acts as a trace listener to the program under test, which is sort of science fiction by now, but an example of another sort of event mark source. The rest is more or less self-explanatory I think.

    Your sample sources are classes designed to obtain data, timestamp it, porhaps queue it, and (I'm not sure about this one) raise .NET events? On the other hand, what you classified as event mark sources simply convey information that something has occurred (possibly including a way to identify the sender), and the semantics of the event will be "embedded" in the type of the event itself - something that lends itself naturally to the .NET event model.
    Except some minor peculiarities of the timestamping mechanism, which can be considered implementation details from our current perspective, yes. In particular, you're right about the .NET-event-based nature of the event mark sources. Even the abstract interface I have defined for them declares such an event. And yes, this is pretty much by nature: The other currently implemented event mark source, the "event log watcher" (not shown in the screen shot) is based on the .NET framework's EventLog class and its EntryWritten event.

    Now, consumers are either UI (various Views in MVP terminology), or objects which essentially (on a very conceptual level) take in a stream of events, and transform it into an output stream of different events, depending on some internal logic (I guess this encompasses both the triggers and the "operators")?
    Yes. And that includes some comparatively abstract and minimalistic kind of consumer that merely consumes event marks and performs basic tasks like start/stop recording, play a sound, start an external process and the like.

    In this context, triggers are actually a special case of event mark sources, while the "operators" would be specialized sample sources. Correct?
    Yes, exactly that.

    I guess that's an overview of the design, as it shows how different categories of classes interact, but I'd also like to know more about the interactions within the categories. Should various types of sample/event sources interact, and under what conditions?
    To keep things "simple" () - remember, I'm planning a plug-in interface -, no, at least not from the perspective of my performance monitor app. With, of course, the exception of triggers and operators which fundamentally are defined as acting both as a consumer and source at the same time.

    On the consumer side, how complicated is the UI, is there some tricky presentation logic involved, and how do you plan to sinc the UI with the data (are you maybe going for the MVP-based approach)?
    Looking at the screen shot above, the chart control comprising the window's client area practically is the only consumer instance existing so far, while the frame window itself belongs to the yet-to-factor-out mediator. However, the chart is sort of a consumer with privileges: The source-related items on the chart have tool tips displaying information that probably will be available to any ordinary consumer as well, but they also feature context menus that allow things like deleting sources (including the respective data series), which is a direct manipulation of mediator-internal data structures that wouldn't be allowed to ordinary consumers.

    Is there a need to support sample/event source switching at runtime, or show data from several sources simultaneously? Basically, what features you target?
    Well, allowing just a single source to be displayed at a time would be quite boring, don't you think? And the user is allowed to add/remove items at runtime, with some restrictions applying to stored recordings. (I don't see much sense in adding new samples to recordings made days ago, for instance.) There's no plan to allow the items themselves to perform actions like that, however. (Sample sources can enter a "dead" state which allows to accommodate to things like processes being shut down while recording without the need to remove the entire source/data series or recording meaningless data.)

    Admittedly it even took me quite some time to accommodate to the model-view (or document-view) architecture, and when it comes to MVC, the C functionality usually is somewhat scattered across the model and view classes (with some bias depending on the subject and my personal feel of it...). Let alone MVP...

    For the triggers and the "operators", there's an opportunity to implement the Decorator pattern; a decorator wraps a source, adds a responsibility (filter/translate events), and passes the result along, itself becoming a source. [...]
    Yeah, I remember a thread discussing that pattern, with you contributing and me just following IIRC... I'm used to envisioning this pattern as sort of a more flexible "Lego-style" design, while I see Mediator as a rather strictly circular design with exactly one vertex connecting the mediator with each colleague. While the concept of triggers and opeators seems to suggest a Decorator-like design, I think Mediator is possible here as well. That would put more responsibility (in particular dispatching/routing of information) on the mediator but may simplify the overall design outside that class. (Just as you said: There often is a trade-off between some possible patterns.)

    When it comes to multithreading, making the shared objects immutable would simplify things a lot, if that's applicable to this scenario.
    Yeah. I remember having called such a concept "fire-and-forget objects" in some forum thread, while that didn't actually require the objects to be strictly immutable. The requirement just was that the "firing" thread wouldn't use anything mutable it got from "outside" when constructing the said object, and wouldn't touch it anymore once it got deployed. The effect would more or less be the same and, yes, chances are that it would eliminate most of the synchronization needs I have now. Definitely worth consideration.

    BTW, a comment to something you said: events are sequential in nature (for example, if you block inside an event handler in say, WinForms app, the whole thing freezes; only when the handler returns can the execution continue, and, eventually, can another event be fired).
    You're right, of course. Technically, .NET events are strictly sequential, and what I actually meant was a sequential way of thinking. As an old-school guy who development-wise grew up in times when no-one even knew what multithreading is, I sometimes tend to confuse these things...

    Can you say what do you intend to use multithreading for, specifically? Background processing tasks are good candidates, but if you're considering multiple threads for drawing, go instead for a game loop like, single threaded approach.
    Actually, maybe an update loop based approach is not a bad idea overall for this type of application (of course, you could exploit the underlying windows msg loop in some way).
    The reason why I introduced multithreading at all was that my program, after accumulating severall thousands of samples, tended to become a real CPU hog, mostly because of the activities of the Windows Forms chart control that doesn't seem to really have been made for things like that. I managed to reduce the overall CPU load imposed by my program to about the same amount that Process Explorer demands by a combination of two techniques I call "history downsampling" (displaying older samples as aggredated average data points while internally maintaining full temporal resolution) and "display rate throtteling" (adaptively, depending on the CPU load I cause myself, reducing the rate at which I update the chart control with respect to the actual sample rate). (Of course, Russinovich's tool achieves much more with the same count of CPU cycles... ) However, my program consumes its CPU load in quite fat bursts, with the chart control keeping the main thread busy for quite some time, eventually causing considerable distortion in the "sample time frame". I'm dodging this problem by doing the actual sampling in a separate thread, with this simple therad procedure (unmodified and uncommented), posting the sampling results to a thread-safe queue for the main thread to fetch them:

    Code:
    void Form1::SamplingThreadProc(Object ^objParams)
    {
      SamplingThreadParams ^params = safe_cast<SamplingThreadParams ^>(objParams);
      int nSampleInterval = params->m_ist->SampleInterval * 1000;
      do {
        ScopedLock lock(params->m_ist->m_indicators);
        params->m_ist->TakeSampleSnapshot();
        for each (PerformanceIndicator ^ind in params->m_ist->m_indicators)
          if (ind->CurrentSnapshotSample && (!ind->Delta || ind->LastSnapshotSample))
            params->m_cquPointQueue->Enqueue(gcnew DataPointQueueEntry(ind));
      } while (!params->m_evtShutdown->WaitOne(nSampleInterval));
    }
    You also said you'd like both event-based notification and polling; what are your current ideas about approaching that?
    The idea behind this originates from the "display rate throtteling" mechanism: While the chart display consumer, in order to reduce CPU load, may decide to just poll the accumulated sample data every, say, four or eight seconds, an "emergency response" consumer that starts an external process or plays a sound may need the sample data as soon as it arrives. However, I'm not yet sure about the concrete implementation. Currently I'm considering a scheme where a consumer can issue a preference for either push or pull operation, which the mediator may or may not honor.

    Finally, about the Mediator patten: basically, a mediator object is, as you said, a hub of sorts through which all interaction goes within a system; it encapsulates interaction rules for the (many) components of the system (contrast with Facade which provides an interface to a system; an interface for the client code to use). Introducing a mediator (which can be a somewhat ugly, complicated class) in turn enables the components of the system to be reused far more easily (as many dependencies are reduced to one (or few)). The other thing is that the system logic that would otherwise be distributed among all the components is now made more explicit, and moved into the mediator itself; this means that it is now possible to alter this behavior by subclassing only one class - the mediator, if something like that is required. [...]
    This seems to match something I said some paragraphs above: Using a mediator "(which can be a somewhat ugly, complicated class)" may put more responsibility on just that class, while in exchange significantly simplifying the outside design.
    I was thrown out of college for cheating on the metaphysics exam; I looked into the soul of the boy sitting next to me.

    This is a snakeskin jacket! And for me it's a symbol of my individuality, and my belief... in personal freedom.

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  





Click Here to Expand Forum to Full Width

Featured