6 ms·
You're not going to like the answer, but I think it captures some of what you're getting at. Windows 95. Old style gui programming meant sitting in a loop, wai
by jfoutz 5y ago
You're not going to like the answer, but I think it captures some of what you're getting at.
Windows 95. Old style gui programming meant sitting in a loop, waiting for the next event, then handling it. You type a letter, there's a case switch, and the next character is rendered on the screen. Being able to copy a file and type at the same time was a big deal. You'd experience the dead letter queue when you moved a window while the OS was handling a device, and the window would sort of smear across the screen when the repaint events were dropped.
Concurrent programming is hard. State isolation from micro services helps a lot. but eventually you'll need to share state, and people try stuff like `add 1 to x`, but that has bugs, so they say, `if x == 7 add 1 to x` but that has bugs so they say, `my vector clock looks like foo. if your vector clock matches, add 1 to x, and give me back your updated vector clock` but now you've imposed a total order and have given up a lot of performance.
I'm blind to the actual problem you're facing. My default recommendation is to have a monorepo, and break out helpers for expensive tasks, no different than spinning up a thread or process on a big host. Have a plan for building pipelines a->b->c->d. also have a plan for fan out a->b & a->c & a->d
It has been widely observed there are no silver bullets. but there are regular bullets. Careful and thoughtful use can be a huge win. If you're in that exponential growth phase, it's duck tape and baling wire all the way, get used to everything being broken all the time. if you're not, take your time and plan out a few steps ahead. Operationalize a few micro services. Get comfortable with the coordination and monitoring. Learn to recover gracefully, and hopefully find a way to dodge that problem next time around.
Sorry this is hand wavy. I don't think you're missing anything. it's just hard. if you're stuck because it won't fit on 1X anymore, you've got to find a way to spread out the load.
- blackoil 5y agoReact also works quite similar, with the added benefits of async and single thread.
- malandrew 5y agoAs someone that worked at the company that taught Pete Hunt, and other early contributors to react this trick, I wouldn't call it a benefit, but the only workable solution to acceptable single page web application performance in an otherwise terrible development environment (browser javascript). Proper concurrency support and real mutexes would be way better than having a single execution thread for all your computations that is shared with all the visual and human interaction computations. Plus, the data sharing models between the main thread and web workers is pretty crap for anything serious, so it's not even easy to get computations out of the main thread that don't need to be there.
- dmos62 5y agoI find Clojurescript to have a superb async support and ecosystem.
- malandrew 5y agoUnless something has changed with web assembly since I last did browser development, doesn't it still compile down to javascript in the same execution environment with those limitations?
- dmos62 5y agoI'm not very familiar with concurrency at a lower level, so I can't comment on your complaints. What Clojurescript provides is considerably better abstractions that in turn get you correct implementations with much less incidental complexity or hassle.
- malandrew 5y agoNot sure why my sincere question about the state of browser execution environment got downvoted, but the general concerns I raised in my first comment weren't about incidental complexity or hassle. They matter and it's great that clojurescript helps with those two. The concern I voiced was about maintaining realtime performance of a responsive user interface. The key issue is that you have a single event loop that all visual and human interactions need to be handled by because that's the only thread that can interact with the DOM. It's just way too easy to block that thread and cause the app to become unresponsive.
- dmos62 5y ago> The key issue is that you have a single event loop that all visual and human interactions need to be handled by because that's the only thread that can interact with the DOM. Isn't that normal? A single event/drawing loop. Would there be an advantage to two threads drawing? Sounds pretty novel.
- 5y ago
- fxtentacle 5y agoI fully agree with this, also that's still quite common in the embedded world. The user presses a button which sets a hardware event flag. CPU wakes up from sleep, checks all event flags, handles them, clears the interrupt bits and goes back to sleep. But using events like this requires a very tight integration between event producer and consumer, so I don't think this will translate well to distributed systems or microservices.
- PinguTS 5y agoThere is an example where highly distributed, event-driven systems are used. Everyday we are using them. It the cars. In a car there are many distributed ECUs(1) that communicate in an event driven system. It was tried to use cyclic communication. But all those attempts failed in the long run. Because cyclic communication would required that all the independent ECUs are synced to each other, which is a very hard problem. That is the reason why everybody moved away from cyclic communication. That said to help the development in automotive a middleware have been developed and used to help the development of such event driven systems. You develop your functions and define how the signals are routed between those functions. The someone later/independent decides on how the functions are distributed on the different ECUs depending the available resources. The middleware then takes care of the correct routing of the signals. Everything is event driven. (1) Electronic Control Units
- deleted 5y ago[deleted]
- Lucero 5y agoAutomotive ECUs use cyclic communication and are event driven. ECUs send their signals over CAN at a defined message rate, regardless of whether the state has changed. Other ECUs set up their hardware to monitor the signals they care about, and trigger a hardware interrupt when the signal is received.
- PinguTS 5y ago> […] and trigger a hardware interrupt when the signal is received. That is the definition of event driven. The same is not only true for the CAN-based, and CAN FD-based communication, but also for the Automotive Ethernet-based communication. There were tries with Time-triggered protocols like TTP/C (used by Daimler for exactly one model) and FlexRay which had cyclic communication. The communication cycle required that the ECUs are synced to the communication cycle because they needed to have to correct data available at exactly their time slot. If they missed the time slot, the data got marked as stale. The same problem on the receiving side.
- DelightOne 5y ago> Have a plan for building pipelines a->b->c->d. also have a plan for fan out a->b & a->c & a->d How does that look like? Do you mean to learn how this is done with the CI of choice, create helper functions or are there concrete steps that you would recommend? I'm new to this and would appreciate any feedback.
- jfoutz 5y agoLet's assume a has a time constraint, and needs to start shoveling bytes back to the client in 30ms. In the pipeline case, a probably only has visibility to b, each service in the chain has ~7ms to provide its response. In the fan out case, a is aware of b c and d, they can each take 25ms or more and a can still meet its deadline. The way a sets its timeouts will vary depending on what's happening downstream. This is a pedantic and fussy point of view. Nobody really does this, some pretend they do. But it can be important for overall performance.
- DelightOne 5y agoOhh you talk about call pipelines, I totally missed the point. You are talking about time-constrained systems where an answer in the timeframe is required, right? Otherwise the timeout does not make sense, or would you do such precise timeouts even in non-time-constrained systems? Anyway, seems to make sense to plan for this timing-wise. Allows addressing and seeing performance bottlenecks. Thank you for spelling it out for me!
- jfoutz 5y agoFailure too. Recovery in a pipeline is different than fan out.
- narag 5y agoWindows 95. Old style gui programming meant sitting in a loop, waiting for the next event, then handling it. The GUI worked in a single thread, but your whole program didn't need to do that. Being able to copy a file and type at the same time was a big deal. That's not correct. You just needed to create a separate thread for the file operation. For some programmers that was a big deal indeed, the same could be said for some programming tools. But that wasn't a general case at all. There were some ugly things, like the way file operations were treated down the OS level, but it wasn't impossible to make your application responsive. It wasn't even difficult... if you knew how to do it.
- relaxing 5y agoOP is talking about what you could do using the built in Windows utilities, not what is possible if you write your own file copy-and-note taking utility (which some people did, like Borland Sidekick.)
- narag 5y agoI guess what you call "built in Windows utilities" is making a call to the GUI shell. It's actually a very complex inter-process communication that happened to be a one-liner from VB and showed that fancy flying folders animation. Not very flexible though. Writing "my own" code for file copy was not really so low-level, it's what most people understood as programming at the time. Locating the file, opening it, using a descriptor and a loop to copy blocks through a buffer, closing the file, managing errors... that kind of thing. If you wanted to do the file operation in the background and keep using the GUI for input, you did need to create a separate thread. But that wasn't some black art feat, you just read a book or searched Altavista for a snippet, if in a hurry.
- ThinkBeat 5y agoI am not sure about Windows95, but the MSDOS legacy is single threaded, so you did not have the luxury of having the abstraction represented for you by the operating system. Some people wrote very inventive software to get around it. In Windows there is a fundamental concept of the message loop. The message loop is an obligatory section of code in every program that uses a graphical user interface under Microsoft Windows. Windows programs that have a GUI are event-driven. Note that WindowsNT is fully multithreaded, but there is a thread sitting there listening to the event loop still. (of course other threads can do other things). https://en.wikipedia.org/wiki/Message_loop_in_Microsoft_Windows https://en.wikipedia.org/wiki/Message_loop_in_Microsoft_Wind...
- jimmaswell 5y agoAren't most "events" just an abstraction that's actually implemented by polling and/or an event queue at some level anyway, be it a library or the kernel?
- parentheses 5y agoI agree mostly to this answer. I also want to point out that we use sharding as a technique. Micro-services is just sharding across a different axis (TM)