1ms等于多少s科学计数法(1ms等于多少s怎么算)

ms等于多少s科学计数法(1ms等于多少s怎么算)"

由于我们—人类—正在使用机器为我们工作,我们可以更快地完成日常工作。 从一开始,人类就利用风、水、太阳能等不同的资源来帮助他们的日常生活。

在 19 世纪,巴贝奇建造了自己的计算机—第一台! 他用那台电脑更快地进行计算。 因为大量的工程师都在努力创造更快更好的计算机。 但是有一个问题,摩尔定律。 我们无法为我们的计算机制造更小的部件,因此我们无法通过使用更多、更小的部件来制造更快的计算机。

使我们的计算机和应用程序更快的另一种方法是编程。 我们使用高级语言,如 C#、Java、Typescript、Javascript、PHP 等。

这些语言在处理器方面是“慢”的。 想想看,我们的处理器频率在千兆赫范围内,但在 C# 中最小的可测量时间范围约为毫秒。

1GHz = 1000000000Hz = 1*10^9Hz[Hz] = 1/[s]
1/10^9MHz = 10^-9s1ms = 0.001s = 1*10^-3s1*10^-3s <> 1*10^-9s
What?

如你所见,我们失去了两个时间尺度。在某种程度上,我们可以重新学习低级语言,例如汇编语言、C、C++,但众所周知,这对我们大多数人来说是相当困难的。

我们还能做什么?

作为开发人员,我们正在编写代码,创建自动化工作流程的应用程序。在这些工作流程中,总有一个步骤需要进行长时间的昂贵计算。而且我们必须使用相同的参数多次调用该计算(不止一次)。

在这种情况下,大多数开发人员将要创建缓存或状态管理解决方案。比如我。

状态管理系统可能很好,用于存储单个令牌的预计算值。例如,特定(登录)用户的不同选项、允许的操作、事件日志。

缓存很好,用于存储具有唯一标识符的信息。如果我们按照上面的示例,标识符可以是用户 ID。

但我们能以更便宜的方式做到这一点吗?老实说,是的,我们可以在指定的计算方法上使用记忆。

简而言之,我们需要两件事:

  • 一个可以被记忆的纯函数
  • 缓存,什么可以存储我们的值

鉴于这两个必需的东西,我们可以开始创建我们的记忆逻辑。 让我们从伪代码开始:

function thisFunctionShouldBeMemoized(arg1, arg2, ... argN) {
  keyInCache = generateCacheKeyBasedOnTheArgs();
  valueInCache = cache.get(keyInCache);
  if(!valueInCache) {
    // do the expensive logic here
    // and set the result into the cache
  }
  return cache.get(keyInCache)
}

如您所见,我们尝试从缓存中读取现有值,并在有任何值时返回它。 如果我们没有它,那么我们必须计算它。

让我们稍微修改一下我们的代码,使其更清晰,并摆脱这种类似伪的方法。

const cache = {};function memoize(calculator: Function, arguments: unknown[]) {
  const key = generateKeyFromArguments(arguments);
  const hasValue = Object.keys(cache).includes(key);
  if(!hasValue) {
    cache[key] = calculator.apply(this, arguments);
  }
  return cache[key];
}// Usage
memoize(doSomethingExpensive, [1, 2]);

我已经使用 Typescript 创建了我的演示,但还有很多工作要做。 可以看到,arguments 参数应该是一个数组,这是我们不想做的。 那么我们该如何改进呢?

在 Typescript 中,我们可以创建自定义装饰器。 基本上,装饰器是一个在创建实例时将运行的函数。 通过一个非常简单的提升技巧,我们可以修改我们现有的函数,使其被我们的 memoize 逻辑包装。 这个技巧将使我们的 memoize 装饰器可重用。

让我们创建我们的 memoize 装饰器:

// memoize.tsconst cache = {};export function MemoizeDecorator() {
  return (
    target: any,
    propertyKey: string,
    descriptor: propertyDescriptor) =>
  {
    const lifted = descriptor.value;
    const newFn = function() {
      const args = arguments;
      const cacheKey = JSON.stringify(args);
      if(!Object.keys(cache).includes(cacheKey)) {
        cache[cacheKey] = lifted.apply(this, args);
      }
      return cache[cacheKey];
    }
    descriptor.value = newFn;
  }
}// Usage:
@MemoizeDecorator()
public myExpensiveFunction(arg1: string, arg2: number) {
  // ...
}

我的代码真正做了什么?

我创建了一个工厂装饰器。 这将返回另一个函数。 返回的函数具有三个参数,它们将在运行时给出。 第一个是引用包含给定方法的实例的目标。 propertyKey 是给定方法的名称。 最后一个是描述属性本身的描述符。 它有一个包含方法本身的属性值。 当我们覆盖descriptor.value 属性时,我们真正接触到了函数。

在上面的代码中,我提升了原始函数,用记忆逻辑包装了它,然后将新函数重新分配给原始值。 这样,我可以按预期的方式调用函数,但可以减少运行时间,当函数应该被多次调用时。

让我们编写一个简单的测试代码:

import { MemoizeDecorator } from "./memoize";export class Demo {  @MemoizeDecorator()
  public async aVeryExpensiveFunctionWhichReturn3() {
    return new Promise((resolve) => {
      setTimeout(() => resolve(3), 1000);
    });
  }
}

上面的代码会等待一秒钟,会返回 3。现在我们只需要一件事,测试上面的代码。 为此,我们必须创建 Demo 类的实例,并多次调用 aVeryExpensiveFunctionWhichReturn3() 函数。 在通话期间,我们应该计算经过的时间。

开始了:

async function test() {
  const instance = new Demo();
  const begin1 = new Date().getTime();
  const r1 = await instance.aVeryExpensiveFunctionWhichReturn3();
  console.log("result 1", r1);
  const end1 = new Date().getTime();
  const begin2 = new Date().getTime();
  const r2 = await instance.aVeryExpensiveFunctionWhichReturn3();
  console.log("result 2", r2);
  const end2 = new Date().getTime();
  console.log("time diff 1", (end1 - begin1) / 1000);
  console.log("time diff 2", (end2 - begin2) / 1000);
}

只剩下一件事:运行测试代码,并检查输出。

RESULT:$ npx tsc && node ./src/main.js
result 1 3
result 2 3
time diff 1 1.015
time diff 2 0

我使用 tsc 编译我的代码并使用节点来运行它。 如图所示,第一次运行花费了 1 秒多一点,因为记忆逻辑本身有一些延迟。 但是对于第二个循环,它使用了不到一毫秒,这意味着代码从缓存中读取了预先计算的值。

创业项目群,学习操作 18个小项目,添加 微信:sum5080  备注:小项目

本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至 3300536702@qq.com 举报,一经查实,本站将立刻删除。
如若转载,请注明出处:https://www.yxfxq.cn/1946.html