首先,让我们生成一个压缩tar档案:
from io import BytesIO
from tarfile import TarInfo
import tarfile
with tarfile.open('foo.tgz', mode='w:gz') as archive:
for file_name in range(1000):
file_info = TarInfo(str(file_name))
file_info.size = 100_000
archive.addfile(file_info, fileobj=BytesIO(b'a' * 100_000))
Run Code Online (Sandbox Code Playgroud)
现在,如果我按自然顺序读取存档内容:
import tarfile
with tarfile.open('foo.tgz') as archive:
for file_name in archive.getnames():
archive.extractfile(file_name).read()
Run Code Online (Sandbox Code Playgroud)
并使用命令测量执行时间,我在 PC 上time得到的执行时间不到1 秒:
real 0m0.591s
user 0m0.560s
sys 0m0.011s
Run Code Online (Sandbox Code Playgroud)
但是如果我以相反的顺序读取存档内容:
real 0m0.591s
user 0m0.560s
sys 0m0.011s
Run Code Online (Sandbox Code Playgroud)
现在执行时间约为120 秒:
real 2m3.050s
user 2m0.910s
sys 0m0.059s
Run Code Online (Sandbox Code Playgroud)
这是为什么?我的代码中有什么错误吗?或者是某些tar人的特点?它记录在某处吗?
当我从使用逗号分隔的字符串读取数据时strtok,如果之前读取的值为(空),则正在读取的值会发生移位。
int main(void)
{
char Temp[10] = "1,2,3,,4";
printf("%s\n", strtok(Temp, ","));
printf("%s\n", strtok(NULL, ","));
printf("%s\n", strtok(NULL, ","));
printf("%s\n", strtok(NULL, ","));
printf("%s\n", strtok(NULL, ","));
}
Run Code Online (Sandbox Code Playgroud)
预期输出:
1
2
3
(null)
4
Run Code Online (Sandbox Code Playgroud)
实际输出:
1
2
3
4
(null)
Run Code Online (Sandbox Code Playgroud)
即使有 2 个空格也会发生同样的情况。它只是移动了两次,而不是一次。
我有一个 EDI 文本文件,需要使用 XSLT 对其进行修改。我首先将文本文件转换为 xml,如下所示:
<data>ST^8^347</data>
<data>BAK^00^A^100001396^20240102^^^^20456^a</data>
<data>REF^OQ^5004506</data>
Run Code Online (Sandbox Code Playgroud)
我只需要将上面代码中以 BAK 开头的行的第 8 个位置(即 20456)更新为新值(例如 NEW)。位置由分隔符“^”确定
我的 xslt 代码看起来像但不起作用
<data><xsl:value-of select="replace(.,(tokenize(.,'\\^')[9]),'NEW')"/></data>
Run Code Online (Sandbox Code Playgroud)
预期输出是
<data>BAK^00^A^100001396^20240102^^^^NEW^a</data>
Run Code Online (Sandbox Code Playgroud)
无法使用子字符串,因为每个位置的长度可能不同。我可以在之后使用 8 次子字符串,但如果可能的话,寻找更好的方法。请帮忙。
我偶然发现了虚拟线程和 ConcurrentHashMap 的问题。
正如下面的代码所示,如果您在 中输入锁定computeIfAbsent,VT 可能永远不会唤醒。这实际上取决于 VT 在载体线程上的调度方式,但我可以轻松地重现这一点。
我知道 ConcurrentHashMap 使用synchronized,而 VT 不能很好地使用synchronized,但没有地方说要避免ConcurrentHashMap,因为那会非常令人失望。
class Scratch {
public static void main(String[] args) throws InterruptedException {
var lock = new ReentrantLock();
var map = new ConcurrentHashMap<Integer, String>();
var callables = new ArrayList<Callable<Void>>();
for (int i = 0; i < 32 /* more than threads in FJ pool */; i++) {
callables.add(() -> {
System.out.println("Spawned thread " + Thread.currentThread().threadId());
map.computeIfAbsent(1, k -> {
System.out.println("on lock() …Run Code Online (Sandbox Code Playgroud) 大多数标准库的实现似乎相当简单,无论是从库的其他部分、操作系统系统调用还是裸 C++ 代码来看。更多位(例如<atomic>)可能需要 ASM 实现
但至少有一些位看起来只能根据编译器内在函数来实现(例如,<source_location>当然,std::has_virtual_destructor, 的其他一些部分<type_traits>等)。
最后一组特别令人感兴趣,因为它有点模糊了标准库和语言标准本身之间的界限。这可能是编译器之间库实现可移植性的最重要限制之一。
具体来说,我的问题是:
是否有属于最后一类的零件的明确列表?该标准在谈论这些事情时是否使用了特定术语?
编辑:
作为一点背景信息,这个问题是在关于“引导”编译器和库堆栈是什么样子的思想实验中出现的。这是一个与平台无关的源代码球,只需绝对最少的手动步骤和外部依赖项,即可获得完全符合标准的库和编译器。重点不是性能,而是健壮性、简单性和“相信它实际上是正确的”外部依赖的最小内核。
因此,实践中通常完成的方式,或者标准委员会划分它们的方式,甚至制作快速编译器所需的内容(无论哪种意义上)都不会自动相关。
比方说,我们想要反转一个数组,就像这个函数一样。
对于两个元素的每次交换,都会进行复制构造函数、析构函数和两个复制赋值。
template<class T>
void Reverse(T *arr, int size)
{
T *leftItem = arr;
T *rightItem = &arr[size - 1];
for (int i = 0; i < size / 2; i++, leftItem++, rightItem--)
{
T swap = *leftItem; // Copy constructor
*leftItem = *rightItem; // Copy assignment
*rightItem = swap; // Copy assignment
} // Destructor
}
Run Code Online (Sandbox Code Playgroud)
这看起来很可怕。所以我想出了一个想法,但我不确定它是好还是坏,因为我实际上在这里安全地绕过了所有类型和约定。
但另一方面,它避免了复制操作,根据类型的不同,复制操作可能会很繁重。
template<class T>
void ReverseUsingMemcpy(T *arr, int size)
{
char *swap = new char[sizeof(T)];
T …Run Code Online (Sandbox Code Playgroud) 我正在编写一个 C++ 标记指针。我有一个问题,我用来实现其基本功能的操作是否会导致未定义的行为:
T*,我reinterpret_cast将指针指向 a uintptr_t。这允许我对内存地址执行按位操作,这是添加/提取/检查标签所必需的。reinterpret_cast转换uintptr_t为 a void*(删除标签后)。如果需要指向特定类型的指针,我会将其接受 (void*假设确实是标记指针中保存的类型)。static_castT*T因此,总而言之,我正在对 a 执行以下转换T*:
reinterpret_cast荷兰国际集团T*到auintptr_treinterpret_cast将其uintptr_t转为 a void*,并可能static_cast将其void*转回 a T*。这是否会导致未定义的行为?此外,我是否在预期的用例中正确使用了reinterpret_cast和?static_cast
我想找到以角度 theta 旋转 2D 几何向量的最快方法。
我当前的实现使用旋转矩阵数学并且速度很慢:
Vec2 rotate(Vec2 point, float theta)
{
float c = std::cos(theta);
float s = std::sin(theta);
Vec2 result =
{
point.x * c - point.y * s,
point.x * s + point.y * c
};
return result;
}
Run Code Online (Sandbox Code Playgroud)
是否有更有效的解决方案(我愿意牺牲一些准确性)?
我这里有这个代码。
fn main() {
// Assign a reference of type `i32`. The `&` signifies there
// is a reference being assigned.
let reference = &4;
match reference {
val => println!("Got a value via destructuring: {}", val),
}
match *reference {
val => println!("Got a value via destructuring: {}", val),
}
}
Run Code Online (Sandbox Code Playgroud)
我期待得到这样的结果:
Got a value via destructuring: &4
Got a value via destructuring: 4
Run Code Online (Sandbox Code Playgroud)
但我得到了
Got a value via destructuring: 4
Got a value via destructuring: 4
Run Code Online (Sandbox Code Playgroud)
有人可以解释一下这是怎么回事吗?
std::vector我在尝试用 C++ 中的结果填充 a 时遇到问题std::views::split。具体来说,我可以成功地std::string从 的项构造 a std::ranges::split_view(如下面代码的第一个循环所示),但在尝试使用迭代器std::vector直接创建 a 时遇到困难。
// requires /std:c++20 or later
#include <ranges>
#include <iostream>
#include <vector>
int main()
{
std::string rg{ "1, 2, 3, 1, 2, 3, 4, 5, 6 "};
// Successful construction of std::string from std::ranges::split_view
for (const auto& subrange : rg | std::views::split('3'))
{
std::string value(subrange.begin(), subrange.end());
std::cout << value << '\n';
}
// Issue arises here when attempting to create std::vector
auto parts …Run Code Online (Sandbox Code Playgroud) c++ ×5
performance ×2
c ×1
c++20 ×1
constructor ×1
deadlock ×1
dereference ×1
geometry ×1
java ×1
math ×1
optimization ×1
pointers ×1
python ×1
rust ×1
split ×1
standards ×1
static-cast ×1
std-ranges ×1
strtok ×1
tar ×1
xml ×1
xslt ×1
xslt-2.0 ×1
xslt-3.0 ×1