Would that be better though? I have no experience of driver development by my feeling is that device drivers being low-level and fundamental building blocks of a working operating system, doesn't fit well with garbage collection interrupting execution on its own schedule.
There are ways to solve that and it’s not an architectural flaw. You just need prediction in the compositor to adjust the location of the mouse.
But honestly, the difference of a frame of latency is ridiculously difficult to feel and we’re talking about a half frame of latency here on average. It’s almost likely something else considering the entire end to end latency here is closer to 50-100ms on most systems and still isn’t what people would describe as laggy. Usually it’s some kind of software bug/hiccup that interrupts things to not be rendered at a constant tick rate or just getting hung and not processing events in a timely fashion.
There's a big difference between slow as molasses and one frame of 16ms (which you sacrifice in exchange for no screen tearing). Unless you're really into high rank competitive shooters, I doubt you can even tell that 1 frame delay is happening.
Also, make sure you use the right config - there are actual issues with some competitors which are not Wayland architecture issues. For example https://github.com/swaywm/sway/issues/4763
Check your display refresh rate. I had issues on Linux with it not supporting the maximum HDMI bandwidth properly so it drops the refresh rate to 30Hz which makes mice super laggy.
Attitudes like these is how we eventually end up with bloated messes like Electron. Performance matters, everywhere. Some of us increasingly also use monitors with more than 60 hertz.
This is pretty silly. They have the option to alloc and leak in C too. Rust is also just guaranteed memory safety not leak free, right? In a competition of lazy code, I'd rather GC pauses than OOM crashes.
But C# isn't ideal for a driver because of the weight of the runtime not because it's hard to save on allocations.
Mouse stutter has become more common in Windows. Every time I open a web page with Spotify embed mouse freezes for ~0.5 to 1 second and then continues moving, I haven't found any reason for it, it happens with Firefox, Google Chrome, and Edge.
It's been repeatable ever since I bought a Ryzen 7950X at the beginning of the year, that's why I tried using system profiler tools to find the reason but as I have no good experience in this it's difficult to find the root cause.
I had similar problems maybe 15 years ago, so I don't remember exactly how I solved it. In my case it was a NIC driver that filled up some queue when I downloaded "Linux ISOs" too fast over bittorrent.
There are tools available to find the source of the problems, I think I used event tracing as a starting point.
Unplug and try a different mouse.
Unplug and disconnect any other peripherals except the mouse and try that.
Try a new user on windows (user space apps)
Try a fresh install (system stuff)
If you have spinning rust try another hard drive (an app doing stupid blocking exclusive stuff with writing or reading can pause input stuff).
I noticed it after I upgraded to a 3900X. Not sure if it's an AMD thing, a USB hub thing, or a many-core thing. But it had never happened before. (Microsoft Pro Intellimouse)
You can use UI4ETW[0] to capture an event trace when the mouse freezes. You may need to install the Windows SDK or Visual Studio to interpret the results, though.
I'm not aware that C# has security or reliability advantages over Rust. It may be better integrated into the Microsoft ecosystem but from the point of view of a driver developer who has to support more than one OS, Rust would seem to be a good tradeoff between security, performance, and reliability vs. C/C++.
I'm a big fan of Rust (and a minor contributor), but one can't deny that a garbage-collector makes most developments much easier. Now, I'm not convinced that a gc makes much sense in driver development, but I could be wrong.
Not wrong. Kernels usually have their own memory management schemes, tied to the lifetime of i/o ops and so on. It would make more sense to somehow integrate that into the driver programing language.
It makes some things easier, and some things harder, or more complex.
So I can deny that most development becomes easier with GC. At least if you also intend to actually run the thing. Running Java means forever fighting the GC, needing to do runtime and development to reduce impact of inherent GC problems.
But it's a Java issue: Java relies on Heap Objects way too much. C# and the CLR behind it has a much better support for value types and stack allocations, where some optimization can even be done by the JIT compiler.
You are right that I was talking about delivering a first working version, not about tuning performance. It could be argued that optimizing for memory (de)allocation so early in the development is a case of premature optimization. Sadly, I don't know a (good) path from gc-based development to safe manual memory management, so I'll keep that counter-argument for the day I see one such path :)
Yeah, the problem with that kind of thing is that GC languages disincentivizes thinking about ownerships, and tacking ownership on after the fact is basically a rewrite.
I wrote a bit about this. After years of having move semantics and borrow checking I don't really agree. I find that GCs are way way harder to reason about. They make it very hard to know when I'm sharing something or not, when something can be mutated, when it will be copied, etc. And then I still have to clean up other resources with a whole other, separate system.
At the end of the day I find languages like Java much harder to reason about and actually a bit harder to write.
You're not wrong, but I believe that we're talking of different properties.
Move semantics and borrow checker shine when you don't want your data structure to be shared and when you want to control mutation. In some domains, that brings you an unequaled level of safety and Rust is the obvious choice.
Move semantics and borrow checker slow you down when you sharing and mutation are properties you don't care about (or at least not enough to prove them to the compiler). In such cases, I'd rather code in OCaml (or Haskell, or TypeScript, ...)
I hope that one day we'll be able to have the best of both worlds, but I don't see a path forward at the moment.
Xerox PARC and ETHZ workstations were fully written in GC enabled languages, including the device drivers.
Smalltalk, Interlip-D, Mesa/Cedar, Oberon, Oberon-2, Active Oberon
Source code is available for some of them, many home made OSes in non GC enabled languages are far from meeting the capabilities of any of those systems.
"Eric Bier Demonstrates Cedar" - Computer History Museum
In what concerns Xerox PARC, enough stuff on Bitsavers, about how everything run on top of those graphical workstations, in a distributed computing environment.
Likewise ETHZ IT department during the late 1990's used several Oberon workstations.
Poorly written device drivers are a significant attack vector. It's one of the reasons Linux is now exploring using Rust for its own device drivers.[0] You may be asking -- why Rust and not some other language? Rust has many of the performance and interoperability advantages of C and C++, but as noted, makes certain classes of memory safety issues impossible. Rust also has significant mindshare among systems programming communities.
Yeah okay but device drivers in C#? That sounds very impractical when you could pick any other language. C, C++, Rust, D, Zig, Objective-C, all seem more suitable than C#. I agree with all that stuff you said about Rust; I was asking how drivers in C# would work
I thinking “this is some project probably written years ago and loading the .NET Framework runtime into kernel space” but this is actually using NativeAOT and the latest features/SDK.
Rust helps against data races in a kernel, as shown by the Rust for Linux project and other kernel projects (Redox, etc).
Of course if you interact with foreign code (including code in other programs, but also code in the same program written in another language), you need unsafe. Or if you write a new synchronization primitive, etc. The unsafe is there to say "I manually checked and this is okay".
What's important is that with Rust, concurrent business logic - in a kernel, things like filesystems and drivers - shouldn't need any unsafe to synchronize correctly. You use unsafe for your lower level infrastructure, but the code that actually does things can be data race free (and thus is easier to modify and assure it's working correctly). And that's incredible.
Also the right way to implement filesystems and drivers in modern OSes should be in userspace drivers, which is the route being taken by Apple, Google and Microsoft across their OSes anyway.
It is very difficult to write device drivers in even C++ while still maintaining the ability to write pageable kernel drivers. Drivers must have very strict control over availability of memory because it will likely access it at times when a page fault is not possible (i.e. during an interrupt handler). The C# language and runtime would have to add features to explicitly accomodate this at a bare minimum
Microsoft tried that already. It failed miserably. I don't think they gave a reason but I suspect that garbage collection caused too many freezes in early 2000s hardware.
Yes, basically when Longhorn started to fail to meet expectations, there were two possible ways, do what Google did with Android, push forward no matter what to make it work, or forcing a rewrite into something else, which is what WinDev ended up doing.
macOS sandboxes apps, which are usually written in Swift or ObjC and thus use reference counting, and doesn’t suffer from the kind of slowness that plagues UWP. So your hypothesis appears to be incorrect
Microsoft is pushing more and more code into user space. The latest change is that they now insist printer manufacturers use UWP printer apps rather than drivers to add custom functionality to their printers; these apps are usually written in languages like C#.
I agree with Microsoft that the best method is probably to run less manufacturer code in the kernel, not to make the kernel accessible more easily. Running a garbage collector in the kernel sounds near impossible to pull off without GC bugs because C# isn't exactly suited for "I want to access some buffer but I can't because it hasn't been paged in and I'm in an interrupt handler".
> The latest change is that they now insist printer manufacturers use UWP printer apps rather than drivers to add custom functionality to their printers; these apps are usually written in languages like C#
it would be nice, however .NET Native is deprecated, Native AOT doesn't do UWP, and WinDev is pretty bullish in C++.
Depends, it can be already compiled to native code, in the case of still having MSIL, it is compiled by Windows Store before becoming available for distribution.
From the point of view of consumer, it is all AOT compiled code.
The GP I was responding to called for drivers written in managed C#, so .NET Native/AOT/C++ are the thing they want to move away from. The example code Microsoft provides (https://learn.microsoft.com/en-us/windows-hardware/drivers/d...) is all plain and simple C# with XAML UI.
I suppose you could write these tools in VB.NET or F# if you wanted to as well, but the goal seems to be to avoid memory and security risks in the printer framework by forcing everything into the nice and safe managed environment. Of course developers could always introduce vulnerable code into a managed environment if they wanted to, but most people don't intentionally make their programs more insecure, not even printer manufacurers.
I didn't realise that. Then again, I only experimented with AOT executables quite briefly. Perhaps Cosmos[1] stuck in my head more than what I read about AOT dotnet applications.
For those who don't remember, Russinovich prior to taking over his boss' job and possible succession as the next MSFT CEO, he owned a software tools and NT kernel consulting company where Redmond sent their engineers to learn NT kernel dev. Also, he found Sony's DRM rootkit, Symantec's rootkit-like file protection, and caught Best Buy pirating ERD Commander.
I'm kind of kicking myself now that I nuked my LinkedIn in 2014 having 2 degrees from the whole Valley and Mark as 1st. Oh well, there's freedom and agility in relative obscurity. What's that reggae song by Desmond Dekker about it's pointless to talk about how much you did, made, or who you used to know? xD
I don't think I'd want a "true hacker" to be a CEO.
"true hacker" feels good when describing people at the top of engineering career paths like fellows,
but for a CEO I'd rather have someone who's mix of decent tech skills and unparalleled business skills. I've had an opportunity to see companies where people didnt know how to do business and that was tragedy. That was way, way worse than non-technical manager trying to push solutions on ya.
Why not? Why can't a true hacker be a CEO? Bill Gates was a hacker. He implemented the Altair Basic language when computer languages were still in their infancy. Timothy Sweeney was a hacker and the creator of the Unreal Engine. He was the CEO of Epic. Eric Schmidt was a hacker. He wrote Lex. He became the CEO of Sun and Google. I would say Elon Musk was a hacker, as he was super technical.
The job of a Chief Executive Officer is to run the company, which requires a distinctly different set of skills and talent from people who like getting their hands dirty at the workbench.
It depends a lot…
Being ”a hacker” does not remove the required skills even if he has used his time for other things in the past.
For software company, it could be useful if the CEO knows what software is and the company might find other business models than trending ”enshittification” route.
> the job of a Chief Executive Officer is to run the company
Thats a very vague job description. Executive's jobs are to make investments that will maximize shareholder return and an executive of an engineering company will only be able to make the best investments if they understand the technology they are selling and their customers. People have been noting how engineers have been running more and more companies, thats because more and more companies rely on technology to drive their growth.
As much as Paul Allen? Would the latter have been as good a CEO?
Assuming you can't be among the best of both, which is a natural if possibly wrong assumption, I think it's clear where Gates excelled and that was obviously great for Microsoft.
Are you saying that it is backed by statistics that good CEOs need to be good managers of people and also implying that engineers are not good managers of people? I would be interested in seeing that statistics.
It feels wrong to me. In fact, I would argue that in tech the opposite is true. Go watch 'Downfall',the documentary on Netflix about Boeing and what happened when they dropped their engineering ethos and let in the "people persons" there.
Are you saying the best kernel hacker categorically makes someone not the best manager.
Or are you staying the best kernel hacker does not necessarily make someone the best manager.
I disagree with the former but agree with the latter. But I also want to add that the best leader for a technology company like Microsoft is not just some guy with an MBA but someone with both deep technical expertise and management/business experience.
The CEO's of Intel, Nvidia, and AMD are all engineers by training.
The sysinternals tools should be part of any windows installation. They are a must in mine.and are sorely missed whenever I need to fix/debug a friends computer. why else did MSFT acquihire them/Mark Russinovich?
How can you mention him and not mention sysinternals? I rely on that suite to do my job every day! Sysinternals have had more of an impact than perhaps even Azure itself considering how basically every company using windows in the world uses at least one sysinternals tool.
> he owned a software tools and NT kernel consulting company where Redmond sent their engineers to learn NT kernel dev.
Apple apparently used to do something similar, internal Apple Docs were nothing compared to Jonathan Levin's books[1], so Apple would routinely buy those for their OS engineers.
It's pretty interesting to me that companies of that size can't really do these things themselves, despite being in a much better position by having access to the engineers actual source code. These third parties (or at least Levin) had to rely on reverse-engineering to a large degree.
Yeah, a consultant can make more than an FTE just by spending a lot of time reading and writing lots of documentation. Especially if they can form a business around it.
Almost all of those refer back to FFI integer types, because that's what the Windows driver API uses. The Linux kernel has similar issues when it comes to writing Rust drivers, and so does every other project interoperating with C.
Types like NTSTATUS have a significant amount of documentation attached to it. Unlike C and C++, you can't just assign an integer value to an enum value. I suppose they could've generated a wrapper class and required you to cast every time, but then you'd get code that's 50% .into()s and that would probably add overhead to your driver as well.
As far as I can tell, you never set or alter these enum values, other than maybe the void* for buffer; you only ever read from them. A match {} block should work just fine on NTSTATUS. WDFREQUEST is a handle, so you can't really do anything with it other than maybe swap it out for another handle of the same type.
Timer and SpinLock have been converted into idiomatic Rust objects, wrapping unsafe library calls in their bodies. Other than that, I don't really see how you'd make this code idiomatic without adding a significant performance burden.
These are automatically generated bindings. Someone could go over every typedef and correct the spelling but I doubt any Rust developer would have problems with using a few capitals here and there.
I think it would have been nicer if this platform took the enum, and didn't the integer conversion at the FFI level, no? That should all be elided by optimisations.
The first two bits indicate severity, the next bit identifies if it was OS generated or not, then there's an indicator to see if it can be turned into a HRESULT or not, then a bunch of bits indicating the source of the error, and lastly the error code relevant given the previously set bits.
The Windows status codes could be converted, but the status codes generated by other drivers can't be. Even then the conversion would be far from free, you'd need to keep a close eye on your optimisations with every compiler version to keep them free.
That also ignores the possibility programs have to classify their own status codes, so you'd need some kind of "unconvertible" object to indicate that you can't reliably parse the faculty ID, and that you have to treat it like a simple integer.
149 comments
[ 3.7 ms ] story [ 419 ms ] threadhttp://farside.link/twitter.com/markrussinovich/status/17057...
(Sitting here running wayland, where the mouse feels stuck in molasses!)
I think later versions fixed this one, though.
The cursor is in the bottom half of the screen.
If I move the cursor, that should be represented in the frame that's being currently outputted, not the next frame.
Wayland has no support for that, by design.
The end result is that there is always a delay of at least one Frame.
But honestly, the difference of a frame of latency is ridiculously difficult to feel and we’re talking about a half frame of latency here on average. It’s almost likely something else considering the entire end to end latency here is closer to 50-100ms on most systems and still isn’t what people would describe as laggy. Usually it’s some kind of software bug/hiccup that interrupts things to not be rendered at a constant tick rate or just getting hung and not processing events in a timely fashion.
Also, make sure you use the right config - there are actual issues with some competitors which are not Wayland architecture issues. For example https://github.com/swaywm/sway/issues/4763
If it's Gnome, the very recent release 45 has improvements running the cursor in a separate thread.
I personally run KDE and agree that you can feel a difference between the X11 and Wayland session but it's not terrible.
But C# isn't ideal for a driver because of the weight of the runtime not because it's hard to save on allocations.
It's been repeatable ever since I bought a Ryzen 7950X at the beginning of the year, that's why I tried using system profiler tools to find the reason but as I have no good experience in this it's difficult to find the root cause.
There are tools available to find the source of the problems, I think I used event tracing as a starting point.
https://learn.microsoft.com/en-us/windows-hardware/drivers/d...
I'd also suggest running https://www.resplendence.com/latencymon to see if it's a specific driver causing the stalls, or if it's random.
[0] https://github.com/google/UIforETW
Don't allocate => don't need to collect.
So I can deny that most development becomes easier with GC. At least if you also intend to actually run the thing. Running Java means forever fighting the GC, needing to do runtime and development to reduce impact of inherent GC problems.
At the end of the day I find languages like Java much harder to reason about and actually a bit harder to write.
https://insanitybit.github.io/2023/06/09/Java-GC-Rust
Move semantics and borrow checker shine when you don't want your data structure to be shared and when you want to control mutation. In some domains, that brings you an unequaled level of safety and Rust is the obvious choice.
Move semantics and borrow checker slow you down when you sharing and mutation are properties you don't care about (or at least not enough to prove them to the compiler). In such cases, I'd rather code in OCaml (or Haskell, or TypeScript, ...)
I hope that one day we'll be able to have the best of both worlds, but I don't see a path forward at the moment.
Smalltalk, Interlip-D, Mesa/Cedar, Oberon, Oberon-2, Active Oberon
Source code is available for some of them, many home made OSes in non GC enabled languages are far from meeting the capabilities of any of those systems.
"Eric Bier Demonstrates Cedar" - Computer History Museum
https://www.youtube.com/watch?v=z_dt7NG38V4
https://people.inf.ethz.ch/wirth/ProjectOberon/Sources/Kerne...
Do these include subsystems with fairly high-performance requirements (GUIs, high-volume network services, etc.)?
Likewise ETHZ IT department during the late 1990's used several Oberon workstations.
GC is easy if you don't have to worry about those problems.
But that doesn't help with today's devices. Even $10 boards are multicore now and come with hundreds megs of RAM.
At least in garbage collected OS design, the lessons from 1970's and 1980's are interesting, but do not directly apply to modern systems.
Don't know exactly what you're asking.
> And why would it be a better idea?
Poorly written device drivers are a significant attack vector. It's one of the reasons Linux is now exploring using Rust for its own device drivers.[0] You may be asking -- why Rust and not some other language? Rust has many of the performance and interoperability advantages of C and C++, but as noted, makes certain classes of memory safety issues impossible. Rust also has significant mindshare among systems programming communities.
[0]: https://rust-for-linux.com
https://github.com/WildernessLabs/Meadow.Foundation
[1] https://github.com/VollRagm/KernelSharp
Indeed pretty much no mainstream language prevents data races at compile time like Rust does
Rust type system doesn't help when the data resides in a shared memory segment accessed by multiple processes.
Of course if you interact with foreign code (including code in other programs, but also code in the same program written in another language), you need unsafe. Or if you write a new synchronization primitive, etc. The unsafe is there to say "I manually checked and this is okay".
What's important is that with Rust, concurrent business logic - in a kernel, things like filesystems and drivers - shouldn't need any unsafe to synchronize correctly. You use unsafe for your lower level infrastructure, but the code that actually does things can be data race free (and thus is easier to modify and assure it's working correctly). And that's incredible.
Also the right way to implement filesystems and drivers in modern OSes should be in userspace drivers, which is the route being taken by Apple, Google and Microsoft across their OSes anyway.
This isn't quite true. You can provide a safe abstraction that involves cross-process locking APIs. https://github.com/elast0ny/shared_memory/blob/HEAD/examples... is an example using a mutex guard.
Rust's type system helps more in some cases than others, but you can get at least some help from it almost all of the time.
[1] https://en.wikipedia.org/wiki/Midori_(operating_system)
My guess is the internal politics would be a bigger problem than any technical issues.
Guess why UWP applications are much slower than regular Win32, app sandboxing and COM reference counting.
But hey, they won.
Is this described anywhere in detail?
"What Really Happened with Vista"
https://hackernoon.com/what-really-happened-with-vista-4ca7f...
"Turning to the past to power Windows’ future: An in-depth look at WinRT"
https://arstechnica.com/features/2012/10/windows-8-and-winrt...
I agree with Microsoft that the best method is probably to run less manufacturer code in the kernel, not to make the kernel accessible more easily. Running a garbage collector in the kernel sounds near impossible to pull off without GC bugs because C# isn't exactly suited for "I want to access some buffer but I can't because it hasn't been paged in and I'm in an interrupt handler".
it would be nice, however .NET Native is deprecated, Native AOT doesn't do UWP, and WinDev is pretty bullish in C++.
Is there a need for it? Printing isn't performance sensitive.
From the point of view of consumer, it is all AOT compiled code.
I suppose you could write these tools in VB.NET or F# if you wanted to as well, but the goal seems to be to avoid memory and security risks in the printer framework by forcing everything into the nice and safe managed environment. Of course developers could always introduce vulnerable code into a managed environment if they wanted to, but most people don't intentionally make their programs more insecure, not even printer manufacurers.
GC and language runtime are still there.
[1]: https://github.com/CosmosOS/Cosmos
I'm kind of kicking myself now that I nuked my LinkedIn in 2014 having 2 degrees from the whole Valley and Mark as 1st. Oh well, there's freedom and agility in relative obscurity. What's that reggae song by Desmond Dekker about it's pointless to talk about how much you did, made, or who you used to know? xD
wat
"true hacker" feels good when describing people at the top of engineering career paths like fellows, but for a CEO I'd rather have someone who's mix of decent tech skills and unparalleled business skills. I've had an opportunity to see companies where people didnt know how to do business and that was tragedy. That was way, way worse than non-technical manager trying to push solutions on ya.
How he is doing from business perspective?
For software company, it could be useful if the CEO knows what software is and the company might find other business models than trending ”enshittification” route.
On the contrast I can show you pure business people failed at the CEO post. E.g. John Sculley ran Apple to the ground.
Thats a very vague job description. Executive's jobs are to make investments that will maximize shareholder return and an executive of an engineering company will only be able to make the best investments if they understand the technology they are selling and their customers. People have been noting how engineers have been running more and more companies, thats because more and more companies rely on technology to drive their growth.
Assuming you can't be among the best of both, which is a natural if possibly wrong assumption, I think it's clear where Gates excelled and that was obviously great for Microsoft.
It feels wrong to me. In fact, I would argue that in tech the opposite is true. Go watch 'Downfall',the documentary on Netflix about Boeing and what happened when they dropped their engineering ethos and let in the "people persons" there.
Or are you staying the best kernel hacker does not necessarily make someone the best manager.
I disagree with the former but agree with the latter. But I also want to add that the best leader for a technology company like Microsoft is not just some guy with an MBA but someone with both deep technical expertise and management/business experience.
The CEO's of Intel, Nvidia, and AMD are all engineers by training.
https://www.nextofwindows.com/tip-having-all-the-sysinternal...
My take from the first book was that he has an extremly black and white view of the world.
Things change over age. He might be no longer such.
Apple apparently used to do something similar, internal Apple Docs were nothing compared to Jonathan Levin's books[1], so Apple would routinely buy those for their OS engineers.
It's pretty interesting to me that companies of that size can't really do these things themselves, despite being in a much better position by having access to the engineers actual source code. These third parties (or at least Levin) had to rely on reverse-engineering to a large degree.
[1] https://newosxbook.com
Back in my Nokia days it wasn't also that easy to get access to this kind of information about Symbian and what not.
I'm having trouble parsing this. What does this mean?
Thank you.
Types like NTSTATUS have a significant amount of documentation attached to it. Unlike C and C++, you can't just assign an integer value to an enum value. I suppose they could've generated a wrapper class and required you to cast every time, but then you'd get code that's 50% .into()s and that would probably add overhead to your driver as well.
As far as I can tell, you never set or alter these enum values, other than maybe the void* for buffer; you only ever read from them. A match {} block should work just fine on NTSTATUS. WDFREQUEST is a handle, so you can't really do anything with it other than maybe swap it out for another handle of the same type.
Timer and SpinLock have been converted into idiomatic Rust objects, wrapping unsafe library calls in their bodies. Other than that, I don't really see how you'd make this code idiomatic without adding a significant performance burden.
I don't think Rust developers would have problems with converting NtStatus to NTSTATUS for the sake of searching documentation.
The first two bits indicate severity, the next bit identifies if it was OS generated or not, then there's an indicator to see if it can be turned into a HRESULT or not, then a bunch of bits indicating the source of the error, and lastly the error code relevant given the previously set bits.
The Windows status codes could be converted, but the status codes generated by other drivers can't be. Even then the conversion would be far from free, you'd need to keep a close eye on your optimisations with every compiler version to keep them free.
That also ignores the possibility programs have to classify their own status codes, so you'd need some kind of "unconvertible" object to indicate that you can't reliably parse the faculty ID, and that you have to treat it like a simple integer.